From 4f22877fbf1f25c76b54b281fcfabfce3a4ca6cd Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Mon, 11 Jul 2011 10:36:27 +0200 Subject: [PATCH] Debug & evaluate third party code. --- .../Debugger.AddIn/Debugger.AddIn.csproj | 8 + .../Debugger.AddIn/Service/WindowsDebugger.cs | 186 +- .../Debugger.AddIn/Tooltips/DebuggerPopup.cs | 2 +- .../Tooltips/DebuggerTooltipControl.xaml.cs | 22 +- .../TreeModel/ExpressionNode.cs | 13 + .../Debugger.Core/Interop/CorDebug.cs | 8 + .../Debugger/Debugger.Core/ManagedCallback.cs | 11 + .../Debugger.Core/MetaData/DebugMethodInfo.cs | 56 +- src/AddIns/Debugger/Debugger.Core/Module.cs | 93 +- .../Visitors/ExpressionEvaluator.cs | 339 +- src/AddIns/Debugger/Debugger.Core/Options.cs | 7 +- src/AddIns/Debugger/Debugger.Core/Process.cs | 33 +- .../Debugger.Core/SourcecodeSegment.cs | 61 +- .../Debugger/Debugger.Core/StackFrame.cs | 34 +- .../AvalonEdit.AddIn/Src/CodeEditor.cs | 11 +- .../AvalonEdit.AddIn/Src/IconBarManager.cs | 2 +- .../AvalonEdit.AddIn/Src/IconBarMargin.cs | 4 +- .../AvalonEdit.AddIn/Src/TextMarkerService.cs | 8 +- .../ILSpyAddIn/ILSpyAddIn.csproj | 4 + .../NavigateToDecompiledEntityService.cs | 26 +- .../ILSpyAddIn/ViewContent/CodeView.cs | 222 +- .../ViewContent/DecompiledViewContent.cs | 76 + .../ICSharpCode.Decompiler/Ast/AstBuilder.cs | 542 +- .../Ast/AstMethodBodyBuilder.cs | 198 +- .../Ast/CecilTypeResolveContext.cs | 37 +- .../Ast/CommentStatement.cs | 19 +- .../Ast/DecompilerContext.cs | 19 +- .../Ast/NRefactoryExtensions.cs | 19 +- .../Ast/NameVariables.cs | 60 +- .../Ast/TextOutputFormatter.cs | 66 +- .../Ast/Transforms/AddCheckedBlocks.cs | 19 +- .../Ast/Transforms/CombineQueryExpressions.cs | 19 +- .../Ast/Transforms/ContextTrackingVisitor.cs | 19 +- .../ConvertConstructorCallIntoInitializer.cs | 75 +- .../Transforms/DecimalConstantTransform.cs | 58 + .../Ast/Transforms/DeclareVariables.cs | 19 +- .../Ast/Transforms/DelegateConstruction.cs | 66 +- .../Transforms/IntroduceExtensionMethods.cs | 19 +- .../Transforms/IntroduceQueryExpressions.cs | 19 +- .../Ast/Transforms/IntroduceUnsafeModifier.cs | 19 +- .../Transforms/IntroduceUsingDeclarations.cs | 298 +- .../Transforms/PatternStatementTransform.cs | 299 +- .../Ast/Transforms/PushNegation.cs | 20 +- .../ReplaceMethodCallsWithOperators.cs | 29 +- .../Ast/Transforms/TransformationPipeline.cs | 20 +- .../Ast/TypesHierarchyHelpers.cs | 331 +- .../ICSharpCode.Decompiler/CecilExtensions.cs | 10 +- .../ICSharpCode.Decompiler/CodeMappings.cs | 346 + .../DecompilerException.cs | 19 +- .../DecompilerSettings.cs | 64 +- .../Disassembler/DisassemblerHelpers.cs | 253 +- .../Disassembler/ILStructure.cs | 6 +- .../Disassembler/MethodBodyDisassembler.cs | 95 +- .../Disassembler/ReflectionDisassembler.cs | 742 +- .../ICSharpCode.Decompiler.csproj | 6 +- .../ILAst/DefaultDictionary.cs | 23 +- .../ILAst/GotoRemoval.cs | 49 +- .../ILAst/ILAstBuilder.cs | 75 +- .../ILAst/ILAstOptimizer.cs | 212 +- .../ILAst/ILAstTypes.cs | 52 +- .../ICSharpCode.Decompiler/ILAst/ILCodes.cs | 42 +- .../ILAst/ILInlining.cs | 188 +- .../ILAst/InitializerPeepholeTransforms.cs | 478 +- .../ILAst/LoopsAndConditions.cs | 23 +- .../ILAst/PatternMatching.cs | 19 +- .../ILAst/PeepholeTransform.cs | 131 +- .../ILAst/SimpleControlFlow.cs | 126 +- .../ILAst/TypeAnalysis.cs | 226 +- .../ILAst/YieldReturnDecompiler.cs | 21 +- .../ICSharpCode.Decompiler/ITextOutput.cs | 3 + .../ICSharpCode.Decompiler/PlainTextOutput.cs | 17 + .../Properties/AssemblyInfo.cs | 2 + .../Properties/AssemblyInfo.template.cs | 27 + .../ReferenceResolvingException.cs | 68 + .../Tests/BooleanConsumedAsInteger.il | 59 + .../Tests/CallOverloadedMethod.cs | 52 + .../Tests/CheckedUnchecked.cs | 66 + .../Tests/CodeSampleFileParser.cs | 132 + .../Tests/CustomAttributes.code.cs | 41 + .../CustomAttributes/CustomAttributeTests.cs | 30 + .../S_AssemblyCustomAttribute.cs | 6 + .../S_CustomAttributeSamples.cs | 480 + .../CustomAttributes/S_CustomAttributes.cs | 64 + .../Tests/CustomShortCircuitOperators.cs | 90 + .../Tests/DecompilerTestBase.cs | 93 + .../Tests/DelegateConstruction.cs | 189 + .../Tests/ExceptionHandling.cs | 128 + .../ICSharpCode.Decompiler/Tests/Generics.cs | 105 + .../Tests/Helpers/CodeAssert.cs | 110 + .../Tests/Helpers/RemoveCompilerAttribute.cs | 38 + .../Tests/ICSharpCode.Decompiler.Tests.csproj | 113 + .../Tests/IncrementDecrement.cs | 254 + .../Tests/InitializerTests.cs | 869 + .../ICSharpCode.Decompiler/Tests/Loops.cs | 74 + .../Tests/MultidimensionalArray.cs | 58 + .../ICSharpCode.Decompiler/Tests/PInvoke.cs | 87 + .../Tests/PropertiesAndEvents.cs | 81 + .../Tests/QueryExpressions.cs | 164 + .../Tests/StackTests/StackTests.exe | Bin 0 -> 2048 bytes .../Tests/StackTests/StackTests.il | 132 + .../ICSharpCode.Decompiler/Tests/Switch.cs | 77 + .../Tests/TestRunner.cs | 185 + .../Tests/TypeAnalysisTests.cs | 109 + .../Tests/Types/EnumTests.cs | 18 + .../Tests/Types/S_EnumSamples.cs | 114 + .../Tests/Types/S_TypeDeclarations.cs | 17 + .../Tests/Types/S_TypeMemberDeclarations.cs | 1121 + .../Tests/Types/TypeTests.cs | 18 + .../Tests/UndocumentedExpressions.cs | 41 + .../Tests/UnsafeCode.cs | 114 + .../Tests/ValueTypes.cs | 162 + .../Tests/YieldReturn.cs | 148 + .../Tests/nunit.framework.dll | Bin 0 -> 135168 bytes .../Tests/packages.config | 4 + .../ICSharpCode.NRefactory/.gitignore | 3 + .../CSharp/Analysis/ControlFlow.cs | 7 +- .../Analysis/DefiniteAssignmentAnalysis.cs | 26 +- .../CSharp/Analysis/MinimalResolveContext.cs | 21 +- .../CSharp/Ast/AstNode.cs | 523 +- .../CSharp/Ast/CSharpTokenNode.cs | 11 +- .../CSharp/Ast/CSharpUtil.cs | 95 + .../CSharp/Ast/CompilationUnit.cs | 78 +- .../CSharp/Ast/ComposedType.cs | 4 +- .../CSharp/Ast/ErrorNode.cs | 79 + .../CSharp/Ast/Expressions/EmptyExpression.cs | 13 +- .../Ast/Expressions/IdentifierExpression.cs | 4 +- .../Expressions/MemberReferenceExpression.cs | 13 +- .../Expressions/NamedArgumentExpression.cs | 11 +- .../Expressions/PointerReferenceExpression.cs | 4 +- .../Ast/Expressions/PrimitiveExpression.cs | 31 +- .../CSharp/Ast/Expressions/QueryExpression.cs | 10 +- .../CSharp/Ast/GeneralScope/Attribute.cs | 21 +- .../CSharp/Ast/GeneralScope/Comment.cs | 13 +- .../CSharp/Ast/GeneralScope/Constraint.cs | 4 +- .../Ast/GeneralScope/DelegateDeclaration.cs | 13 +- .../GeneralScope/ExternAliasDeclaration.cs | 2 +- .../Ast/GeneralScope/NamespaceDeclaration.cs | 4 +- .../Ast/GeneralScope/TypeDeclaration.cs | 13 +- .../GeneralScope/TypeParameterDeclaration.cs | 11 +- .../Ast/GeneralScope/UsingAliasDeclaration.cs | 8 +- .../CSharp/Ast/IRelocatable.cs | 35 + .../CSharp/Ast/Identifier.cs | 79 +- .../CSharp/Ast/MemberType.cs | 36 +- .../CSharp/Ast/NotImplementedAstVisitor.cs | 560 + .../CSharp/Ast/ObservableAstVisitor.cs | 1141 + .../CSharp/Ast/PrimitiveType.cs | 10 +- .../ICSharpCode.NRefactory/CSharp/Ast/Role.cs | 8 +- .../CSharp/Ast/SimpleType.cs | 27 +- .../CSharp/Ast/Statements/EmptyStatement.cs | 11 +- .../CSharp/Ast/Statements/ForeachStatement.cs | 13 +- .../CSharp/Ast/Statements/GotoStatement.cs | 4 +- .../CSharp/Ast/Statements/LabelStatement.cs | 4 +- .../CSharp/Ast/Statements/SwitchStatement.cs | 9 + .../Ast/Statements/TryCatchStatement.cs | 13 +- .../VariableDeclarationStatement.cs | 5 + .../CSharp/Ast/TypeMembers/AttributedNode.cs | 9 +- .../Ast/TypeMembers/ConstructorDeclaration.cs | 5 + .../Ast/TypeMembers/DestructorDeclaration.cs | 5 + .../Ast/TypeMembers/EnumMemberDeclaration.cs | 13 +- .../TypeMembers/FixedVariableInitializer.cs | 15 +- .../Ast/TypeMembers/MemberDeclaration.cs | 13 +- .../Ast/TypeMembers/OperatorDeclaration.cs | 23 +- .../Ast/TypeMembers/ParameterDeclaration.cs | 13 +- .../Ast/TypeMembers/VariableInitializer.cs | 13 +- .../CSharp/Formatter/AstFormattingVisitor.cs | 1608 + .../CSharp/Formatter/Change.cs | 72 + .../CSharp/Formatter/ITextEditorAdapter.cs | 83 + .../CSharp/Formatter/Indent.cs | 89 + .../CSharp/OutputVisitor/OutputVisitor.cs | 2625 +- .../TextWriterOutputFormatter.cs | 76 +- .../CSharp/Parser/CSharpParser.cs | 3155 ++ .../CSharp/Parser/ParsedFile.cs | 59 +- .../CSharp/Parser/TypeSystemConvertVisitor.cs | 360 +- .../CSharp/Parser/mcs/AssemblyInfo.cs | 43 + .../CSharp/Parser/mcs/ChangeLog | 34100 ++++++++++++++++ .../CSharp/Parser/mcs/CryptoConvert.cs | 754 + .../CSharp/Parser/mcs/Makefile | 126 + .../CSharp/Parser/mcs/MonoSymbolFile.cs | 723 + .../CSharp/Parser/mcs/MonoSymbolTable.cs | 1376 + .../CSharp/Parser/mcs/MonoSymbolWriter.cs | 403 + .../CSharp/Parser/mcs/NOTES | 38 + .../CSharp/Parser/mcs/OPTIMIZE | 26 + .../CSharp/Parser/mcs/OTODO | 239 + .../CSharp/Parser/mcs/PLAN | 66 + .../CSharp/Parser/mcs/README | 72 + .../CSharp/Parser/mcs/TODO | 223 + .../CSharp/Parser/mcs/anonymous.cs | 2038 + .../CSharp/Parser/mcs/argument.cs | 551 + .../CSharp/Parser/mcs/assembly.cs | 1183 + .../CSharp/Parser/mcs/assign.cs | 786 + .../CSharp/Parser/mcs/async.cs | 614 + .../CSharp/Parser/mcs/attribute.cs | 2008 + .../CSharp/Parser/mcs/cfold.cs | 1173 + .../CSharp/Parser/mcs/class.cs | 3622 ++ .../CSharp/Parser/mcs/codegen.cs | 728 + .../CSharp/Parser/mcs/compiler.doc | 116 + .../CSharp/Parser/mcs/complete.cs | 200 + .../CSharp/Parser/mcs/const.cs | 237 + .../CSharp/Parser/mcs/constant.cs | 2232 + .../CSharp/Parser/mcs/context.cs | 741 + .../CSharp/Parser/mcs/convert.cs | 2150 + .../CSharp/Parser/mcs/cs-parser.cs | 13108 ++++++ .../CSharp/Parser/mcs/cs-parser.jay | 7108 ++++ .../CSharp/Parser/mcs/cs-tokenizer.cs | 3584 ++ .../CSharp/Parser/mcs/decl.cs | 1557 + .../CSharp/Parser/mcs/delegate.cs | 774 + .../CSharp/Parser/mcs/dmcs.csproj | 154 + .../CSharp/Parser/mcs/dmcs.exe.config | 6 + .../CSharp/Parser/mcs/dmcs.exe.sources | 55 + .../CSharp/Parser/mcs/dmcs.sln | 20 + .../CSharp/Parser/mcs/doc-bootstrap.cs | 59 + .../CSharp/Parser/mcs/doc.cs | 645 + .../CSharp/Parser/mcs/driver.cs | 472 + .../CSharp/Parser/mcs/dynamic.cs | 965 + .../CSharp/Parser/mcs/ecore.cs | 5920 +++ .../CSharp/Parser/mcs/enum.cs | 322 + .../CSharp/Parser/mcs/eval.cs | 1128 + .../CSharp/Parser/mcs/expression.cs | 9943 +++++ .../CSharp/Parser/mcs/field.cs | 690 + .../CSharp/Parser/mcs/flowanalysis.cs | 1765 + .../CSharp/Parser/mcs/generic.cs | 3407 ++ .../CSharp/Parser/mcs/gmcs.csproj | 111 + .../CSharp/Parser/mcs/gmcs.exe.config | 14 + .../CSharp/Parser/mcs/gmcs.exe.sources | 56 + .../CSharp/Parser/mcs/gmcs.sln | 20 + .../CSharp/Parser/mcs/gmcs.userprefs | 23 + .../CSharp/Parser/mcs/gmcs2.csproj | 29 + .../CSharp/Parser/mcs/hosting.cs | 0 .../CSharp/Parser/mcs/import.cs | 2096 + .../CSharp/Parser/mcs/iterators.cs | 1057 + .../CSharp/Parser/mcs/lambda.cs | 229 + .../CSharp/Parser/mcs/lambda.todo | 24 + .../CSharp/Parser/mcs/linq.cs | 892 + .../CSharp/Parser/mcs/literal.cs | 282 + .../CSharp/Parser/mcs/location.cs | 912 + .../CSharp/Parser/mcs/membercache.cs | 1409 + .../CSharp/Parser/mcs/method.cs | 2563 +- .../CSharp/Parser/mcs/modifiers.cs | 281 + .../CSharp/Parser/mcs/namespace.cs | 1227 + .../CSharp/Parser/mcs/nullable.cs | 1292 + .../CSharp/Parser/mcs/outline.cs | 1024 + .../CSharp/Parser/mcs/parameter.cs | 1306 + .../CSharp/Parser/mcs/pending.cs | 641 + .../CSharp/Parser/mcs/property.cs | 1675 + .../CSharp/Parser/mcs/reflection.cs | 557 + .../CSharp/Parser/mcs/repl.txt | 168 + .../CSharp/Parser/mcs/report.cs | 1221 + .../CSharp/Parser/mcs/rootcontext.cs | 1462 + .../CSharp/Parser/mcs/roottypes.cs | 621 + .../CSharp/Parser/mcs/smcs.exe.sources | 53 + .../CSharp/Parser/mcs/smcs.exe.sources-xml | 384 + .../CSharp/Parser/mcs/statement.cs | 5969 +++ .../CSharp/Parser/mcs/support.cs | 317 + .../CSharp/Parser/mcs/symbolwriter.cs | 245 + .../CSharp/Parser/mcs/typemanager.cs | 980 + .../CSharp/Parser/mcs/typespec.cs | 1759 + .../CSharp/Parser/mcs/visit.cs | 630 + .../CSharp/Parser/mcs/y.output | 31920 +++++++++++++++ .../CSharp/Refactoring/Action.cs | 55 + .../ContextAction/AddAnotherAccessor.cs | 89 + .../ContextAction/CheckIfParameterIsNull.cs | 112 + .../ContextAction/ConvertDecToHex.cs | 52 + .../ContextAction/ConvertForeachToFor.cs | 95 + .../ContextAction/ConvertHexToDec.cs | 52 + .../ContextAction/CreateBackingStore.cs | 73 + .../ContextAction/CreateEventInvocator.cs | 109 + .../Refactoring/ContextAction/CreateField.cs | 77 + .../ContextAction/CreateLocalVariable.cs | 129 + .../ContextAction/CreateProperty.cs | 66 + .../ContextAction/FlipOperatorArguments.cs | 59 + .../ContextAction/GenerateGetter.cs | 95 + .../ContextAction/GenerateSwitchLabels.cs | 88 + .../InsertAnonymousMethodSignature.cs | 94 + .../ContextAction/IntroduceFormatItem.cs | 100 + .../Refactoring/ContextAction/InvertIf.cs | 61 + .../ContextAction/RemoveBackingStore.cs | 123 + .../Refactoring/ContextAction/RemoveBraces.cs | 61 + .../ContextAction/ReplaceEmptyString.cs | 53 + .../SplitDeclarationAndAssignment.cs | 74 + .../Refactoring/ContextAction/SplitString.cs | 55 + .../ContextAction/UseExplicitType.cs | 67 + .../ContextAction/UseVarKeyword.cs | 56 + .../CSharp/Refactoring/CreateLinkAction.cs | 44 + .../CSharp/Refactoring/FormatTextAction.cs | 39 + .../CSharp/Refactoring/IActionFactory.cs | 75 + .../CSharp/Refactoring/IContextAction.cs | 36 + .../CSharp/Refactoring/NodeOutputAction.cs | 136 + .../CSharp/Refactoring/NodeSelectionAction.cs | 40 + .../CSharp/Refactoring/RefactoringContext.cs | 141 + .../CSharp/Refactoring/Script.cs | 180 + .../StringBuilderOutputFormatter.cs | 158 + .../CSharp/Refactoring/TextReplaceAction.cs | 134 + .../Refactoring/TypeSystemAstBuilder.cs | 218 + .../CSharp/Resolver/CSharpAttribute.cs | 144 + .../CSharp/Resolver/CSharpResolver.cs | 160 +- .../CSharp/Resolver/ConstantValues.cs | 638 + .../CSharp/Resolver/Conversions.cs | 100 +- .../CSharp/Resolver/MapTypeIntoNewContext.cs | 49 + .../CSharp/Resolver/MemberLookup.cs | 25 +- .../MemberTypeOrNamespaceReference.cs | 11 + .../CSharp/Resolver/OverloadResolution.cs | 4 +- .../CSharp/Resolver/ResolveVisitor.cs | 436 +- .../SimpleTypeOrNamespaceReference.cs | 11 + .../CSharp/Resolver/TypeInference.cs | 25 +- .../Documentation/XmlDocumentationProvider.cs | 2 +- .../ICSharpCode.NRefactory.csproj | 128 +- .../PatternMatching/INode.cs | 4 +- .../PatternMatching/OptionalNode.cs | 2 +- .../PatternMatching/Pattern.cs | 6 +- .../PatternMatching/Repeat.cs | 2 +- .../Properties/AssemblyInfo.cs | 20 +- .../SupportedLanguage.cs | 12 + .../TypeSystem/ArrayType.cs | 7 +- .../TypeSystem/ByReferenceType.cs | 5 +- .../TypeSystem/CecilLoader.cs | 118 +- .../TypeSystem/DomRegion.cs | 50 +- .../TypeSystem/Error.cs | 135 + .../TypeSystem/ExtensionMethods.cs | 59 +- .../TypeSystem/IAnnotatable.cs | 216 + .../TypeSystem/IAttribute.cs | 30 +- .../TypeSystem/IEntity.cs | 48 + .../TypeSystem/IParsedFile.cs | 63 + .../TypeSystem/IProjectContent.cs | 21 +- .../TypeSystem/IType.cs | 37 +- .../TypeSystem/ITypeDefinition.cs | 6 +- .../TypeSystem/ITypeParameter.cs | 10 +- .../TypeSystem/ITypeResolveContext.cs | 28 +- .../TypeSystem/IVariable.cs | 5 + .../Implementation/AbstractFreezable.cs | 12 +- .../Implementation/AbstractMember.cs | 24 + .../TypeSystem/Implementation/AbstractType.cs | 11 +- .../CompositeTypeResolveContext.cs | 34 +- .../Implementation/DefaultAttribute.cs | 10 + .../TypeSystem/Implementation/DefaultField.cs | 6 + .../Implementation/DefaultMethod.cs | 6 +- .../Implementation/DefaultParameter.cs | 6 + .../Implementation/DefaultTypeDefinition.cs | 102 +- .../Implementation/DefaultTypeParameter.cs | 140 +- .../Implementation/GetClassTypeReference.cs | 2 +- .../Implementation/NestedTypeReference.cs | 2 +- .../Implementation/ProxyTypeResolveContext.cs | 16 +- .../Implementation/SimpleProjectContent.cs | 75 +- .../Implementation/SpecializedMethod.cs | 9 +- .../Implementation/SpecializedProperty.cs | 6 +- .../SubstitutionTypeReference.cs | 31 + .../TypeSystem/Implementation/TypeStorage.cs | 93 +- .../TypeSystem/IntersectionType.cs | 10 +- .../TypeSystem/NullableType.cs | 2 +- .../TypeSystem/ParameterizedType.cs | 69 +- .../TypeSystem/PointerType.cs | 5 +- .../TypeSystem/ReflectionHelper.cs | 22 +- .../TypeSystem/SharedTypes.cs | 15 +- .../ICSharpCode.NRefactory/Utils/Platform.cs | 25 + .../Project/Src/Bookmarks/IBookmarkMargin.cs | 2 + .../Project/Src/Bookmarks/Pad/BookmarkPad.cs | 3 +- .../Services/Debugger/CurrentLineBookmark.cs | 14 +- .../Src/Services/Debugger/DebuggerService.cs | 31 +- .../NavigationService/NavigationService.cs | 69 +- 358 files changed, 198748 insertions(+), 3210 deletions(-) create mode 100644 src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/ReferenceResolvingException.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Generics.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/InitializerTests.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Loops.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/PInvoke.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/QueryExpressions.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/StackTests/StackTests.exe create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/StackTests/StackTests.il create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Switch.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/TestRunner.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/UnsafeCode.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/YieldReturn.cs create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/nunit.framework.dll create mode 100644 src/Libraries/ICSharpCode.Decompiler/Tests/packages.config create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/.gitignore create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/NotImplementedAstVisitor.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Change.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/SupportedLanguage.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs create mode 100644 src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Utils/Platform.cs diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index ddced0ecf8..292319a323 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -360,6 +360,14 @@ ICSharpCode.AvalonEdit False + + {984CC812-9470-4A13-AFF9-CC44068D666C} + ICSharpCode.Decompiler + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + {2748AD25-9C63-4E12-877B-4DCE96FBED54} ICSharpCode.SharpDevelop diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs index 1d0aec5605..4a72a07811 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs @@ -2,6 +2,7 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; +using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; @@ -15,8 +16,12 @@ using Debugger; using Debugger.AddIn.Tooltips; using Debugger.AddIn.TreeModel; using Debugger.Interop.CorPublish; +using Debugger.MetaData; using ICSharpCode.Core; +using ICSharpCode.Core.Services; using ICSharpCode.Core.WinForms; +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.ILAst; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Visitors; @@ -25,6 +30,7 @@ using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui.OptionPanels; using ICSharpCode.SharpDevelop.Project; +using Mono.Cecil; using Process = Debugger.Process; namespace ICSharpCode.SharpDevelop.Services @@ -81,6 +87,18 @@ namespace ICSharpCode.SharpDevelop.Services set; } + public bool IsInExternalCode { + get { + if (debuggedProcess == null) + return true; + + if(debuggedProcess.SelectedThread == null) + return true; + + return debuggedProcess.SelectedStackFrame.ToString() != debuggedProcess.SelectedThread.MostRecentStackFrame.ToString(); + } + } + protected virtual void OnProcessSelected(ProcessEventArgs e) { if (ProcessSelected != null) { @@ -210,6 +228,8 @@ namespace ICSharpCode.SharpDevelop.Services DebugStarting(this, EventArgs.Empty); try { + // set the JIT flag for evaluating optimized code + Process.DebugMode = DebugModeFlag.Debug; Process process = debugger.Start(processStartInfo.FileName, processStartInfo.WorkingDirectory, processStartInfo.Arguments); @@ -271,6 +291,8 @@ namespace ICSharpCode.SharpDevelop.Services DebugStarting(this, EventArgs.Empty); try { + // set the JIT flag for evaluating optimized code + Process.DebugMode = DebugModeFlag.Debug; Process process = debugger.Attach(existingProcess); attached = true; SelectProcess(process); @@ -444,16 +466,56 @@ namespace ICSharpCode.SharpDevelop.Services // Stepping: + SourceCodeMapping GetCurrentCodeMapping(out bool isMatch) + { + DecompileInformation debugInformation = (DecompileInformation)DebuggerService.ExternalDebugInformation; + isMatch = false; + + if (debugInformation == null) + return null; + var frame = debuggedProcess.SelectedThread.MostRecentStackFrame; + int token = frame.MethodInfo.MetadataToken; + + // get the mapped instruction from the current line marker or the next one + if (!debugInformation.CodeMappings.ContainsKey(token)) + return null; + var mappings = (List)debugInformation.CodeMappings[token]; + return mappings.GetInstructionByTokenAndOffset(token, frame.IP, out isMatch); + } + + Debugger.StackFrame GetStackFrame() + { + bool isMatch; + Debugger.StackFrame frame = debuggedProcess.SelectedThread.MostRecentStackFrame; + var map = GetCurrentCodeMapping(out isMatch); + if (map == null) { + frame = debuggedProcess.SelectedThread.MostRecentStackFrame; + frame.ILRanges = new [] { 0, 1 }; + } else { + frame.SourceCodeLine = map.SourceCodeLine; + frame.ILRanges = map.ToArray(isMatch); + } + + return frame; + } + public void StepInto() { if (!IsDebugging) { MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepInto}"); return; } - if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) { + + var frame = debuggedProcess.SelectedStackFrame ?? debuggedProcess.SelectedThread.MostRecentStackFrame; + if (frame == null || debuggedProcess.IsRunning) { MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}"); } else { - debuggedProcess.SelectedStackFrame.AsyncStepInto(); + if (IsInExternalCode) { + // get frame info from external code mappings + frame = GetStackFrame(); + } + + frame.AsyncStepInto(); } } @@ -463,10 +525,17 @@ namespace ICSharpCode.SharpDevelop.Services MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOver}"); return; } - if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) { + + var frame = debuggedProcess.SelectedStackFrame ?? debuggedProcess.SelectedThread.MostRecentStackFrame; + if (frame == null || debuggedProcess.IsRunning) { MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepOver}"); } else { - debuggedProcess.SelectedStackFrame.AsyncStepOver(); + if (IsInExternalCode) { + // get frame info from external code mappings + frame = GetStackFrame(); + } + + frame.AsyncStepOver(); } } @@ -476,10 +545,17 @@ namespace ICSharpCode.SharpDevelop.Services MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOut}"); return; } - if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) { - MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepOut}"); + + var frame = debuggedProcess.SelectedStackFrame ?? debuggedProcess.SelectedThread.MostRecentStackFrame; + if (frame == null || debuggedProcess.IsRunning) { + MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}"); } else { - debuggedProcess.SelectedStackFrame.AsyncStepOut(); + if (IsInExternalCode) { + // get frame info from external code mappings + frame = GetStackFrame(); + } + + frame.AsyncStepOut(); } } @@ -505,9 +581,19 @@ namespace ICSharpCode.SharpDevelop.Services if (!CanEvaluate) { return null; } - return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, debuggedProcess.SelectedStackFrame); + + Debugger.StackFrame stackFrame = debuggedProcess.SelectedThread.MostRecentStackFrame; + + try { + object data = GetLocalVariableIndex(stackFrame, variableName); + + // evaluate expression + return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, stackFrame, data); + } catch { + throw; + } } - + /// /// Gets Expression for given variable. Can throw GetValueException. /// Thrown when getting expression fails. Exception message explains reason. @@ -550,7 +636,8 @@ namespace ICSharpCode.SharpDevelop.Services bool CanEvaluate { get { - return debuggedProcess != null && !debuggedProcess.IsRunning && debuggedProcess.SelectedStackFrame != null; + return debuggedProcess != null && !debuggedProcess.IsRunning && + (debuggedProcess.SelectedStackFrame != null || debuggedProcess.SelectedThread.MostRecentStackFrame != null); } } @@ -566,7 +653,7 @@ namespace ICSharpCode.SharpDevelop.Services var image = ExpressionNode.GetImageForLocalVariable(out imageName); ExpressionNode expressionNode = new ExpressionNode(image, variableName, tooltipExpression); expressionNode.ImageName = imageName; - return new DebuggerTooltipControl(logicalPosition, expressionNode); + return new DebuggerTooltipControl(logicalPosition, expressionNode) { ShowPins = !IsInExternalCode }; } catch (GetValueException) { return null; } @@ -885,15 +972,64 @@ namespace ICSharpCode.SharpDevelop.Services public void JumpToCurrentLine() { + if (debuggedProcess == null || debuggedProcess.SelectedThread == null) + return; + WorkbenchSingleton.MainWindow.Activate(); DebuggerService.RemoveCurrentLineMarker(); - if (debuggedProcess != null) { + + if (!IsInExternalCode) { SourcecodeSegment nextStatement = debuggedProcess.NextStatement; if (nextStatement != null) { DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn); } + } else { + DecompileInformation externalData = (DecompileInformation)DebuggerService.ExternalDebugInformation; + + // use most recent stack frame because we don't have the symbols + var frame = debuggedProcess.SelectedThread.MostRecentStackFrame; + + if (frame == null) + return; + + int token = frame.MethodInfo.MetadataToken; + int ilOffset = frame.IP; + int line; + MemberReference memberReference; + + if (externalData != null && externalData.CodeMappings.ContainsKey(token)) { + var mappings = externalData.CodeMappings[token]; + if (mappings.GetInstructionByTokenAndOffset(token, ilOffset, out memberReference, out line)) { + DebuggerService.DebugStepInformation = null; // we do not need to step into/out + + // update marker + var debugType = (DebugType)frame.MethodInfo.DeclaringType; + string title = "[" + debugType.Name + "]"; + foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType()) { + if (string.Equals(vc.TitleName, title, StringComparison.OrdinalIgnoreCase)) { + CurrentLineBookmark.SetPosition(vc, line, 0, line, 0); + vc.WorkbenchWindow.SelectWindow(); + return; + } + } + // the decompiled content was closed so we have to recreate it + StepIntoUnknownFrame(frame, token, ilOffset); + } else { + StepIntoUnknownFrame(frame, token, ilOffset); + } + } else { + StepIntoUnknownFrame(frame, token, ilOffset); + } } } + + void StepIntoUnknownFrame(Debugger.StackFrame frame, int token, int ilOffset) + { + var debugType = (DebugType)frame.MethodInfo.DeclaringType; + string fullName = debugType.FullNameWithoutGenericArguments; + DebuggerService.DebugStepInformation = Tuple.Create(token, ilOffset); + NavigationService.NavigateTo(debugType.DebugModule.FullPath, debugType.FullNameWithoutGenericArguments, string.Empty); + } StopAttachedProcessDialogResult ShowStopAttachedProcessDialog() { @@ -912,5 +1048,31 @@ namespace ICSharpCode.SharpDevelop.Services .Where(p => e.Item.Name.IndexOf(p.Name) >= 0) .ForEach(p => e.Item.LoadSymbolsFromDisk(new []{ Path.GetDirectoryName(p.OutputAssemblyFullPath) })); } + + public static object GetLocalVariableIndex(Debugger.StackFrame stackFrame, string variableName) + { + // get the target name + int token = stackFrame.MethodInfo.MetadataToken; + int index = variableName.IndexOf('.'); + string targetName = variableName; + if (index != -1) { + targetName = variableName.Substring(0, index); + } + + // get local variable index and store it in UserData property - used in evaluator + object data = null; + IEnumerable list; + DecompileInformation externalData = (DecompileInformation)DebuggerService.ExternalDebugInformation; + if (externalData == null) + return null; + + if (externalData.LocalVariables.TryGetValue(token, out list)) { + var variable = list.FirstOrDefault(v => v.Name == targetName); + if (variable != null && variable.OriginalVariable != null) { + data = new[] { variable.OriginalVariable.Index }; + } + } + return data; + } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs index 87529f37e1..f6132f6ee1 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs @@ -23,7 +23,7 @@ namespace Debugger.AddIn.Tooltips public DebuggerPopup(DebuggerTooltipControl parentControl, Location logicalPosition, bool showPins = true) { - this.contentControl = new DebuggerTooltipControl(parentControl, logicalPosition, showPins); + this.contentControl = new DebuggerTooltipControl(parentControl, logicalPosition) { ShowPins = showPins }; this.contentControl.containingPopup = this; this.Child = this.contentControl; this.IsLeaf = false; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs index f5463752d3..85646c668c 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs @@ -58,11 +58,10 @@ namespace Debugger.AddIn.Tooltips this.itemsSource = nodes; } - public DebuggerTooltipControl(DebuggerTooltipControl parentControl, Location logicalPosition, bool showPins = true) + public DebuggerTooltipControl(DebuggerTooltipControl parentControl, Location logicalPosition) : this(logicalPosition) { this.parentControl = parentControl; - this.showPins = showPins; } private void OnLoaded(object sender, RoutedEventArgs e) @@ -82,6 +81,11 @@ namespace Debugger.AddIn.Tooltips } } + public bool ShowPins { + get { return showPins; } + set { showPins = value; } + } + public IEnumerable ItemsSource { get { return this.itemsSource; } } @@ -95,8 +99,16 @@ namespace Debugger.AddIn.Tooltips this.itemsSource.ForEach(item => observable.Add(item)); // verify if at the line of the root there's a pin bookmark - ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; - var editor = provider.TextEditor; + ITextEditor editor; + var viewContent = WorkbenchSingleton.Workbench.ActiveViewContent; + ITextEditorProvider provider = viewContent as ITextEditorProvider; + if (provider != null) { + editor = provider.TextEditor; + } else { + dynamic codeView = viewContent.Control; + editor = codeView.TextEditor as ITextEditor; + } + if (editor != null) { var pin = BookmarkManager.Bookmarks.Find( b => b is PinBookmark && @@ -208,7 +220,7 @@ namespace Debugger.AddIn.Tooltips // open child Popup if (this.childPopup == null) { - this.childPopup = new DebuggerPopup(this, logicalPosition); + this.childPopup = new DebuggerPopup(this, logicalPosition, showPins); this.childPopup.Placement = PlacementMode.Absolute; } if (this.containingPopup != null) { diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs index 813135904c..deb6752d7f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs @@ -5,13 +5,17 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; + using Debugger.AddIn.Visualizers; using Debugger.MetaData; using ICSharpCode.Core; +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.ILAst; using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Debugging; @@ -154,6 +158,15 @@ namespace Debugger.AddIn.TreeModel Value val; try { + object data = WindowsDebugger.GetLocalVariableIndex(WindowsDebugger.DebuggedProcess.SelectedThread.MostRecentStackFrame, Name); + if (expression is MemberReferenceExpression) { + var memberExpression = (MemberReferenceExpression)expression; + memberExpression.TargetObject.UserData = data; + } else { + expression.UserData = data; + } + + // evaluate expression val = expression.Evaluate(WindowsDebugger.DebuggedProcess); } catch (GetValueException e) { error = e; diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/CorDebug.cs b/src/AddIns/Debugger/Debugger.Core/Interop/CorDebug.cs index 88ccf6d91d..fba895667f 100644 --- a/src/AddIns/Debugger/Debugger.Core/Interop/CorDebug.cs +++ b/src/AddIns/Debugger/Debugger.Core/Interop/CorDebug.cs @@ -62,6 +62,14 @@ namespace Debugger.Interop.CorDebug CHAIN_SECURITY = 4, CHAIN_THREAD_START = 0x40 } + + [Flags] + public enum CorDebugJITCompilerFlags + { + CORDEBUG_JIT_DEFAULT = 0x1, + CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3, + CORDEBUG_JIT_ENABLE_ENC = 0x7 + } [ComImport, TypeLibType((short) 2), Guid("6FEF44D0-39E7-4C77-BE8E-C9F8CF988630"), ClassInterface((short) 0)] public class CorDebugClass : ICorDebug, CorDebug diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs index 5a0b7d92a5..56517541dc 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs @@ -320,6 +320,17 @@ namespace Debugger EnterCallback(PausedReason.Other, "CreateProcess", pProcess); // Process is added in NDebugger.Start + // disable NGen + if (!this.process.Options.EnableJustMyCode && !this.process.Options.StepOverNoSymbols) { + ICorDebugProcess2 pProcess2 = pProcess as ICorDebugProcess2; + if (pProcess2 != null && Process.DebugMode == DebugModeFlag.Debug) { + try { + pProcess2.SetDesiredNGENCompilerFlags((uint)CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION); + } catch (COMException) { + // we cannot set the NGEN flag => no evaluation for optimized code. + } + } + } ExitCallback(); } diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs index f1bc327d70..35bb848459 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs @@ -68,7 +68,7 @@ namespace Debugger.MetaData sb.Append(this.ReturnType.Name); sb.Append(" "); } else { - sb.Append("void "); + sb.Append("System.Void "); } sb.Append(this.DeclaringType.FullName); @@ -80,7 +80,7 @@ namespace Debugger.MetaData if (!first) sb.Append(", "); first = false; - sb.Append(p.ParameterType.Name); + sb.Append(p.ParameterType.FullName); sb.Append(" "); sb.Append(p.Name); } @@ -89,6 +89,37 @@ namespace Debugger.MetaData } } + /// Name including the declaring type, return type without parameters names + public string FullNameWithoutParameterNames { + get { + StringBuilder sb = new StringBuilder(); + + if (this.IsStatic) { + sb.Append("static "); + } + if (this.ReturnType != null) { + sb.Append(this.ReturnType.Name); + sb.Append(" "); + } else { + sb.Append("System.Void "); + } + + sb.Append(this.DeclaringType.FullName); + sb.Append("."); + sb.Append(this.Name); + sb.Append("("); + bool first = true; + foreach(DebugParameterInfo p in GetParameters()) { + if (!first) + sb.Append(", "); + first = false; + sb.Append(p.ParameterType.FullName); + } + sb.Append(")"); + return sb.ToString(); + } + } + /// public override string Name { get { return methodProps.Name; } @@ -343,12 +374,12 @@ namespace Debugger.MetaData uint token = 0; bool success = - (Read(code, 0x00) || true) && // nop || nothing + (Read(code, 0x00) || true) && // nop || nothing (Read(code, 0x02, 0x7B) || Read(code, 0x7E)) && // ldarg.0; ldfld || ldsfld ReadToken(code, ref token) && // (Read(code, 0x0A, 0x2B, 0x00, 0x06) || true) && // stloc.0; br.s; offset+00; ldloc.0 || nothing Read(code, 0x2A); // ret - + if (!success) return; if (this.Process.Options.Verbose) { @@ -427,7 +458,7 @@ namespace Debugger.MetaData // Look on the method DebugType.IsDefined( this, - false, + false, typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerHiddenAttribute)) @@ -435,7 +466,7 @@ namespace Debugger.MetaData // Look on the type DebugType.IsDefined( declaringType, - false, + false, typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerHiddenAttribute)); @@ -464,6 +495,19 @@ namespace Debugger.MetaData } } + public static Value GetLocalVariableValue(StackFrame context, int varIndex) + { + ICorDebugValue corVal; + try { + corVal = context.CorILFrame.GetLocalVariable((uint)varIndex); + } catch (COMException e) { + if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); + // show the message in case of bad index + throw new GetValueException(e.Message); + } + return new Value(context.AppDomain, corVal); + } + public DebugLocalVariableInfo GetLocalVariable(int offset, string name) { foreach(DebugLocalVariableInfo loc in GetLocalVariables(offset)) { diff --git a/src/AddIns/Debugger/Debugger.Core/Module.cs b/src/AddIns/Debugger/Debugger.Core/Module.cs index cea0eeac7d..dafb26bbb9 100644 --- a/src/AddIns/Debugger/Debugger.Core/Module.cs +++ b/src/AddIns/Debugger/Debugger.Core/Module.cs @@ -93,22 +93,22 @@ namespace Debugger } [Debugger.Tests.Ignore] - public ulong BaseAdress { + public ulong BaseAdress { get { return this.CorModule.GetBaseAddress(); - } + } } - public bool IsDynamic { + public bool IsDynamic { get { return this.CorModule.IsDynamic() == 1; - } + } } - public bool IsInMemory { + public bool IsInMemory { get { return this.CorModule.IsInMemory() == 1; - } + } } internal uint AppDomainID { @@ -124,19 +124,19 @@ namespace Debugger } [Debugger.Tests.Ignore] - public string FullPath { + public string FullPath { get { return fullPath; - } + } } - public bool HasSymbols { + public bool HasSymbols { get { return symReader != null; - } + } } - public int OrderOfLoading { + public int OrderOfLoading { get { return orderOfLoading; } @@ -145,6 +145,22 @@ namespace Debugger } } + [Debugger.Tests.Ignore] + public CorDebugJITCompilerFlags JITCompilerFlags + { + get + { + uint retval = ((ICorDebugModule2)corModule).GetJITCompilerFlags(); + return (CorDebugJITCompilerFlags)retval; + } + set + { + // ICorDebugModule2.SetJITCompilerFlags can return successful HRESULTS other than S_OK. + // Since we have asked the COMInterop layer to preservesig, we need to marshal any failing HRESULTS. + ((ICorDebugModule2)corModule).SetJITCompilerFlags((uint)value); + } + } + /// Returns all non-generic types defined in the module /// Generic types can not be returned, because we do not know how to instanciate them public List GetDefinedTypes() @@ -183,6 +199,8 @@ namespace Debugger name = System.IO.Path.GetFileName(FullPath); } + SetJITCompilerFlags(); + LoadSymbolsFromDisk(process.Options.SymbolsSearchPaths); ResetJustMyCodeStatus(); } @@ -268,7 +286,7 @@ namespace Debugger } } - void SetBreakpoints() + void SetBreakpoints() { if (this.HasSymbols) { // This is in case that the client modifies the collection as a response to set breakpoint @@ -282,6 +300,34 @@ namespace Debugger } } + void SetJITCompilerFlags() + { + if (Process.DebugMode != DebugModeFlag.Default) { + // translate DebugModeFlags to JITCompilerFlags + CorDebugJITCompilerFlags jcf = MapDebugModeToJITCompilerFlags(Process.DebugMode); + + try + { + this.JITCompilerFlags = jcf; + + // Flags may succeed but not set all bits, so requery. + CorDebugJITCompilerFlags jcfActual = this.JITCompilerFlags; + + #if DEBUG + if (jcf != jcfActual) + Console.WriteLine("Couldn't set all flags. Actual flags:" + jcfActual.ToString()); + else + Console.WriteLine("Actual flags:" + jcfActual.ToString()); + #endif + } + catch (COMException ex) + { + // we'll ignore the error if we cannot set the jit flags + Console.WriteLine(string.Format("Failed to set flags with hr=0x{0:x}", ex.ErrorCode)); + } + } + } + /// Sets all code as being 'my code'. The code will be gradually /// set to not-user-code as encountered acording to stepping options public void ResetJustMyCodeStatus() @@ -319,6 +365,29 @@ namespace Debugger { return string.Format("{0}", this.Name); } + + public static CorDebugJITCompilerFlags MapDebugModeToJITCompilerFlags(DebugModeFlag debugMode) + { + CorDebugJITCompilerFlags jcf; + switch (debugMode) + { + case DebugModeFlag.Optimized: + jcf = CorDebugJITCompilerFlags.CORDEBUG_JIT_DEFAULT; // DEFAULT really means force optimized. + break; + case DebugModeFlag.Debug: + jcf = CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION; + break; + case DebugModeFlag.Enc: + jcf = CorDebugJITCompilerFlags.CORDEBUG_JIT_ENABLE_ENC; + break; + default: + // we don't have mapping from default to "default", + // therefore we'll use DISABLE_OPTIMIZATION. + jcf = CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION; + break; + } + return jcf; + } } [Serializable] diff --git a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs b/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs index 063d1a5298..3002d6f916 100644 --- a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs +++ b/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs @@ -71,29 +71,33 @@ namespace ICSharpCode.NRefactory.Visitors /// Evaluate given expression. If you have expression tree already, use overloads of this method. /// Returned value or null for statements - public static Value Evaluate(string code, SupportedLanguage language, StackFrame context) + public static Value Evaluate(string code, SupportedLanguage language, StackFrame context, object data = null) { - return Evaluate(Parse(code, language), context); + return Evaluate(Parse(code, language), context, data); } public static Value Evaluate(INode code, Process context) { - if (context.SelectedStackFrame != null) { - return Evaluate(code, context.SelectedStackFrame); - } else if (context.SelectedThread.MostRecentStackFrame != null ) { - return Evaluate(code, context.SelectedThread.MostRecentStackFrame); - } else { + StackFrame stackFrame; + if (context.SelectedStackFrame == null && context.SelectedThread.MostRecentStackFrame == null) // This can happen when needed 'dll' is missing. This causes an exception dialog to be shown even before the applicaiton starts throw new GetValueException("Can not evaluate because the process has no managed stack frames"); - } + + if (context.SelectedStackFrame.ToString() == context.SelectedThread.MostRecentStackFrame.ToString()) { + stackFrame = context.SelectedStackFrame; + } else { + stackFrame = context.SelectedThread.MostRecentStackFrame; + } + + return Evaluate(code, stackFrame); } - public static Value Evaluate(INode code, StackFrame context) + public static Value Evaluate(INode code, StackFrame context, object data = null) { if (context == null) throw new ArgumentNullException("context"); if (context.IsInvalid) throw new DebuggerException("The context is no longer valid"); - TypedValue val = new ExpressionEvaluator(context).Evaluate(code, false); + TypedValue val = new ExpressionEvaluator(context).Evaluate(code, false, data); if (val == null) return null; return val.Value; @@ -164,7 +168,7 @@ namespace ICSharpCode.NRefactory.Visitors return Evaluate(expression, true); } - TypedValue Evaluate(INode expression, bool permRef) + TypedValue Evaluate(INode expression, bool permRef, object data = null) { // Try to get the value from cache // (the cache is cleared when the process is resumed) @@ -177,7 +181,7 @@ namespace ICSharpCode.NRefactory.Visitors System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); try { - val = (TypedValue)expression.AcceptVisitor(this, null); + val = (TypedValue)expression.AcceptVisitor(this, data); if (val != null && permRef) val = new TypedValue(val.Value.GetPermanentReference(), val.Type); } catch (GetValueException e) { @@ -277,21 +281,21 @@ namespace ICSharpCode.NRefactory.Visitors { BinaryOperatorType op; switch (assignmentExpression.Op) { - case AssignmentOperatorType.Assign: op = BinaryOperatorType.None; break; - case AssignmentOperatorType.Add: op = BinaryOperatorType.Add; break; - case AssignmentOperatorType.ConcatString: op = BinaryOperatorType.Concat; break; - case AssignmentOperatorType.Subtract: op = BinaryOperatorType.Subtract; break; - case AssignmentOperatorType.Multiply: op = BinaryOperatorType.Multiply; break; - case AssignmentOperatorType.Divide: op = BinaryOperatorType.Divide; break; - case AssignmentOperatorType.DivideInteger: op = BinaryOperatorType.DivideInteger; break; - case AssignmentOperatorType.ShiftLeft: op = BinaryOperatorType.ShiftLeft; break; - case AssignmentOperatorType.ShiftRight: op = BinaryOperatorType.ShiftRight; break; - case AssignmentOperatorType.ExclusiveOr: op = BinaryOperatorType.ExclusiveOr; break; - case AssignmentOperatorType.Modulus: op = BinaryOperatorType.Modulus; break; - case AssignmentOperatorType.BitwiseAnd: op = BinaryOperatorType.BitwiseAnd; break; - case AssignmentOperatorType.BitwiseOr: op = BinaryOperatorType.BitwiseOr; break; - case AssignmentOperatorType.Power: op = BinaryOperatorType.Power; break; - default: throw new GetValueException("Unknown operator " + assignmentExpression.Op); + case AssignmentOperatorType.Assign: op = BinaryOperatorType.None; break; + case AssignmentOperatorType.Add: op = BinaryOperatorType.Add; break; + case AssignmentOperatorType.ConcatString: op = BinaryOperatorType.Concat; break; + case AssignmentOperatorType.Subtract: op = BinaryOperatorType.Subtract; break; + case AssignmentOperatorType.Multiply: op = BinaryOperatorType.Multiply; break; + case AssignmentOperatorType.Divide: op = BinaryOperatorType.Divide; break; + case AssignmentOperatorType.DivideInteger: op = BinaryOperatorType.DivideInteger; break; + case AssignmentOperatorType.ShiftLeft: op = BinaryOperatorType.ShiftLeft; break; + case AssignmentOperatorType.ShiftRight: op = BinaryOperatorType.ShiftRight; break; + case AssignmentOperatorType.ExclusiveOr: op = BinaryOperatorType.ExclusiveOr; break; + case AssignmentOperatorType.Modulus: op = BinaryOperatorType.Modulus; break; + case AssignmentOperatorType.BitwiseAnd: op = BinaryOperatorType.BitwiseAnd; break; + case AssignmentOperatorType.BitwiseOr: op = BinaryOperatorType.BitwiseOr; break; + case AssignmentOperatorType.Power: op = BinaryOperatorType.Power; break; + default: throw new GetValueException("Unknown operator " + assignmentExpression.Op); } TypedValue right; @@ -382,6 +386,14 @@ namespace ICSharpCode.NRefactory.Visitors if (loc != null) return new TypedValue(loc.GetValue(context), (DebugType)loc.LocalType); + // try get local var from external information - data or UserData + int[] localIndex = (data ?? identifierExpression.UserData) as int[]; + + if (localIndex != null) { + Value localValue = DebugMethodInfo.GetLocalVariableValue(context, localIndex[0]); + return new TypedValue(localValue, localValue.Type); + } + // Instance class members // Note that the method might be generated instance method that represents anonymous method TypedValue thisValue = GetThisValue(); @@ -554,7 +566,14 @@ namespace ICSharpCode.NRefactory.Visitors DebugLocalVariableInfo thisVar = context.MethodInfo.GetLocalVariableThis(); if (thisVar != null) return new TypedValue(thisVar.GetValue(context), (DebugType)thisVar.LocalType); - return null; + + // when symbols are not present + try { + return new TypedValue(context.GetThisValue(), (DebugType)context.MethodInfo.DeclaringType); + } catch (GetValueException) { + // static method + return null; + } } public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) @@ -640,7 +659,7 @@ namespace ICSharpCode.NRefactory.Visitors } } } - + throw new EvaluateException(unaryOperatorExpression, "Can not use the unary operator {0} on type {1}", op.ToString(), value.Type.FullName); } @@ -654,57 +673,57 @@ namespace ICSharpCode.NRefactory.Visitors if (argType == typeof(bool)) { bool a = (bool)val; switch (op) { - case UnaryOperatorType.Not: return !a; + case UnaryOperatorType.Not: return !a; } } if (argType == typeof(float)) { float a = (float)val; switch (op) { - case UnaryOperatorType.Minus: return -a; - case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.Minus: return -a; + case UnaryOperatorType.Plus: return +a; } } if (argType == typeof(double)) { double a = (double)val; switch (op) { - case UnaryOperatorType.Minus: return -a; - case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.Minus: return -a; + case UnaryOperatorType.Plus: return +a; } } - + if (argType == typeof(int)) { int a = (int)val; switch (op) { - case UnaryOperatorType.Minus: return -a; - case UnaryOperatorType.Plus: return +a; - case UnaryOperatorType.BitNot: return ~a; + case UnaryOperatorType.Minus: return -a; + case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.BitNot: return ~a; } } if (argType == typeof(uint)) { uint a = (uint)val; switch (op) { - case UnaryOperatorType.Plus: return +a; - case UnaryOperatorType.BitNot: return ~a; + case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.BitNot: return ~a; } } if (argType == typeof(long)) { long a = (long)val; switch (op) { - case UnaryOperatorType.Minus: return -a; - case UnaryOperatorType.Plus: return +a; - case UnaryOperatorType.BitNot: return ~a; + case UnaryOperatorType.Minus: return -a; + case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.BitNot: return ~a; } } if (argType == typeof(ulong)) { ulong a = (ulong)val; switch (op) { - case UnaryOperatorType.Plus: return +a; - case UnaryOperatorType.BitNot: return ~a; + case UnaryOperatorType.Plus: return +a; + case UnaryOperatorType.BitNot: return ~a; } } } @@ -789,8 +808,8 @@ namespace ICSharpCode.NRefactory.Visitors // void operator +(ulong x, long y); // float operator +(float x, float y); // double operator +(double x, double y); - // - // &, |, ^, &&, || + // + // &, |, ^, &&, || // ==, != // bool operator &(bool x, bool y); @@ -834,9 +853,9 @@ namespace ICSharpCode.NRefactory.Visitors string a = (string)left; string b = (string)right; switch (op) { - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.Add: return a + b; } } @@ -844,13 +863,13 @@ namespace ICSharpCode.NRefactory.Visitors bool a = (bool)left; bool b = (bool)right; switch (op) { - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.ExclusiveOr: return a ^ b; - case BinaryOperatorType.BitwiseAnd: return a & b; - case BinaryOperatorType.BitwiseOr: return a | b; - case BinaryOperatorType.LogicalAnd: return a && b; - case BinaryOperatorType.LogicalOr: return a || b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.ExclusiveOr: return a ^ b; + case BinaryOperatorType.BitwiseAnd: return a & b; + case BinaryOperatorType.BitwiseOr: return a | b; + case BinaryOperatorType.LogicalAnd: return a && b; + case BinaryOperatorType.LogicalOr: return a || b; } } @@ -858,19 +877,19 @@ namespace ICSharpCode.NRefactory.Visitors float a = (float)left; float b = (float)right; switch (op) { - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } @@ -878,134 +897,134 @@ namespace ICSharpCode.NRefactory.Visitors double a = (double)left; double b = (double)right; switch (op) { - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } if (argTypes == typeof(int)) { switch (op) { - case BinaryOperatorType.ShiftLeft: return (int)left << (int)right; - case BinaryOperatorType.ShiftRight: return (int)left >> (int)right; + case BinaryOperatorType.ShiftLeft: return (int)left << (int)right; + case BinaryOperatorType.ShiftRight: return (int)left >> (int)right; } int a = (int)left; int b = (int)right; switch (op) { - case BinaryOperatorType.BitwiseAnd: return a & b; - case BinaryOperatorType.BitwiseOr: return a | b; - case BinaryOperatorType.ExclusiveOr: return a ^ b; - - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.BitwiseAnd: return a & b; + case BinaryOperatorType.BitwiseOr: return a | b; + case BinaryOperatorType.ExclusiveOr: return a ^ b; + + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } if (argTypes == typeof(uint)) { switch (op) { - case BinaryOperatorType.ShiftLeft: return (uint)left << (int)right; - case BinaryOperatorType.ShiftRight: return (uint)left >> (int)right; + case BinaryOperatorType.ShiftLeft: return (uint)left << (int)right; + case BinaryOperatorType.ShiftRight: return (uint)left >> (int)right; } uint a = (uint)left; uint b = (uint)right; switch (op) { - case BinaryOperatorType.BitwiseAnd: return a & b; - case BinaryOperatorType.BitwiseOr: return a | b; - case BinaryOperatorType.ExclusiveOr: return a ^ b; - - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.BitwiseAnd: return a & b; + case BinaryOperatorType.BitwiseOr: return a | b; + case BinaryOperatorType.ExclusiveOr: return a ^ b; + + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } if (argTypes == typeof(long)) { switch (op) { - case BinaryOperatorType.ShiftLeft: return (long)left << (int)right; - case BinaryOperatorType.ShiftRight: return (long)left >> (int)right; + case BinaryOperatorType.ShiftLeft: return (long)left << (int)right; + case BinaryOperatorType.ShiftRight: return (long)left >> (int)right; } long a = (long)left; long b = (long)right; switch (op) { - case BinaryOperatorType.BitwiseAnd: return a & b; - case BinaryOperatorType.BitwiseOr: return a | b; - case BinaryOperatorType.ExclusiveOr: return a ^ b; - - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.BitwiseAnd: return a & b; + case BinaryOperatorType.BitwiseOr: return a | b; + case BinaryOperatorType.ExclusiveOr: return a ^ b; + + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } if (argTypes == typeof(ulong)) { switch (op) { - case BinaryOperatorType.ShiftLeft: return (ulong)left << (int)right; - case BinaryOperatorType.ShiftRight: return (ulong)left >> (int)right; + case BinaryOperatorType.ShiftLeft: return (ulong)left << (int)right; + case BinaryOperatorType.ShiftRight: return (ulong)left >> (int)right; } ulong a = (ulong)left; ulong b = (ulong)right; switch (op) { - case BinaryOperatorType.BitwiseAnd: return a & b; - case BinaryOperatorType.BitwiseOr: return a | b; - case BinaryOperatorType.ExclusiveOr: return a ^ b; - - case BinaryOperatorType.GreaterThan: return a > b; - case BinaryOperatorType.GreaterThanOrEqual: return a >= b; - case BinaryOperatorType.Equality: return a == b; - case BinaryOperatorType.InEquality: return a != b; - case BinaryOperatorType.LessThan: return a < b; - case BinaryOperatorType.LessThanOrEqual: return a <= b; - - case BinaryOperatorType.Add: return a + b; - case BinaryOperatorType.Subtract: return a - b; - case BinaryOperatorType.Multiply: return a * b; - case BinaryOperatorType.Divide: return a / b; - case BinaryOperatorType.Modulus: return a % b; - case BinaryOperatorType.Concat: return a + b; + case BinaryOperatorType.BitwiseAnd: return a & b; + case BinaryOperatorType.BitwiseOr: return a | b; + case BinaryOperatorType.ExclusiveOr: return a ^ b; + + case BinaryOperatorType.GreaterThan: return a > b; + case BinaryOperatorType.GreaterThanOrEqual: return a >= b; + case BinaryOperatorType.Equality: return a == b; + case BinaryOperatorType.InEquality: return a != b; + case BinaryOperatorType.LessThan: return a < b; + case BinaryOperatorType.LessThanOrEqual: return a <= b; + + case BinaryOperatorType.Add: return a + b; + case BinaryOperatorType.Subtract: return a - b; + case BinaryOperatorType.Multiply: return a * b; + case BinaryOperatorType.Divide: return a / b; + case BinaryOperatorType.Modulus: return a % b; + case BinaryOperatorType.Concat: return a + b; } } - + return null; } } diff --git a/src/AddIns/Debugger/Debugger.Core/Options.cs b/src/AddIns/Debugger/Debugger.Core/Options.cs index 72a84ae3e7..43d6f64b31 100644 --- a/src/AddIns/Debugger/Debugger.Core/Options.cs +++ b/src/AddIns/Debugger/Debugger.Core/Options.cs @@ -5,14 +5,15 @@ namespace Debugger { public class Options { - public bool EnableJustMyCode = true; - public bool StepOverNoSymbols = true; + public bool EnableJustMyCode = false; + public bool StepOverNoSymbols = false; public bool StepOverDebuggerAttributes = true; public bool StepOverAllProperties = false; public bool StepOverSingleLineProperties = false; public bool StepOverFieldAccessProperties = true; public bool Verbose = false; public string[] SymbolsSearchPaths = new string[0]; - public bool SuspendOtherThreads = true; + public bool SuspendOtherThreads = false; + public bool EnableEditAndContinue = false; } } diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index b788876e84..bd47e6f2b5 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -14,6 +14,29 @@ namespace Debugger { internal enum DebuggeeStateAction { Keep, Clear } + /// + /// Debug Mode Flags. + /// + public enum DebugModeFlag + { + /// + /// Run in the same mode as without debugger. + /// + Default, + /// + /// Run in forced optimized mode. + /// + Optimized, + /// + /// Run in debug mode (easy inspection) but slower. + /// + Debug, + /// + /// Run in ENC mode (ENC possible) but even slower than debug + /// + Enc + } + public class Process: DebuggerObject { NDebugger debugger; @@ -28,6 +51,7 @@ namespace Debugger string workingDirectory; + public NDebugger Debugger { get { return debugger; } } @@ -108,6 +132,8 @@ namespace Debugger get { return workingDirectory; } } + public static DebugModeFlag DebugMode { get; set; } + internal Process(NDebugger debugger, ICorDebugProcess corProcess, string workingDirectory) { this.debugger = debugger; @@ -660,13 +686,18 @@ namespace Debugger breakpoint.Remove(); breakpoint = null; }; - } catch { + } catch { // the app does not have an entry point - COM exception } BreakAtBeginning = false; } + + if (ModulesAdded != null) + ModulesAdded(this, new ModuleEventArgs(e.Item)); } #endregion + + public event EventHandler ModulesAdded; } } diff --git a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs index d9150899e8..459d34451e 100644 --- a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs +++ b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs @@ -16,6 +16,7 @@ namespace Debugger Module module; string filename; + string typename; byte[] checkSum; int startLine; int startColumn; @@ -35,6 +36,10 @@ namespace Debugger get { return filename; } } + public string Typename { + get { return typename; } + } + public byte[] CheckSum { get { return checkSum; } } @@ -99,7 +104,7 @@ namespace Debugger yield return symUrl; yield break; } - + if (Path.IsPathRooted(symUrl)) { Dictionary returned = new Dictionary(); @@ -207,7 +212,7 @@ namespace Debugger segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); segment.ilStart = (int)sqPoint.Offset; segment.ilEnd = (int)sqPoint.Offset; - segment.stepRanges = null; + segment.stepRanges = null; return segment; } } @@ -336,7 +341,57 @@ namespace Debugger public override string ToString() { - return string.Format("{0}:{1},{2}-{3},{4}", Path.GetFileName(this.Filename), this.startLine, this.startColumn, this.endLine, this.endColumn); + return string.Format("{0}:{1},{2}-{3},{4}", + Path.GetFileName(this.Filename ?? string.Empty), + this.startLine, this.startColumn, this.endLine, this.endColumn); } + + #region ILSpy + + public static SourcecodeSegment CreateForIL(Module module, int line, int metadataToken, int iLOffset) + { + try { + SourcecodeSegment segment = new SourcecodeSegment(); + segment.module = module; + segment.typename = null; + segment.checkSum = null; + segment.startLine = line; + segment.startColumn = 0; + segment.endLine = line; + segment.endColumn = 0; + segment.corFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken); + segment.ilStart = iLOffset; + segment.ilEnd = iLOffset; + segment.stepRanges = null; + + return segment; + } catch { + return null; + } + } + + public static SourcecodeSegment ResolveForIL(Module module, ICorDebugFunction corFunction, int line, int offset, int[] ranges) + { + try { + SourcecodeSegment segment = new SourcecodeSegment(); + segment.module = module; + segment.typename = null; + segment.checkSum = null; + segment.startLine = line; + segment.startColumn = 0; + segment.endLine = line; + segment.endColumn = 0; + segment.corFunction = corFunction; + segment.ilStart = offset; + segment.ilEnd = ranges[1]; + segment.stepRanges = ranges; + + return segment; + } catch { + return null; + } + } + + #endregion } } diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs index 2f0858c23f..05f6b00579 100644 --- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs +++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs @@ -16,7 +16,7 @@ namespace Debugger /// Use to obtain arguments or local variables. /// public class StackFrame: DebuggerObject - { + { Thread thread; AppDomain appDomain; Process process; @@ -59,7 +59,7 @@ namespace Debugger } - /// True if the stack frame has symbols defined. + /// True if the stack frame has symbols defined. /// (That is has accesss to the .pdb file) public bool HasSymbols { get { @@ -139,8 +139,14 @@ namespace Debugger } } + public int[] ILRanges { get; set; } + + public int SourceCodeLine { get; set; } + SourcecodeSegment GetSegmentForOffet(int offset) { + if (SourceCodeLine != 0) + return SourcecodeSegment.ResolveForIL(this.MethodInfo.DebugModule, corFunction, SourceCodeLine, offset, ILRanges); return SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, corFunction, offset); } @@ -187,17 +193,23 @@ namespace Debugger void AsyncStep(bool stepIn) { - if (this.MethodInfo.DebugModule.HasSymbols == false) { + if (this.MethodInfo.DebugModule.HasSymbols == false && process.Options.StepOverNoSymbols) { throw new DebuggerException("Unable to step. No symbols loaded."); } - SourcecodeSegment nextSt = NextStatement; - if (nextSt == null) { - throw new DebuggerException("Unable to step. Next statement not aviable"); + int[] stepRanges; + if (ILRanges == null) { + SourcecodeSegment nextSt = NextStatement; + if (nextSt == null) { + throw new DebuggerException("Unable to step. Next statement not aviable"); + } + stepRanges = nextSt.StepRanges; + } else { + stepRanges = ILRanges; } if (stepIn) { - Stepper stepInStepper = Stepper.StepIn(this, nextSt.StepRanges, "normal"); + Stepper stepInStepper = Stepper.StepIn(this, stepRanges, "normal"); this.Thread.CurrentStepIn = stepInStepper; Stepper clearCurrentStepIn = Stepper.StepOut(this, "clear current step in"); clearCurrentStepIn.StepComplete += delegate { @@ -207,7 +219,7 @@ namespace Debugger }; clearCurrentStepIn.Ignore = true; } else { - Stepper.StepOver(this, nextSt.StepRanges, "normal"); + Stepper.StepOver(this, stepRanges, "normal"); } AsyncContinue(); @@ -276,7 +288,7 @@ namespace Debugger return null; } - /// + /// /// Gets the instance of the class asociated with the current frame. /// That is, 'this' in C#. /// Note that for delegates and enumerators this returns the instance of the display class. @@ -397,8 +409,8 @@ namespace Debugger { int hashCode = 0; unchecked { - if (thread != null) hashCode += 1000000009 * thread.GetHashCode(); - if (methodInfo != null) hashCode += 1000000093 * methodInfo.GetHashCode(); + if (thread != null) hashCode += 1000000009 * thread.GetHashCode(); + if (methodInfo != null) hashCode += 1000000093 * methodInfo.GetHashCode(); hashCode += 1000000097 * chainIndex.GetHashCode(); hashCode += 1000000103 * frameIndex.GetHashCode(); } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index 180bc7e13e..a0a634c413 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -31,11 +31,20 @@ using ICSharpCode.SharpDevelop.Editor.CodeCompletion; namespace ICSharpCode.AvalonEdit.AddIn { + public interface ICodeEditor + { + TextDocument Document { get; } + + void Redraw(ISegment segment, DispatcherPriority priority); + + event EventHandler DocumentChanged; + } + /// /// Integrates AvalonEdit with SharpDevelop. /// Also provides support for Split-View (showing two AvalonEdit instances using the same TextDocument) /// - public class CodeEditor : Grid, IDisposable + public class CodeEditor : Grid, IDisposable, ICodeEditor { const string contextMenuPath = "/SharpDevelop/ViewContent/AvalonEdit/ContextMenu"; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarManager.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarManager.cs index 86eccd0125..9ec975baa9 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarManager.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarManager.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.AvalonEdit.AddIn public event EventHandler RedrawRequested; - internal void UpdateClassMemberBookmarks(ParseInformation parseInfo) + public void UpdateClassMemberBookmarks(ParseInformation parseInfo) { for (int i = bookmarks.Count - 1; i >= 0; i--) { if (IsClassMemberBookmark(bookmarks[i])) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs index aa17b024ec..20cd1bf9f3 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs @@ -20,9 +20,9 @@ namespace ICSharpCode.AvalonEdit.AddIn /// public class IconBarMargin : AbstractMargin, IDisposable { - readonly IconBarManager manager; + readonly IBookmarkMargin manager; - public IconBarMargin(IconBarManager manager) + public IconBarMargin(IBookmarkMargin manager) { if (manager == null) throw new ArgumentNullException("manager"); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs index 7fb7e03ef2..83a5ce5208 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs @@ -18,12 +18,12 @@ namespace ICSharpCode.AvalonEdit.AddIn /// /// Handles the text markers for a code editor. /// - sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService + public sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService { - readonly CodeEditor codeEditor; + readonly ICodeEditor codeEditor; TextSegmentCollection markers; - public TextMarkerService(CodeEditor codeEditor) + public TextMarkerService(ICodeEditor codeEditor) { if (codeEditor == null) throw new ArgumentNullException("codeEditor"); @@ -200,7 +200,7 @@ namespace ICSharpCode.AvalonEdit.AddIn #endregion } - sealed class TextMarker : TextSegment, ITextMarker + public sealed class TextMarker : TextSegment, ITextMarker { readonly TextMarkerService service; diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj index e2d4ae0e46..415cbd3c4f 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj @@ -99,6 +99,10 @@ {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory + + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} + NRefactory + {2748AD25-9C63-4E12-877B-4DCE96FBED54} ICSharpCode.SharpDevelop diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs index e4a0f88884..4304c15231 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs @@ -4,15 +4,18 @@ using System; using System.IO; using System.Linq; + +using ICSharpCode.Core.Services; using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.ILSpyAddIn { - public class NavigateToDecompiledEntityService : INavigateToEntityService + public class NavigateToDecompiledEntityService : INavigateToEntityService, INavigateToMemberService { - public bool NavigateTo(IEntity entity) + public bool NavigateToEntity(IEntity entity) { if (entity == null) throw new ArgumentNullException("entity"); @@ -41,6 +44,12 @@ namespace ICSharpCode.ILSpyAddIn public static void NavigateTo(string assemblyFile, string typeName, string entityTag) { + if (string.IsNullOrEmpty(assemblyFile)) + throw new ArgumentException("assemblyFile is null or empty"); + + if (string.IsNullOrEmpty(typeName)) + throw new ArgumentException("typeName is null or empty"); + foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType()) { if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) { vc.WorkbenchWindow.SelectWindow(); @@ -50,5 +59,18 @@ namespace ICSharpCode.ILSpyAddIn } WorkbenchSingleton.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityTag)); } + + public bool NavigateToMember(string assemblyFile, string typeName, string entityTag) + { + //close the window if exists - this is a workaround + foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType()) { + if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) { + vc.WorkbenchWindow.CloseWindow(true); + break; + } + } + WorkbenchSingleton.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityTag)); + return true; + } } } diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs index 1ff758072a..4e8dcb56ad 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs @@ -2,33 +2,243 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Diagnostics; +using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; + +using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.AddIn; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Rendering; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; namespace ICSharpCode.ILSpyAddIn.ViewContent { /// /// Equivalent to AE.AddIn CodeEditor, but without editing capabilities. /// - public class CodeView : Grid, IDisposable + public class CodeView : Grid, IDisposable, ICodeEditor { - readonly SharpDevelopTextEditor textEditor = new SharpDevelopTextEditor(); + public event EventHandler DocumentChanged; + + readonly AvalonEditTextEditorAdapter adapter = new AvalonEditTextEditorAdapter(new SharpDevelopTextEditor { IsReadOnly = true }); + readonly IconBarManager iconBarManager; + readonly IconBarMargin iconMargin; + readonly TextMarkerService textMarkerService; public CodeView() { - this.Children.Add(textEditor); - textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#"); + this.Children.Add(adapter.TextEditor); + adapter.TextEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#"); + + // add margin + iconMargin = new IconBarMargin(iconBarManager = new IconBarManager()); + adapter.TextEditor.TextArea.LeftMargins.Insert(0, iconMargin); + adapter.TextEditor.TextArea.TextView.VisualLinesChanged += delegate { iconMargin.InvalidateVisual(); }; + + // add marker service + textMarkerService = new TextMarkerService(this); + adapter.TextEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); + adapter.TextEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); + adapter.TextEditor.TextArea.TextView.Services.AddService(typeof(ITextMarkerService), textMarkerService); + + // add events + this.adapter.TextEditor.MouseHover += TextEditorMouseHover; + this.adapter.TextEditor.MouseHoverStopped += TextEditorMouseHoverStopped; + this.adapter.TextEditor.MouseLeave += TextEditorMouseLeave; + } + + #region Popup + ToolTip toolTip; + Popup popup; + + void TextEditorMouseHover(object sender, MouseEventArgs e) + { + ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(this.adapter); + var pos = adapter.TextEditor.GetPositionFromPoint(e.GetPosition(this)); + args.InDocument = pos.HasValue; + if (pos.HasValue) { + args.LogicalPosition = AvalonEditDocumentAdapter.ToLocation(pos.Value); + } + + if (!args.Handled) { + // if request wasn't handled by a marker, pass it to the ToolTipRequestService + ToolTipRequestService.RequestToolTip(args); + } + + if (args.ContentToShow != null) { + var contentToShowITooltip = args.ContentToShow as ITooltip; + + if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) { + if (!(args.ContentToShow is UIElement)) { + throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow); + } + if (popup == null) { + popup = CreatePopup(); + } + if (TryCloseExistingPopup(false)) { + // when popup content decides to close, close the popup + contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; }; + popup.Child = (UIElement)args.ContentToShow; + //ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged + SetPopupPosition(popup, e); + popup.IsOpen = true; + } + e.Handled = true; + } else { + if (toolTip == null) { + toolTip = new ToolTip(); + toolTip.Closed += delegate { toolTip = null; }; + } + toolTip.PlacementTarget = this.adapter.TextEditor; // required for property inheritance + + if(args.ContentToShow is string) { + toolTip.Content = new TextBlock + { + Text = args.ContentToShow as string, + TextWrapping = TextWrapping.Wrap + }; + } + else + toolTip.Content = args.ContentToShow; + + toolTip.IsOpen = true; + e.Handled = true; + } + } else { + // close popup if mouse hovered over empty area + if (popup != null) { + e.Handled = true; + } + TryCloseExistingPopup(false); + } + } + + bool TryCloseExistingPopup(bool mouseClick) + { + bool canClose = true; + if (popup != null) { + var popupContentITooltip = popup.Child as ITooltip; + if (popupContentITooltip != null) { + canClose = popupContentITooltip.Close(mouseClick); + } + if (canClose) { + popup.IsOpen = false; + } + } + return canClose; + } + + void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs) + { + var popupPosition = GetPopupPosition(mouseArgs); + popup.HorizontalOffset = popupPosition.X; + popup.VerticalOffset = popupPosition.Y; + } + + /// Returns Popup position based on mouse position, in device independent units + Point GetPopupPosition(MouseEventArgs mouseArgs) + { + Point mousePos = mouseArgs.GetPosition(this); + Point positionInPixels; + // align Popup with line bottom + TextViewPosition? logicalPos = adapter.TextEditor.GetPositionFromPoint(mousePos); + if (logicalPos.HasValue) { + var textView = adapter.TextEditor.TextArea.TextView; + positionInPixels = + textView.PointToScreen( + textView.GetVisualPosition(logicalPos.Value, VisualYPosition.LineBottom) - textView.ScrollOffset); + positionInPixels.X -= 4; + } else { + positionInPixels = PointToScreen(mousePos + new Vector(-4, 6)); + } + // use device independent units, because Popup Left/Top are in independent units + return positionInPixels.TransformFromDevice(this); + } + + Popup CreatePopup() + { + popup = new Popup(); + popup.Closed += (s, e) => popup = null; + popup.AllowsTransparency = true; + popup.PlacementTarget = this; // required for property inheritance + popup.Placement = PlacementMode.Absolute; + popup.StaysOpen = true; + return popup; } + void TextEditorMouseHoverStopped(object sender, MouseEventArgs e) + { + if (toolTip != null) { + toolTip.IsOpen = false; + e.Handled = true; + } + + TextEditorMouseLeave(sender, e); + } + + void TextEditorMouseLeave(object sender, MouseEventArgs e) + { + if (popup != null && !popup.IsMouseOver) { + // do not close popup if mouse moved from editor to popup + TryCloseExistingPopup(false); + } + } + + #endregion + public TextDocument Document { - get { return textEditor.Document; } - set { textEditor.Document = value; } + get { return adapter.TextEditor.Document; } + set { + adapter.TextEditor.Document = value; + if (DocumentChanged != null) { + DocumentChanged(value, EventArgs.Empty); + } + } + } + + public ITextEditor TextEditor { + get { + return adapter; + } + } + + public IconBarManager IconBarManager { + get { return iconBarManager; } } public void Dispose() { } + + public void UnfoldAndScroll(int lineNumber) + { + if (lineNumber <= 0 || lineNumber > adapter.Document.TotalNumberOfLines) + return; + + //var line = adapter.TextEditor.Document.GetLineByNumber(lineNumber); + + // unfold +// var foldings = foldingManager.GetFoldingsContaining(line.Offset); +// if (foldings != null) { +// foreach (var folding in foldings) { +// if (folding.IsFolded) { +// folding.IsFolded = false; +// } +// } +// } + // scroll to + adapter.TextEditor.ScrollTo(lineNumber, 0); + } + + public void Redraw(ISegment segment, System.Windows.Threading.DispatcherPriority priority) + { + this.adapter.TextEditor.TextArea.TextView.Redraw(segment, priority); + } } } diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs index 304bffa655..8c83ea14a1 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs @@ -2,14 +2,25 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.Core; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; +using ICSharpCode.Decompiler.ILAst; using ICSharpCode.ILSpyAddIn.ViewContent; +using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Bookmarks; +using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; using Mono.Cecil; @@ -46,7 +57,9 @@ namespace ICSharpCode.ILSpyAddIn Thread thread = new Thread(DecompilationThread); thread.Name = "Decompiler (" + shortTypeName + ")"; thread.Start(); + BookmarkManager.Removed += BookmarkManager_Removed; } + #endregion #region Properties @@ -61,6 +74,10 @@ namespace ICSharpCode.ILSpyAddIn public override object Control { get { return codeView; } } + + public override bool IsReadOnly { + get { return true; } + } #endregion #region Dispose @@ -68,6 +85,7 @@ namespace ICSharpCode.ILSpyAddIn { cancellation.Cancel(); codeView.Dispose(); + BookmarkManager.Removed -= BookmarkManager_Removed; base.Dispose(); } #endregion @@ -139,6 +157,17 @@ namespace ICSharpCode.ILSpyAddIn AstBuilder astBuilder = new AstBuilder(context); astBuilder.AddType(typeDefinition); astBuilder.GenerateCode(textOutput); + + // save decompilation data + var nodes = TreeTraversal + .PreOrder((AstNode)astBuilder.CompilationUnit, n => n.Children) + .Where(n => n is AttributedNode && n.Annotation>() != null); + DebuggerService.ExternalDebugInformation = new DecompileInformation { + CodeMappings = astBuilder.CodeMappings, + LocalVariables = astBuilder.LocalVariables, + DecompiledMemberReferences = astBuilder.DecompiledMemberReferences, + AstNodes = nodes + }; } void OnDecompilationFinished(StringWriter output) @@ -150,6 +179,53 @@ namespace ICSharpCode.ILSpyAddIn this.decompilationFinished = true; JumpToEntity(this.jumpToEntityTagWhenDecompilationFinished); + + // update UI + UpdateIconMargin(output.ToString()); + UpdateDebuggingUI(); + } + #endregion + + #region Update UI + void UpdateIconMargin(string text) + { + string tempFileName = string.Format("decompiled/{0}.cs", fullTypeName); + + codeView.IconBarManager.UpdateClassMemberBookmarks(ParserService.ParseFile(tempFileName, new StringTextBuffer(text))); + } + + void UpdateDebuggingUI() + { + if (!DebuggerService.IsDebuggerStarted) + return; + + if (DebuggerService.DebugStepInformation != null) { + // get debugging information + DecompileInformation debugInformation = (DecompileInformation)DebuggerService.ExternalDebugInformation; + int token = DebuggerService.DebugStepInformation.Item1; + int ilOffset = DebuggerService.DebugStepInformation.Item2; + int line; + MemberReference member; + if (!debugInformation.CodeMappings.ContainsKey(token)) + return; + + debugInformation.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out member, out line); + + // update bookmark & marker + codeView.UnfoldAndScroll(line); + CurrentLineBookmark.SetPosition(this, line, 0, line, 0); + } + } + #endregion + + #region Bookmarks + void BookmarkManager_Removed(object sender, BookmarkEventArgs e) + { + var mark = e.Bookmark; + if (mark != null && codeView.IconBarManager.Bookmarks.Contains(mark)) { + codeView.IconBarManager.Bookmarks.Remove(mark); + mark.Document = null; + } } #endregion } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs index a163213ddf..0927ec865c 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -1,4 +1,23 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -7,6 +26,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast.Transforms; using ICSharpCode.Decompiler.ILAst; @@ -26,10 +46,11 @@ namespace ICSharpCode.Decompiler.Ast { None = 0, IncludeNamespace = 1, - IncludeTypeParameterDefinitions = 2 + IncludeTypeParameterDefinitions = 2, + DoNotUsePrimitiveTypeNames = 4 } - public class AstBuilder + public class AstBuilder : BaseCodeMappings { DecompilerContext context; CompilationUnit astCompileUnit = new CompilationUnit(); @@ -42,6 +63,10 @@ namespace ICSharpCode.Decompiler.Ast throw new ArgumentNullException("context"); this.context = context; this.DecompileMethodBodies = true; + + this.LocalVariables = new ConcurrentDictionary>(); + this.CodeMappings = new Dictionary>(); + this.DecompiledMemberReferences = new Dictionary(); } public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings) @@ -121,8 +146,28 @@ namespace ICSharpCode.Decompiler.Ast public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) { + if (assemblyDefinition.Name.Version != null) { + astCompileUnit.AddChild( + new AttributeSection { + AttributeTarget = "assembly", + Attributes = { + new NRefactory.CSharp.Attribute { + Type = new SimpleType("AssemblyVersion") + .WithAnnotation(new TypeReference( + "System.Reflection", "AssemblyVersionAttribute", + assemblyDefinition.MainModule, assemblyDefinition.MainModule.TypeSystem.Corlib)), + Arguments = { + new PrimitiveExpression(assemblyDefinition.Name.Version.ToString()) + } + } + } + }, AttributedNode.AttributeRole); + } + ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly"); + ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module"); + AddTypeForwarderAttributes(astCompileUnit, assemblyDefinition.MainModule, "assembly"); if (!onlyAssemblyLevel) { foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { @@ -137,6 +182,30 @@ namespace ICSharpCode.Decompiler.Ast } } + void AddTypeForwarderAttributes(CompilationUnit astCompileUnit, ModuleDefinition module, string target) + { + if (!module.HasExportedTypes) + return; + foreach (ExportedType type in module.ExportedTypes) { + if (type.IsForwarder) { + var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope)); + astCompileUnit.AddChild( + new AttributeSection { + AttributeTarget = target, + Attributes = { + new NRefactory.CSharp.Attribute { + Type = new SimpleType("TypeForwardedTo") + .WithAnnotation(new TypeReference( + "System.Runtime.CompilerServices", "TypeForwardedToAttribute", + module, module.TypeSystem.Corlib)), + Arguments = { forwardedType } + } + } + }, AttributedNode.AttributeRole); + } + } + } + NamespaceDeclaration GetCodeNamespace(string name) { if (string.IsNullOrEmpty(name)) { @@ -192,6 +261,7 @@ namespace ICSharpCode.Decompiler.Ast /// TypeDeclaration or DelegateDeclaration. public AttributedNode CreateType(TypeDefinition typeDef) { + // create type TypeDefinition oldCurrentType = context.CurrentType; context.CurrentType = typeDef; TypeDeclaration astType = new TypeDeclaration(); @@ -219,13 +289,6 @@ namespace ICSharpCode.Decompiler.Ast astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters)); astType.Constraints.AddRange(MakeConstraints(genericParameters)); - // Nested types - foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) { - if (MemberIsHidden(nestedTypeDef, context.Settings)) - continue; - astType.AddChild(CreateType(nestedTypeDef), TypeDeclaration.MemberRole); - } - AttributedNode result = astType; if (typeDef.IsEnum) { long expectedEnumMemberValue = 0; @@ -238,6 +301,7 @@ namespace ICSharpCode.Decompiler.Ast } } else { EnumMemberDeclaration enumMember = new EnumMemberDeclaration(); + enumMember.AddAnnotation(field); enumMember.Name = CleanName(field.Name); long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) { @@ -259,6 +323,7 @@ namespace ICSharpCode.Decompiler.Ast if (m.Name == "Invoke") { dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType); dd.Parameters.AddRange(MakeParameters(m)); + ConvertAttributes(dd, m.MethodReturnType, m.Module); } } result = dd; @@ -302,6 +367,45 @@ namespace ICSharpCode.Decompiler.Ast return name; } + #region Create TypeOf Expression + /// + /// Creates a typeof-expression for the specified type. + /// + public static TypeOfExpression CreateTypeOfExpression(TypeReference type) + { + return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type))); + } + + static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) + { + TypeReference typeRef = type.Annotation(); + if (typeRef == null) + return type; + TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters + if (typeDef == null || !typeDef.HasGenericParameters) + return type; + SimpleType sType = type as SimpleType; + MemberType mType = type as MemberType; + if (sType != null) { + while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) { + sType.TypeArguments.Add(new SimpleType("")); + } + } + + if (mType != null) { + AddEmptyTypeArgumentsForUnboundGenerics(mType.Target); + + int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count; + + while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) { + mType.TypeArguments.Add(new SimpleType("")); + } + } + + return type; + } + #endregion + #region Convert Type Reference /// /// Converts a type reference. @@ -376,39 +480,42 @@ namespace ICSharpCode.Decompiler.Ast return new PrimitiveType("dynamic"); } else { if (ns == "System") { - switch (name) { - case "SByte": - return new PrimitiveType("sbyte"); - case "Int16": - return new PrimitiveType("short"); - case "Int32": - return new PrimitiveType("int"); - case "Int64": - return new PrimitiveType("long"); - case "Byte": - return new PrimitiveType("byte"); - case "UInt16": - return new PrimitiveType("ushort"); - case "UInt32": - return new PrimitiveType("uint"); - case "UInt64": - return new PrimitiveType("ulong"); - case "String": - return new PrimitiveType("string"); - case "Single": - return new PrimitiveType("float"); - case "Double": - return new PrimitiveType("double"); - case "Decimal": - return new PrimitiveType("decimal"); - case "Char": - return new PrimitiveType("char"); - case "Boolean": - return new PrimitiveType("bool"); - case "Void": - return new PrimitiveType("void"); - case "Object": - return new PrimitiveType("object"); + if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) + != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) { + switch (name) { + case "SByte": + return new PrimitiveType("sbyte"); + case "Int16": + return new PrimitiveType("short"); + case "Int32": + return new PrimitiveType("int"); + case "Int64": + return new PrimitiveType("long"); + case "Byte": + return new PrimitiveType("byte"); + case "UInt16": + return new PrimitiveType("ushort"); + case "UInt32": + return new PrimitiveType("uint"); + case "UInt64": + return new PrimitiveType("ulong"); + case "String": + return new PrimitiveType("string"); + case "Single": + return new PrimitiveType("float"); + case "Double": + return new PrimitiveType("double"); + case "Decimal": + return new PrimitiveType("decimal"); + case "Char": + return new PrimitiveType("char"); + case "Boolean": + return new PrimitiveType("bool"); + case "Void": + return new PrimitiveType("void"); + case "Object": + return new PrimitiveType("object"); + } } } @@ -585,6 +692,15 @@ namespace ICSharpCode.Decompiler.Ast void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) { + // Nested types + foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) { + if (MemberIsHidden(nestedTypeDef, context.Settings)) + continue; + var nestedType = CreateType(nestedTypeDef); + SetNewModifier(nestedType); + astType.AddChild(nestedType, TypeDeclaration.MemberRole); + } + // Add fields foreach(FieldDefinition fieldDef in typeDef.Fields) { if (MemberIsHidden(fieldDef, context.Settings)) continue; @@ -614,22 +730,26 @@ namespace ICSharpCode.Decompiler.Ast AttributedNode CreateMethod(MethodDefinition methodDef) { - MethodDeclaration astMethod = new MethodDeclaration(); + // Create mapping - used in debugger + CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef); + MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]); + + MethodDeclaration astMethod = new MethodDeclaration().WithAnnotation(methodMapping); astMethod.AddAnnotation(methodDef); astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType); astMethod.Name = CleanName(methodDef.Name); astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters)); astMethod.Parameters.AddRange(MakeParameters(methodDef)); - astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters)); + // constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters)); if (!methodDef.DeclaringType.IsInterface) { if (!methodDef.HasOverrides) { astMethod.Modifiers = ConvertModifiers(methodDef); - if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) { - if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any()) - astMethod.Modifiers |= Modifiers.New; - } - } else + if (methodDef.IsVirtual == methodDef.IsNewSlot) + SetNewModifier(astMethod); + } else { astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType); + } astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); } ConvertAttributes(astMethod, methodDef); @@ -699,6 +819,10 @@ namespace ICSharpCode.Decompiler.Ast ConstructorDeclaration CreateConstructor(MethodDefinition methodDef) { + // Create mapping - used in debugger + CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef); + MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]); + ConstructorDeclaration astMethod = new ConstructorDeclaration(); astMethod.AddAnnotation(methodDef); astMethod.Modifiers = ConvertModifiers(methodDef); @@ -710,6 +834,10 @@ namespace ICSharpCode.Decompiler.Ast astMethod.Parameters.AddRange(MakeParameters(methodDef)); astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); ConvertAttributes(astMethod, methodDef); + astMethod.WithAnnotation(methodMapping); + if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) { + astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), AstNode.Roles.Comment); + } return astMethod; } @@ -739,49 +867,71 @@ namespace ICSharpCode.Decompiler.Ast getterModifiers = ConvertModifiers(propDef.GetMethod); setterModifiers = ConvertModifiers(propDef.SetMethod); astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers); - if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) { - foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) { - if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) { - var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod); - astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask)); - break; - } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) { - break; + try { + if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) { + foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) { + if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) { + var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod); + astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask)); + break; + } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) { + break; + } } } - } - if (accessor.IsVirtual ^ !accessor.IsNewSlot) { - if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any()) - astProp.Modifiers |= Modifiers.New; + } catch (ReferenceResolvingException) { + // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. } } astProp.Name = CleanName(propDef.Name); astProp.ReturnType = ConvertType(propDef.PropertyType, propDef); + if (propDef.GetMethod != null) { + // Create mapping - used in debugger + CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef); + MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[propDef.GetMethod.MetadataToken.ToInt32()], propDef); + astProp.Getter = new Accessor(); astProp.Getter.Body = CreateMethodBody(propDef.GetMethod); - astProp.AddAnnotation(propDef.GetMethod); + astProp.Getter.AddAnnotation(propDef.GetMethod); ConvertAttributes(astProp.Getter, propDef.GetMethod); if ((getterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask)) astProp.Getter.Modifiers = getterModifiers & Modifiers.VisibilityMask; + + astProp.Getter.WithAnnotation(methodMapping); } if (propDef.SetMethod != null) { + // Create mapping - used in debugger + CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef); + MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[propDef.SetMethod.MetadataToken.ToInt32()], propDef); + astProp.Setter = new Accessor(); astProp.Setter.Body = CreateMethodBody(propDef.SetMethod); astProp.Setter.AddAnnotation(propDef.SetMethod); ConvertAttributes(astProp.Setter, propDef.SetMethod); - ConvertCustomAttributes(astProp.Setter, propDef.SetMethod.Parameters.Last(), "param"); + ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault(); + if (lastParam != null) { + ConvertCustomAttributes(astProp.Setter, lastParam, "param"); + if (lastParam.HasMarshalInfo) { + astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" }); + } + } if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask)) astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask; + + astProp.Setter.WithAnnotation(methodMapping); } ConvertCustomAttributes(astProp, propDef); - + + MemberDeclaration member = astProp; if(propDef.IsIndexer()) - return ConvertPropertyToIndexer(astProp, propDef); - else - return astProp; + member = ConvertPropertyToIndexer(astProp, propDef); + if(!accessor.HasOverrides && !accessor.DeclaringType.IsInterface) + if (accessor.IsVirtual == accessor.IsNewSlot) + SetNewModifier(member); + return member; } IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef) @@ -821,17 +971,34 @@ namespace ICSharpCode.Decompiler.Ast astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod); else astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType); + if (eventDef.AddMethod != null) { + // Create mapping - used in debugger + CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef); + MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[eventDef.AddMethod.MetadataToken.ToInt32()], eventDef); + astEvent.AddAccessor = new Accessor { Body = CreateMethodBody(eventDef.AddMethod) }.WithAnnotation(eventDef.AddMethod); ConvertAttributes(astEvent.AddAccessor, eventDef.AddMethod); + + astEvent.AddAccessor.WithAnnotation(methodMapping); } if (eventDef.RemoveMethod != null) { + // Create mapping - used in debugger + CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef); + MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[eventDef.RemoveMethod.MetadataToken.ToInt32()], eventDef); + astEvent.RemoveAccessor = new Accessor { Body = CreateMethodBody(eventDef.RemoveMethod) }.WithAnnotation(eventDef.RemoveMethod); ConvertAttributes(astEvent.RemoveAccessor, eventDef.RemoveMethod); + + astEvent.RemoveAccessor.WithAnnotation(methodMapping); + } + MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod; + if (accessor.IsVirtual == accessor.IsNewSlot) { + SetNewModifier(astEvent); } return astEvent; } @@ -842,13 +1009,15 @@ namespace ICSharpCode.Decompiler.Ast BlockStatement CreateMethodBody(MethodDefinition method, IEnumerable parameters = null) { if (DecompileMethodBodies) - return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters); + return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters, LocalVariables); else return null; } FieldDeclaration CreateField(FieldDefinition fieldDef) { + this.DecompiledMemberReferences.Add(fieldDef.MetadataToken.ToInt32(), fieldDef); + FieldDeclaration astField = new FieldDeclaration(); astField.AddAnnotation(fieldDef); VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name)); @@ -856,21 +1025,30 @@ namespace ICSharpCode.Decompiler.Ast astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef); astField.Modifiers = ConvertModifiers(fieldDef); if (fieldDef.HasConstant) { - if (fieldDef.Constant == null) { - initializer.Initializer = new NullReferenceExpression(); - } else { - TypeCode c = Type.GetTypeCode(fieldDef.Constant.GetType()); - if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !fieldDef.DeclaringType.IsEnum) { - initializer.Initializer = MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, fieldDef.Constant, false), fieldDef.FieldType); - } else { - initializer.Initializer = new PrimitiveExpression(fieldDef.Constant); - } - } + initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum); } ConvertAttributes(astField, fieldDef); + SetNewModifier(astField); return astField; } + static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false) + { + if (constant == null) { + if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1")) + return new DefaultValueExpression(ConvertType(type)); + else + return new NullReferenceExpression(); + } else { + TypeCode c = Type.GetTypeCode(constant.GetType()); + if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) { + return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type); + } else { + return new PrimitiveExpression(constant); + } + } + } + public static IEnumerable MakeParameters(MethodDefinition method, bool isLambda = false) { var parameters = MakeParameters(method.Parameters, isLambda); @@ -896,12 +1074,16 @@ namespace ICSharpCode.Decompiler.Ast if (ct != null && ct.PointerRank > 0) ct.PointerRank--; } + if (paramDef.HasCustomAttributes) { foreach (CustomAttribute ca in paramDef.CustomAttributes) { if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System") astParam.ParameterModifier = ParameterModifier.Params; } } + if (paramDef.IsOptional) { + astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType); + } ConvertCustomAttributes(astParam, paramDef); ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module; @@ -922,6 +1104,7 @@ namespace ICSharpCode.Decompiler.Ast void ConvertAttributes(AttributedNode attributedNode, TypeDefinition typeDefinition) { ConvertCustomAttributes(attributedNode, typeDefinition); + ConvertSecurityAttributes(attributedNode, typeDefinition); // Handle the non-custom attributes: #region SerializableAttribute @@ -972,11 +1155,12 @@ namespace ICSharpCode.Decompiler.Ast void ConvertAttributes(AttributedNode attributedNode, MethodDefinition methodDefinition) { ConvertCustomAttributes(attributedNode, methodDefinition); + ConvertSecurityAttributes(attributedNode, methodDefinition); MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; #region DllImportAttribute - if (methodDefinition.HasPInvokeInfo) { + if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) { PInvokeInfo info = methodDefinition.PInvokeInfo; Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute)); dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name)); @@ -1065,9 +1249,14 @@ namespace ICSharpCode.Decompiler.Ast } #endregion - ConvertCustomAttributes(attributedNode, methodDefinition.MethodReturnType, "return"); - if (methodDefinition.MethodReturnType.HasMarshalInfo) { - var marshalInfo = ConvertMarshalInfo(methodDefinition.MethodReturnType, methodDefinition.Module); + ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module); + } + + void ConvertAttributes(AttributedNode attributedNode, MethodReturnType methodReturnType, ModuleDefinition module) + { + ConvertCustomAttributes(attributedNode, methodReturnType, "return"); + if (methodReturnType.HasMarshalInfo) { + var marshalInfo = ConvertMarshalInfo(methodReturnType, module); attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" }); } } @@ -1103,6 +1292,37 @@ namespace ICSharpCode.Decompiler.Ast Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module); var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib); attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType)); + + FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; + if (fami != null) { + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size)); + if (fami.ElementType != NativeType.None) + attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType)); + } + SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; + if (sami != null && sami.ElementType != VariantType.None) { + var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib); + attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum)); + } + ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; + if (ami != null) { + if (ami.ElementType != NativeType.Max) + attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType)); + if (ami.Size >= 0) + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size)); + if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) + attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex)); + } + CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; + if (cmi != null) { + attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName)); + if (!string.IsNullOrEmpty(cmi.Cookie)) + attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie)); + } + FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; + if (fssmi != null) { + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size)); + } return attr; } #endregion @@ -1192,6 +1412,65 @@ namespace ICSharpCode.Decompiler.Ast } } + static void ConvertSecurityAttributes(AstNode attributedNode, ISecurityDeclarationProvider secDeclProvider, string attributeTarget = null) + { + if (!secDeclProvider.HasSecurityDeclarations) + return; + var attributes = new List(); + foreach (var secDecl in secDeclProvider.SecurityDeclarations) { + foreach (var secAttribute in secDecl.SecurityAttributes) { + var attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); + attribute.AddAnnotation(secAttribute); + attribute.Type = ConvertType(secAttribute.AttributeType); + attributes.Add(attribute); + + SimpleType st = attribute.Type as SimpleType; + if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { + st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length); + } + + var module = secAttribute.AttributeType.Module; + var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib); + attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType)); + + if (secAttribute.HasProperties) { + TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); + foreach (var propertyNamedArg in secAttribute.Properties) { + var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null; + var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference); + var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument); + attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); + } + } + + if (secAttribute.HasFields) { + TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); + foreach (var fieldNamedArg in secAttribute.Fields) { + var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null; + var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference); + var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument); + attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue)); + } + } + } + } + if (attributeTarget == "module" || attributeTarget == "assembly") { + // use separate section for each attribute + foreach (var attribute in attributes) { + var section = new AttributeSection(); + section.AttributeTarget = attributeTarget; + section.Attributes.Add(attribute); + attributedNode.AddChild(section, AttributedNode.AttributeRole); + } + } else if (attributes.Count > 0) { + // use single section for all attributes + var section = new AttributeSection(); + section.AttributeTarget = attributeTarget; + section.Attributes.AddRange(attributes); + attributedNode.AddChild(section, AttributedNode.AttributeRole); + } + } + private static Expression ConvertArgumentValue(CustomAttributeArgument argument) { if (argument.Value is CustomAttributeArgument[]) { @@ -1212,9 +1491,7 @@ namespace ICSharpCode.Decompiler.Ast if (type != null && type.IsEnum) { return MakePrimitive(Convert.ToInt64(argument.Value), type); } else if (argument.Value is TypeReference) { - return new TypeOfExpression() { - Type = ConvertType((TypeReference)argument.Value), - }; + return CreateTypeOfExpression((TypeReference)argument.Value); } else { return new PrimitiveExpression(argument.Value); } @@ -1233,13 +1510,13 @@ namespace ICSharpCode.Decompiler.Ast { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs) TypeDefinition enumDefinition = type.Resolve(); if (enumDefinition != null && enumDefinition.IsEnum) { + TypeCode enumBaseTypeCode = TypeCode.Int32; foreach (FieldDefinition field in enumDefinition.Fields) { if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val)) - return ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + return ConvertType(type).Member(field.Name).WithAnnotation(field); else if (!field.IsStatic && field.IsRuntimeSpecialName) - type = field.FieldType; // use primitive type of the enum + enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum } - TypeCode enumBaseTypeCode = TypeAnalysis.GetTypeCode(type); if (IsFlagsEnum(enumDefinition)) { long enumValue = val; Expression expr = null; @@ -1266,7 +1543,7 @@ namespace ICSharpCode.Decompiler.Ast continue; // skip None enum value if ((fieldValue & enumValue) == fieldValue) { - var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field); if (expr == null) expr = fieldExpression; else @@ -1275,7 +1552,7 @@ namespace ICSharpCode.Decompiler.Ast enumValue &= ~fieldValue; } if ((fieldValue & negatedEnumValue) == fieldValue) { - var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field); if (negatedExpr == null) negatedExpr = fieldExpression; else @@ -1293,7 +1570,7 @@ namespace ICSharpCode.Decompiler.Ast return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr); } } - return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(enumDefinition)); + return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type)); } } TypeCode code = TypeAnalysis.GetTypeCode(type); @@ -1309,5 +1586,88 @@ namespace ICSharpCode.Decompiler.Ast return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute"); } + + /// + /// Sets new modifier if the member hides some other member from a base type. + /// + /// The node of the member which new modifier state should be determined. + static void SetNewModifier(AttributedNode member) + { + try { + bool addNewModifier = false; + if (member is IndexerDeclaration) { + var propertyDef = member.Annotation(); + var baseProperties = + TypesHierarchyHelpers.FindBaseProperties(propertyDef); + addNewModifier = baseProperties.Any(); + } else + addNewModifier = HidesBaseMember(member); + + if (addNewModifier) + member.Modifiers |= Modifiers.New; + } + catch (ReferenceResolvingException) { + // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. + } + } + + private static bool HidesBaseMember(AttributedNode member) + { + var memberDefinition = member.Annotation(); + bool addNewModifier = false; + var methodDefinition = memberDefinition as MethodDefinition; + if (methodDefinition != null) { + addNewModifier = HidesByName(memberDefinition, includeBaseMethods: false); + if (!addNewModifier) + addNewModifier = TypesHierarchyHelpers.FindBaseMethods(methodDefinition).Any(); + } else + addNewModifier = HidesByName(memberDefinition, includeBaseMethods: true); + return addNewModifier; + } + + /// + /// Determines whether any base class member has the same name as the given member. + /// + /// The derived type's member. + /// true if names of methods declared in base types should also be checked. + /// true if any base member has the same name as given member, otherwise false. + static bool HidesByName(IMemberDefinition member, bool includeBaseMethods) + { + Debug.Assert(!(member is PropertyDefinition) || !((PropertyDefinition)member).IsIndexer()); + + if (member.DeclaringType.BaseType != null) { + var baseTypeRef = member.DeclaringType.BaseType; + while (baseTypeRef != null) { + var baseType = baseTypeRef.ResolveOrThrow(); + if (baseType.HasProperties && AnyIsHiddenBy(baseType.Properties, member, m => !m.IsIndexer())) + return true; + if (baseType.HasEvents && AnyIsHiddenBy(baseType.Events, member)) + return true; + if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member)) + return true; + if (includeBaseMethods && baseType.HasMethods + && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName)) + return true; + if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member)) + return true; + baseTypeRef = baseType.BaseType; + } + } + return false; + } + + static bool AnyIsHiddenBy(IEnumerable members, IMemberDefinition derived, Predicate condition = null) + where T : IMemberDefinition + { + return members.Any(m => m.Name == derived.Name + && (condition == null || condition(m)) + && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType)); + } + + /// + /// Gets the local variables for the current decompiled type, method, etc. + /// The key is the metadata token. + /// + public ConcurrentDictionary> LocalVariables { get; private set; } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 368dadefd8..cab334432f 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -1,3 +1,21 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -32,9 +50,16 @@ namespace ICSharpCode.Decompiler.Ast /// Decompilation context. /// Parameter declarations of the method being decompiled. /// These are used to update the parameter names when the decompiler generates names for the parameters. + /// Local variables storage that will be filled/updated with the local variables. /// Block for the method body - public static BlockStatement CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable parameters = null) + public static BlockStatement CreateMethodBody(MethodDefinition methodDef, + DecompilerContext context, + IEnumerable parameters = null, + ConcurrentDictionary> localVariables = null) { + if (localVariables == null) + localVariables = new ConcurrentDictionary>(); + MethodDefinition oldCurrentMethod = context.CurrentMethod; Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef); context.CurrentMethod = methodDef; @@ -44,10 +69,10 @@ namespace ICSharpCode.Decompiler.Ast builder.context = context; builder.typeSystem = methodDef.Module.TypeSystem; if (Debugger.IsAttached) { - return builder.CreateMethodBody(parameters); + return builder.CreateMethodBody(parameters, localVariables); } else { try { - return builder.CreateMethodBody(parameters); + return builder.CreateMethodBody(parameters, localVariables); } catch (OperationCanceledException) { throw; } catch (Exception ex) { @@ -59,10 +84,14 @@ namespace ICSharpCode.Decompiler.Ast } } - public BlockStatement CreateMethodBody(IEnumerable parameters) + public BlockStatement CreateMethodBody(IEnumerable parameters, + ConcurrentDictionary> localVariables) { if (methodDef.Body == null) return null; + if (localVariables == null) + throw new ArgumentException("localVariables must be instantiated"); + context.CancellationToken.ThrowIfCancellationRequested(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); @@ -102,6 +131,10 @@ namespace ICSharpCode.Decompiler.Ast astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); } + // store the variables - used for debugger + int token = methodDef.MetadataToken.ToInt32(); + localVariables.AddOrUpdate(token, allVariables, (key, oldValue) => allVariables); + return astBlock; } @@ -215,10 +248,20 @@ namespace ICSharpCode.Decompiler.Ast { AstNode node = TransformByteCode(expr); Expression astExpr = node as Expression; + + // get IL ranges - used in debugger + List ilRanges = ILRange.OrderAndJoint(expr.GetSelfAndChildrenRecursive().SelectMany(e => e.ILRanges)); + AstNode result; + if (astExpr != null) - return Convert(astExpr, expr.InferredType, expr.ExpectedType); + result = Convert(astExpr, expr.InferredType, expr.ExpectedType); else - return node; + result = node; + + if (result != null) + return result.WithAnnotation(ilRanges); + + return result; } AstNode TransformByteCode(ILExpression byteCode) @@ -306,8 +349,7 @@ namespace ICSharpCode.Decompiler.Ast } #endregion #region Arrays - case ILCode.Newarr: - case ILCode.InitArray: { + case ILCode.Newarr: { var ace = new Ast.ArrayCreateExpression(); ace.Type = operandAsTypeRef; ComposedType ct = operandAsTypeRef as ComposedType; @@ -323,7 +365,39 @@ namespace ICSharpCode.Decompiler.Ast } return ace; } - case ILCode.Ldlen: return arg1.Member("Length"); + case ILCode.InitArray: { + var ace = new Ast.ArrayCreateExpression(); + ace.Type = operandAsTypeRef; + ComposedType ct = operandAsTypeRef as ComposedType; + var arrayType = (ArrayType) operand; + if (ct != null) + { + // change "new (int[,])[10] to new int[10][,]" + ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); + ace.Initializer = new ArrayInitializerExpression(); + var first = ace.AdditionalArraySpecifiers.First(); + first.Remove(); + ace.Arguments.AddRange(Enumerable.Repeat(0, first.Dimensions).Select(i => new EmptyExpression())); + } + var newArgs = new List(); + foreach (var arrayDimension in arrayType.Dimensions.Skip(1).Reverse()) + { + int length = (int)arrayDimension.UpperBound - (int)arrayDimension.LowerBound; + for (int j = 0; j < args.Count; j += length) + { + var child = new ArrayInitializerExpression(); + child.Elements.AddRange(args.GetRange(j, length)); + newArgs.Add(child); + } + var temp = args; + args = newArgs; + newArgs = temp; + newArgs.Clear(); + } + ace.Initializer.Elements.AddRange(args); + return ace; + } + case ILCode.Ldlen: return arg1.Member("Length"); case ILCode.Ldelem_I: case ILCode.Ldelem_I1: case ILCode.Ldelem_I2: @@ -460,9 +534,12 @@ namespace ICSharpCode.Decompiler.Ast return arg1; else return arg1.CastTo(operandAsTypeRef); - case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); - case ILCode.Box: return arg1; - case ILCode.Unbox: return InlineAssembly(byteCode, args); + case ILCode.Isinst: + return arg1.CastAs(operandAsTypeRef); + case ILCode.Box: + return arg1; + case ILCode.Unbox: + return MakeRef(arg1.CastTo(operandAsTypeRef)); #endregion #region Indirect case ILCode.Ldind_Ref: @@ -514,11 +591,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Endfilter: return InlineAssembly(byteCode, args); case ILCode.Endfinally: return null; case ILCode.Initblk: return InlineAssembly(byteCode, args); - case ILCode.Initobj: - if (args[0] is DirectionExpression) - return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), MakeDefaultValue((TypeReference)operand)); - else - return InlineAssembly(byteCode, args); + case ILCode.Initobj: return InlineAssembly(byteCode, args); case ILCode.DefaultValue: return MakeDefaultValue((TypeReference)operand); case ILCode.Jmp: return InlineAssembly(byteCode, args); @@ -577,7 +650,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is Cecil.TypeReference) { - return new Ast.TypeOfExpression { Type = operandAsTypeRef }.Member("TypeHandle"); + return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle"); } else { return InlineAssembly(byteCode, args); } @@ -678,24 +751,81 @@ namespace ICSharpCode.Decompiler.Ast return new Ast.YieldBreakStatement(); case ILCode.YieldReturn: return new Ast.YieldStatement { Expression = arg1 }; - case ILCode.InitCollection: { - ObjectCreateExpression oce = (ObjectCreateExpression)arg1; - oce.Initializer = new ArrayInitializerExpression(); + case ILCode.InitObject: + case ILCode.InitCollection: + { + ArrayInitializerExpression initializer = new ArrayInitializerExpression(); for (int i = 1; i < args.Count; i++) { - ArrayInitializerExpression aie = args[i] as ArrayInitializerExpression; - if (aie != null && aie.Elements.Count == 1) - oce.Initializer.Elements.Add(aie.Elements.Single().Detach()); - else - oce.Initializer.Elements.Add(args[i]); + Match m = objectInitializerPattern.Match(args[i]); + if (m.Success) { + MemberReferenceExpression mre = m.Get("left").Single(); + initializer.Elements.Add( + new NamedArgumentExpression { + Identifier = mre.MemberName, + Expression = m.Get("right").Single().Detach() + }.CopyAnnotationsFrom(mre)); + } else { + m = collectionInitializerPattern.Match(args[i]); + if (m.Success) { + if (m.Get("arg").Count() == 1) { + initializer.Elements.Add(m.Get("arg").Single().Detach()); + } else { + ArrayInitializerExpression argList = new ArrayInitializerExpression(); + foreach (var expr in m.Get("arg")) { + argList.Elements.Add(expr.Detach()); + } + initializer.Elements.Add(argList); + } + } else { + initializer.Elements.Add(args[i]); + } + } + } + ObjectCreateExpression oce = arg1 as ObjectCreateExpression; + DefaultValueExpression dve = arg1 as DefaultValueExpression; + if (oce != null) { + oce.Initializer = initializer; + return oce; + } else if (dve != null) { + oce = new ObjectCreateExpression(dve.Type.Detach()); + oce.CopyAnnotationsFrom(dve); + oce.Initializer = initializer; + return oce; + } else { + return new AssignmentExpression(arg1, initializer); } - return oce; - } - case ILCode.InitCollectionAddMethod: { - var collectionInit = new ArrayInitializerExpression(); - collectionInit.Elements.AddRange(args); - return collectionInit; } - default: throw new Exception("Unknown OpCode: " + byteCode.Code); + case ILCode.InitializedObject: + return new InitializedObjectExpression(); + case ILCode.AddressOf: + return MakeRef(arg1); + default: + throw new Exception("Unknown OpCode: " + byteCode.Code); + } + } + + static readonly AstNode objectInitializerPattern = new AssignmentExpression( + new MemberReferenceExpression { + Target = new InitializedObjectExpression() + }.WithName("left"), + new AnyNode("right") + ); + + static readonly AstNode collectionInitializerPattern = new InvocationExpression { + Target = new MemberReferenceExpression { + Target = new InitializedObjectExpression(), + MemberName = "Add" + }, + Arguments = { new Repeat(new AnyNode("arg")) } + }; + + sealed class InitializedObjectExpression : IdentifierExpression + { + public InitializedObjectExpression() : base("__initialized_object__") {} + + protected override bool DoMatch(AstNode other, Match match) + { + return other is InitializedObjectExpression; } } @@ -810,8 +940,6 @@ namespace ICSharpCode.Decompiler.Ast if (cecilMethod.Name == "Get" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 1) { return target.Indexer(methodArgs); - } else if (cecilMethod.Name == "Address" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 1) { - return MakeRef(target.Indexer(methodArgs)); } else if (cecilMethod.Name == "Set" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 2) { return new AssignmentExpression(target.Indexer(methodArgs.GetRange(0, methodArgs.Count - 1)), methodArgs.Last()); } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs index 0a5348bf47..2e10dfda14 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs @@ -1,9 +1,25 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.TypeSystem; using Mono.Cecil; @@ -12,7 +28,7 @@ namespace ICSharpCode.Decompiler.Ast /// /// ITypeResolveContext implementation that lazily loads types from Cecil. /// - public class CecilTypeResolveContext : ISynchronizedTypeResolveContext, IProjectContent + public class CecilTypeResolveContext : AbstractAnnotatable, ISynchronizedTypeResolveContext, IProjectContent { readonly ModuleDefinition module; readonly string[] namespaces; @@ -76,7 +92,7 @@ namespace ICSharpCode.Decompiler.Ast public IList AssemblyAttributes { get; private set; } - public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { if (typeParameterCount > 0) name = name + "`" + typeParameterCount.ToString(); @@ -98,14 +114,14 @@ namespace ICSharpCode.Decompiler.Ast return null; } - public IEnumerable GetClasses() + public IEnumerable GetTypes() { foreach (TypeDefinition cecilType in module.Types) { yield return GetClass(cecilType); } } - public IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { foreach (TypeDefinition cecilType in module.Types) { if (nameComparer.Equals(nameSpace, cecilType.Namespace)) @@ -144,5 +160,14 @@ namespace ICSharpCode.Decompiler.Ast { // exit from Synchronize() block } + + IEnumerable IProjectContent.Files { + get { return new IParsedFile[0]; } + } + + IParsedFile IProjectContent.GetFile(string fileName) + { + return null; + } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/CommentStatement.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/CommentStatement.cs index 8bbc6deda5..0940c6c5c7 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/CommentStatement.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/CommentStatement.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Linq; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs index cc47456176..4a3f277827 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs index 0c2a60b863..2edd30b591 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using ICSharpCode.NRefactory.CSharp; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/NameVariables.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/NameVariables.cs index 22e32d8f05..f0a862f44c 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/NameVariables.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/NameVariables.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -42,8 +57,23 @@ namespace ICSharpCode.Decompiler.Ast foreach (var p in parameters) nv.AddExistingName(p.Name); foreach (var v in variables) { - if (v.IsGenerated) + if (v.IsGenerated) { + // don't introduce names for variables generated by ILSpy - keep "expr"/"arg" nv.AddExistingName(v.Name); + } else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols) { + string varName = v.OriginalVariable.Name; + if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName)) + { + // don't use the name from the debug symbols if it looks like a generated name + v.Name = null; + } else { + // use the name from the debug symbols + // (but ensure we don't use the same name for two variables) + v.Name = nv.GetAlternativeName(varName); + } + } else { + v.Name = null; + } } // Now generate names: foreach (ILVariable p in parameters) { @@ -51,12 +81,24 @@ namespace ICSharpCode.Decompiler.Ast p.Name = nv.GenerateNameForVariable(p, methodBody); } foreach (ILVariable varDef in variables) { - if (!varDef.IsGenerated) { + if (string.IsNullOrEmpty(varDef.Name)) varDef.Name = nv.GenerateNameForVariable(varDef, methodBody); - } } } + static bool IsValidName(string varName) + { + if (string.IsNullOrEmpty(varName)) + return false; + if (!(char.IsLetter(varName[0]) || varName[0] == '_')) + return false; + for (int i = 1; i < varName.Length; i++) { + if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_')) + return false; + } + return true; + } + DecompilerContext context; List fieldNamesInCurrentType; Dictionary typeNames = new Dictionary(); @@ -107,10 +149,10 @@ namespace ICSharpCode.Decompiler.Ast string nameWithoutDigits = SplitName(oldVariableName, out number); if (!typeNames.ContainsKey(nameWithoutDigits)) { - typeNames.Add(nameWithoutDigits, 0); + typeNames.Add(nameWithoutDigits, number - 1); } int count = ++typeNames[nameWithoutDigits]; - if (count > 1) { + if (count != 1) { return nameWithoutDigits + count.ToString(); } else { return nameWithoutDigits; @@ -255,6 +297,8 @@ namespace ICSharpCode.Decompiler.Ast string GetNameByType(TypeReference type) { + type = TypeAnalysis.UnpackModifiers(type); + GenericInstanceType git = type as GenericInstanceType; if (git != null && git.ElementType.FullName == "System.Nullable`1" && git.GenericArguments.Count == 1) { type = ((GenericInstanceType)type).GenericArguments[0]; @@ -265,6 +309,8 @@ namespace ICSharpCode.Decompiler.Ast name = "array"; } else if (type.IsPointer || type.IsByReference) { name = "ptr"; + } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) { + name = "ex"; } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) { name = type.Name; // remove the 'I' for interfaces diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs index 1013715352..7c8ca1230d 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs @@ -1,10 +1,27 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.ILAst; using ICSharpCode.NRefactory.CSharp; using Mono.Cecil; @@ -15,6 +32,7 @@ namespace ICSharpCode.Decompiler.Ast readonly ITextOutput output; readonly Stack nodeStack = new Stack(); int braceLevelWithinType = -1; + bool inDocumentationComment = false; public TextOutputFormatter(ITextOutput output) { @@ -113,14 +131,56 @@ namespace ICSharpCode.Decompiler.Ast output.Write("*/"); break; case CommentType.Documentation: + if (!inDocumentationComment) + output.MarkFoldStart("///" + content, true); output.Write("///"); - output.WriteLine(content); + output.Write(content); + inDocumentationComment = true; + bool isLastLine = !(nodeStack.Peek().NextSibling is Comment); + if (isLastLine) { + inDocumentationComment = false; + output.MarkFoldEnd(); + } + output.WriteLine(); break; } } public void StartNode(AstNode node) { + // code mappings + var ranges = node.Annotation>(); + if (ranges != null && ranges.Count > 0) { + // find the ancestor that has method mapping as annotation + if (node.Parent != null) + { + var n = node.Ancestors.FirstOrDefault(a => a.Annotation() != null); + if (n != null) { + MemberMapping mapping = n.Annotation(); + + // add all ranges + foreach (var range in ranges) { + mapping.MemberCodeMappings.Add(new SourceCodeMapping { + ILInstructionOffset = range, + SourceCodeLine = output.CurrentLine, + MemberMapping = mapping + }); + } + } + } + } + + // definitions of types and their members + Predicate predicate = n => n is AttributedNode; + + if (predicate(node)) { + var n = node as AttributedNode; + int c = 0; + if (n != null) + c = n.Attributes.Count; + node.AddAnnotation(Tuple.Create(output.CurrentLine + c, output.CurrentColumn)); + } + nodeStack.Push(node); } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs index b8d25a0463..21638c0b40 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Linq; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs index d614d55fb6..24a14b9215 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Linq; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs index 236b95711d..1d1f3d0817 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Diagnostics; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs index 9b83394797..054d3066e3 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.PatternMatching; @@ -54,9 +70,29 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { - var instanceCtors = typeDeclaration.Members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); + // Handle initializers on instance fields + HandleInstanceFieldInitializers(typeDeclaration.Members); + + // Now convert base constructor calls to initializers: + base.VisitTypeDeclaration(typeDeclaration, data); + + // Remove single empty constructor: + RemoveSingleEmptyConstructor(typeDeclaration); + + // Handle initializers on static fields: + HandleStaticFieldInitializers(typeDeclaration.Members); + return null; + } + + void HandleInstanceFieldInitializers(IEnumerable members) + { + var instanceCtors = members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray(); - if (instanceCtorsNotChainingWithThis.Length > 0 && typeDeclaration.ClassType == NRefactory.TypeSystem.ClassType.Class) { + if (instanceCtorsNotChainingWithThis.Length > 0) { + MethodDefinition ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation(); + if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsValueType) + return; + // Recognize field initializers: // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer. bool allSame; @@ -68,7 +104,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms FieldDefinition fieldDef = m.Get("fieldAccess").Single().Annotation().ResolveWithinSameModule(); if (fieldDef == null) break; - AttributedNode fieldOrEventDecl = typeDeclaration.Members.FirstOrDefault(f => f.Annotation() == fieldDef); + AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation() == fieldDef); if (fieldOrEventDecl == null) break; @@ -84,11 +120,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } } while (allSame); } - - // Now convert base constructor calls to initializers: - base.VisitTypeDeclaration(typeDeclaration, data); - - // Remove single empty constructor: + } + + void RemoveSingleEmptyConstructor(TypeDeclaration typeDeclaration) + { + var instanceCtors = typeDeclaration.Members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); if (instanceCtors.Length == 1) { ConstructorDeclaration emptyCtor = new ConstructorDeclaration(); emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public); @@ -96,12 +132,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms if (emptyCtor.IsMatch(instanceCtors[0])) instanceCtors[0].Remove(); } - + } + + void HandleStaticFieldInitializers(IEnumerable members) + { // Convert static constructor into field initializers if the class is BeforeFieldInit - var staticCtor = typeDeclaration.Members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); + var staticCtor = members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); if (staticCtor != null) { - TypeDefinition typeDef = typeDeclaration.Annotation(); - if (typeDef != null && typeDef.IsBeforeFieldInit) { + MethodDefinition ctorMethodDef = staticCtor.Annotation(); + if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) { while (true) { ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; if (es == null) @@ -112,7 +151,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms FieldDefinition fieldDef = assignment.Left.Annotation().ResolveWithinSameModule(); if (fieldDef == null || !fieldDef.IsStatic) break; - FieldDeclaration fieldDecl = typeDeclaration.Members.OfType().FirstOrDefault(f => f.Annotation() == fieldDef); + FieldDeclaration fieldDecl = members.OfType().FirstOrDefault(f => f.Annotation() == fieldDef); if (fieldDecl == null) break; fieldDecl.Variables.Single().Initializer = assignment.Right.Detach(); @@ -122,11 +161,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms staticCtor.Remove(); } } - return null; } void IAstTransform.Run(AstNode node) { + // If we're viewing some set of members (fields are direct children of CompilationUnit), + // we also need to handle those: + HandleInstanceFieldInitializers(node.Children); + HandleStaticFieldInitializers(node.Children); + node.AcceptVisitor(this, null); } } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs new file mode 100644 index 0000000000..298682afb6 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.PatternMatching; +using Mono.Cecil; + +namespace ICSharpCode.Decompiler.Ast.Transforms +{ + /// + /// Transforms decimal constant fields. + /// + public class DecimalConstantTransform : DepthFirstAstVisitor, IAstTransform + { + static readonly PrimitiveType decimalType = new PrimitiveType("decimal"); + + public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + const Modifiers staticReadOnly = Modifiers.Static | Modifiers.Readonly; + if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) { + foreach (var attributeSection in fieldDeclaration.Attributes) { + foreach (var attribute in attributeSection.Attributes) { + TypeReference tr = attribute.Type.Annotation(); + if (tr != null && tr.Name == "DecimalConstantAttribute" && tr.Namespace == "System.Runtime.CompilerServices") { + attribute.Remove(); + if (attributeSection.Attributes.Count == 0) + attributeSection.Remove(); + fieldDeclaration.Modifiers = (fieldDeclaration.Modifiers & ~staticReadOnly) | Modifiers.Const; + return null; + } + } + } + } + return null; + } + + public void Run(AstNode compilationUnit) + { + compilationUnit.AcceptVisitor(this, null); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs index 6fcce7be20..ed21440853 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index 59c90c28c0..0e431e3f84 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -46,7 +61,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { - if (objectCreateExpression.Arguments.Count() == 2) { + if (objectCreateExpression.Arguments.Count == 2) { Expression obj = objectCreateExpression.Arguments.First(); Expression func = objectCreateExpression.Arguments.Last(); Annotation annotation = func.Annotation(); @@ -100,7 +115,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms internal static bool IsAnonymousMethod(DecompilerContext context, MethodDefinition method) { - if (method == null || !method.Name.StartsWith("<", StringComparison.Ordinal)) + if (method == null || !(method.Name.StartsWith("<", StringComparison.Ordinal) || method.Name.Contains("$"))) return false; if (!(method.IsCompilerGenerated() || IsPotentialClosure(context, method.DeclaringType))) return false; @@ -111,6 +126,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms { if (!context.Settings.AnonymousMethods) return false; // anonymous method decompilation is disabled + if (target != null && !(target is IdentifierExpression || target is ThisReferenceExpression || target is NullReferenceExpression)) + return false; // don't copy arbitrary expressions, deal with identifiers only // Anonymous methods are defined in the same assembly MethodDefinition method = methodRef.ResolveWithinSameModule(); @@ -119,6 +136,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms // Create AnonymousMethodExpression and prepare parameters AnonymousMethodExpression ame = new AnonymousMethodExpression(); + ame.CopyAnnotationsFrom(objectCreateExpression); // copy ILRanges etc. + ame.RemoveAnnotations(); // remove reference to delegate ctor + ame.AddAnnotation(method); // add reference to anonymous method ame.Parameters.AddRange(AstBuilder.MakeParameters(method, isLambda: true)); ame.HasParameterList = true; @@ -163,6 +183,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } if (isLambda) { LambdaExpression lambda = new LambdaExpression(); + lambda.CopyAnnotationsFrom(ame); ame.Parameters.MoveTo(lambda.Parameters); Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression; returnExpr.Remove(); @@ -175,7 +196,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return true; } - static bool IsPotentialClosure(DecompilerContext context, TypeDefinition potentialDisplayClass) + internal static bool IsPotentialClosure(DecompilerContext context, TypeDefinition potentialDisplayClass) { if (potentialDisplayClass == null || !potentialDisplayClass.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) return false; @@ -328,12 +349,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms if (right is ThisReferenceExpression) { isParameter = true; } else if (right is IdentifierExpression) { - // handle parameters only if the whole method contains no other occurrance except for 'right' + // handle parameters only if the whole method contains no other occurrence except for 'right' ILVariable v = right.Annotation(); isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1; - if (!isParameter && TypeAnalysis.IsSameType(v.Type, fieldDef.FieldType) && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) { + if (!isParameter && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) { + // parent display class within the same method + // (closure2.localsX = closure1;) isDisplayClassParentPointerAssignment = true; } + } else if (right is MemberReferenceExpression) { + // copy of parent display class reference from an outer lambda + // closure2.localsX = this.localsY + MemberReferenceExpression mre = m.Get("right").Single(); + do { + // descend into the targets of the mre as long as the field types are closures + FieldDefinition fieldDef2 = mre.Annotation().ResolveWithinSameModule(); + if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ResolveWithinSameModule())) { + break; + } + // if we finally get to a this reference, it's copying a display class parent pointer + if (mre.Target is ThisReferenceExpression) { + isDisplayClassParentPointerAssignment = true; + } + mre = mre.Target as MemberReferenceExpression; + } while (mre != null); } if (isParameter || isDisplayClassParentPointerAssignment) { dict[fieldDef] = right; @@ -349,12 +388,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms // Now create variables for all fields of the display class (except for those that we already handled as parameters) List> variablesToDeclare = new List>(); foreach (FieldDefinition field in type.Fields) { + if (field.IsStatic) + continue; // skip static fields if (dict.ContainsKey(field)) // skip field if it already was handled as parameter continue; - EnsureVariableNameIsAvailable(blockStatement, field.Name); - currentlyUsedVariableNames.Add(field.Name); - variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), field.Name)); - dict[field] = new IdentifierExpression(field.Name); + string capturedVariableName = field.Name; + if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10) + capturedVariableName = capturedVariableName.Substring(10); + EnsureVariableNameIsAvailable(blockStatement, capturedVariableName); + currentlyUsedVariableNames.Add(capturedVariableName); + variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), capturedVariableName)); + dict[field] = new IdentifierExpression(capturedVariableName); } // Now figure out where the closure was accessed and use the simpler replacement expression there: diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs index 919731b6ab..c42677d749 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Linq; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs index aad6afa6dc..0da56fe911 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Diagnostics; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs index 958b97c65e..dc7e7f1a5a 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using ICSharpCode.NRefactory.CSharp; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs index ed2fa5b1c6..55d49b977d 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -12,14 +27,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms /// /// Introduces using declarations. /// - public class IntroduceUsingDeclarations : DepthFirstAstVisitor, IAstTransform + public class IntroduceUsingDeclarations : IAstTransform { DecompilerContext context; public IntroduceUsingDeclarations(DecompilerContext context) { this.context = context; - currentNamespace = context.CurrentType != null ? context.CurrentType.Namespace : string.Empty; } public void Run(AstNode compilationUnit) @@ -28,7 +42,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return; // First determine all the namespaces that need to be imported: - compilationUnit.AcceptVisitor(this, null); + compilationUnit.AcceptVisitor(new FindRequiredImports(this), null); importedNamespaces.Add("System"); // always import System, even when not necessary @@ -55,48 +69,60 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } // verify that the SimpleTypes refer to the correct type (no ambiguities) - FullyQualifyAmbiguousTypeNames(compilationUnit); + compilationUnit.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(this), null); } readonly HashSet declaredNamespaces = new HashSet() { string.Empty }; readonly HashSet importedNamespaces = new HashSet(); + // Note that we store type names with `n suffix, so we automatically disambiguate based on number of type parameters. readonly HashSet availableTypeNames = new HashSet(); readonly HashSet ambiguousTypeNames = new HashSet(); - string currentNamespace; - bool IsParentOfCurrentNamespace(string ns) + sealed class FindRequiredImports : DepthFirstAstVisitor { - if (ns.Length == 0) - return true; - if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) { - if (currentNamespace.Length == ns.Length) - return true; - if (currentNamespace[ns.Length] == '.') + readonly IntroduceUsingDeclarations transform; + string currentNamespace; + + public FindRequiredImports(IntroduceUsingDeclarations transform) + { + this.transform = transform; + this.currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty; + } + + bool IsParentOfCurrentNamespace(string ns) + { + if (ns.Length == 0) return true; + if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) { + if (currentNamespace.Length == ns.Length) + return true; + if (currentNamespace[ns.Length] == '.') + return true; + } + return false; } - return false; - } - - public override object VisitSimpleType(SimpleType simpleType, object data) - { - TypeReference tr = simpleType.Annotation(); - if (tr != null && !IsParentOfCurrentNamespace(tr.Namespace)) { - importedNamespaces.Add(tr.Namespace); + + public override object VisitSimpleType(SimpleType simpleType, object data) + { + TypeReference tr = simpleType.Annotation(); + if (tr != null && !IsParentOfCurrentNamespace(tr.Namespace)) { + transform.importedNamespaces.Add(tr.Namespace); + } + return base.VisitSimpleType(simpleType, data); // also visit type arguments + } + + public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + string oldNamespace = currentNamespace; + foreach (Identifier ident in namespaceDeclaration.Identifiers) { + currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name); + transform.declaredNamespaces.Add(currentNamespace); + } + base.VisitNamespaceDeclaration(namespaceDeclaration, data); + currentNamespace = oldNamespace; + return null; } - return base.VisitSimpleType(simpleType, data); // also visit type arguments - } - - public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) - { - string oldNamespace = currentNamespace; - foreach (Identifier ident in namespaceDeclaration.Identifiers) { - currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name); - declaredNamespaces.Add(currentNamespace); - } - base.VisitNamespaceDeclaration(namespaceDeclaration, data); - currentNamespace = oldNamespace; - return null; } void FindAmbiguousTypeNames(ModuleDefinition module, bool internalsVisible) @@ -111,17 +137,176 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } } - void FullyQualifyAmbiguousTypeNames(AstNode compilationUnit) + sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor { - foreach (SimpleType simpleType in compilationUnit.Descendants.OfType()) { + readonly IntroduceUsingDeclarations transform; + string currentNamespace; + HashSet currentMemberTypes; + Dictionary currentMembers; + bool isWithinTypeReferenceExpression; + + public FullyQualifyAmbiguousTypeNamesVisitor(IntroduceUsingDeclarations transform) + { + this.transform = transform; + this.currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty; + } + + public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + string oldNamespace = currentNamespace; + foreach (Identifier ident in namespaceDeclaration.Identifiers) { + currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name); + } + base.VisitNamespaceDeclaration(namespaceDeclaration, data); + currentNamespace = oldNamespace; + return null; + } + + public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + HashSet oldMemberTypes = currentMemberTypes; + currentMemberTypes = currentMemberTypes != null ? new HashSet(currentMemberTypes) : new HashSet(); + + Dictionary oldMembers = currentMembers; + currentMembers = new Dictionary(); + + TypeDefinition typeDef = typeDeclaration.Annotation(); + bool privateMembersVisible = true; + ModuleDefinition internalMembersVisibleInModule = typeDef.Module; + while (typeDef != null) { + foreach (GenericParameter gp in typeDef.GenericParameters) { + currentMemberTypes.Add(gp.Name); + } + foreach (TypeDefinition t in typeDef.NestedTypes) { + if (privateMembersVisible || IsVisible(t, internalMembersVisibleInModule)) + currentMemberTypes.Add(t.Name.Substring(t.Name.LastIndexOf('+') + 1)); + } + + foreach (MethodDefinition method in typeDef.Methods) { + if (privateMembersVisible || IsVisible(method, internalMembersVisibleInModule)) + AddCurrentMember(method); + } + foreach (PropertyDefinition property in typeDef.Properties) { + if (privateMembersVisible || IsVisible(property.GetMethod, internalMembersVisibleInModule) || IsVisible(property.SetMethod, internalMembersVisibleInModule)) + AddCurrentMember(property); + } + foreach (EventDefinition ev in typeDef.Events) { + if (privateMembersVisible || IsVisible(ev.AddMethod, internalMembersVisibleInModule) || IsVisible(ev.RemoveMethod, internalMembersVisibleInModule)) + AddCurrentMember(ev); + } + foreach (FieldDefinition f in typeDef.Fields) { + if (privateMembersVisible || IsVisible(f, internalMembersVisibleInModule)) + AddCurrentMember(f); + } + // repeat with base class: + if (typeDef.BaseType != null) + typeDef = typeDef.BaseType.Resolve(); + else + typeDef = null; + privateMembersVisible = false; + } + + // Now add current members from outer classes: + if (oldMembers != null) { + foreach (var pair in oldMembers) { + // add members from outer classes only if the inner class doesn't define the member + if (!currentMembers.ContainsKey(pair.Key)) + currentMembers.Add(pair.Key, pair.Value); + } + } + + base.VisitTypeDeclaration(typeDeclaration, data); + currentMembers = oldMembers; + return null; + } + + void AddCurrentMember(MemberReference m) + { + MemberReference existingMember; + if (currentMembers.TryGetValue(m.Name, out existingMember)) { + // We keep the existing member assignment if it was from another class (=from a derived class), + // because members in derived classes have precedence over members in base classes. + if (existingMember != null && existingMember.DeclaringType == m.DeclaringType) { + // Use null as value to signalize multiple members with the same name + currentMembers[m.Name] = null; + } + } else { + currentMembers.Add(m.Name, m); + } + } + + bool IsVisible(MethodDefinition m, ModuleDefinition internalMembersVisibleInModule) + { + if (m == null) + return false; + switch (m.Attributes & MethodAttributes.MemberAccessMask) { + case MethodAttributes.FamANDAssem: + case MethodAttributes.Assembly: + return m.Module == internalMembersVisibleInModule; + case MethodAttributes.Family: + case MethodAttributes.FamORAssem: + case MethodAttributes.Public: + return true; + default: + return false; + } + } + + bool IsVisible(FieldDefinition f, ModuleDefinition internalMembersVisibleInModule) + { + if (f == null) + return false; + switch (f.Attributes & FieldAttributes.FieldAccessMask) { + case FieldAttributes.FamANDAssem: + case FieldAttributes.Assembly: + return f.Module == internalMembersVisibleInModule; + case FieldAttributes.Family: + case FieldAttributes.FamORAssem: + case FieldAttributes.Public: + return true; + default: + return false; + } + } + + bool IsVisible(TypeDefinition t, ModuleDefinition internalMembersVisibleInModule) + { + if (t == null) + return false; + switch (t.Attributes & TypeAttributes.VisibilityMask) { + case TypeAttributes.NotPublic: + case TypeAttributes.NestedAssembly: + case TypeAttributes.NestedFamANDAssem: + return t.Module == internalMembersVisibleInModule; + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamORAssem: + case TypeAttributes.NestedPublic: + case TypeAttributes.Public: + return true; + default: + return false; + } + } + + public override object VisitSimpleType(SimpleType simpleType, object data) + { + // Handle type arguments first, so that the fixed-up type arguments get moved over to the MemberType, + // if we're also creating one here. + base.VisitSimpleType(simpleType, data); TypeReference tr = simpleType.Annotation(); - if (tr != null && ambiguousTypeNames.Contains(tr.Name)) { + // Fully qualify any ambiguous type names. + if (tr != null && IsAmbiguous(tr.Namespace, tr.Name)) { AstType ns; if (string.IsNullOrEmpty(tr.Namespace)) { ns = new SimpleType("global"); } else { string[] parts = tr.Namespace.Split('.'); - ns = new SimpleType(parts[0]); + if (IsAmbiguous(string.Empty, parts[0])) { + // conflict between namespace and type name/member name + ns = new MemberType { Target = new SimpleType("global"), IsDoubleColon = true, MemberName = parts[0] }; + } else { + ns = new SimpleType(parts[0]); + } for (int i = 1; i < parts.Length; i++) { ns = new MemberType { Target = ns, MemberName = parts[i] }; } @@ -134,6 +319,41 @@ namespace ICSharpCode.Decompiler.Ast.Transforms simpleType.TypeArguments.MoveTo(mt.TypeArguments); simpleType.ReplaceWith(mt); } + return null; + } + + public override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + isWithinTypeReferenceExpression = true; + base.VisitTypeReferenceExpression(typeReferenceExpression, data); + isWithinTypeReferenceExpression = false; + return null; + } + + bool IsAmbiguous(string ns, string name) + { + // If the type name conflicts with an inner class/type parameter, we need to fully-qualify it: + if (currentMemberTypes != null && currentMemberTypes.Contains(name)) + return true; + // If the type name conflicts with a field/property etc. on the current class, we need to fully-qualify it, + // if we're inside an expression. + if (isWithinTypeReferenceExpression && currentMembers != null) { + MemberReference mr; + if (currentMembers.TryGetValue(name, out mr)) { + // However, in the special case where the member is a field or property with the same type + // as is requested, then we can use the short name (if it's not otherwise ambiguous) + PropertyDefinition prop = mr as PropertyDefinition; + FieldDefinition field = mr as FieldDefinition; + if (!(prop != null && prop.PropertyType.Namespace == ns && prop.PropertyType.Name == name) + && !(field != null && field.FieldType.Namespace == ns && field.FieldType.Name == name)) + return true; + } + } + // If the type is defined in the current namespace, + // then we can use the short name even if we imported type with same name from another namespace. + if (ns == currentNamespace && !string.IsNullOrEmpty(ns)) + return false; + return transform.ambiguousTypeNames.Contains(name); } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs index e8c6191436..3d5c0e596b 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -47,6 +62,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms result = TransformUsings(expressionStatement); if (result != null) return result; + result = TransformNonGenericForEach(expressionStatement); + if (result != null) + return result; } result = TransformFor(expressionStatement); if (result != null) @@ -118,7 +136,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms #endregion /// - /// $type $variable = $initializer; + /// $variable = $initializer; /// static readonly AstNode variableAssignPattern = new ExpressionStatement( new AssignmentExpression( @@ -136,7 +154,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } static readonly AstNode usingTryCatchPattern = new TryCatchStatement { - TryBlock = new AnyNode("body"), + TryBlock = new AnyNode(), FinallyBlock = new BlockStatement { new Choice { { "valueType", @@ -162,44 +180,60 @@ namespace ICSharpCode.Decompiler.Ast.Transforms { Match m1 = variableAssignPattern.Match(node); if (!m1.Success) return null; - AstNode tryCatch = node.NextSibling; + TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement; Match m2 = usingTryCatchPattern.Match(tryCatch); if (!m2.Success) return null; string variableName = m1.Get("variable").Single().Identifier; - if (variableName == m2.Get("ident").Single().Identifier) { - if (m2.Has("valueType")) { - // if there's no if(x!=null), then it must be a value type - ILVariable v = m1.Get("variable").Single().Annotation(); - if (v == null || v.Type == null || !v.Type.IsValueType) - return null; - } - node.Remove(); - BlockStatement body = m2.Get("body").Single(); - UsingStatement usingStatement = new UsingStatement(); - usingStatement.ResourceAcquisition = node.Expression.Detach(); - usingStatement.EmbeddedStatement = body.Detach(); - tryCatch.ReplaceWith(usingStatement); - // Move the variable declaration into the resource acquisition, if possible - // This is necessary for the foreach-pattern to work on the result of the using-pattern - VariableDeclarationStatement varDecl = FindVariableDeclaration(usingStatement, variableName); - if (varDecl != null && varDecl.Parent is BlockStatement) { - Statement declarationPoint; - if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint)) { - // Moving the variable into the UsingStatement is allowed: - usingStatement.ResourceAcquisition = new VariableDeclarationStatement { - Type = (AstType)varDecl.Type.Clone(), - Variables = { - new VariableInitializer { - Name = variableName, - Initializer = m1.Get("initializer").Single().Detach() - }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition) - } - }.CopyAnnotationsFrom(node); + if (variableName != m2.Get("ident").Single().Identifier) + return null; + if (m2.Has("valueType")) { + // if there's no if(x!=null), then it must be a value type + ILVariable v = m1.Get("variable").Single().Annotation(); + if (v == null || v.Type == null || !v.Type.IsValueType) + return null; + } + + // There are two variants of the using statement: + // "using (var a = init)" and "using (expr)". + // The former declares a read-only variable 'a', and the latter declares an unnamed read-only variable + // to store the original value of 'expr'. + // This means that in order to introduce a using statement, in both cases we need to detect a read-only + // variable that is used only within that block. + + if (HasAssignment(tryCatch, variableName)) + return null; + + VariableDeclarationStatement varDecl = FindVariableDeclaration(node, variableName); + if (varDecl == null || !(varDecl.Parent is BlockStatement)) + return null; + + // Validate that the variable is not used after the using statement: + if (!IsVariableValueUnused(varDecl, tryCatch)) + return null; + + node.Remove(); + + UsingStatement usingStatement = new UsingStatement(); + usingStatement.EmbeddedStatement = tryCatch.TryBlock.Detach(); + tryCatch.ReplaceWith(usingStatement); + + // If possible, we'll eliminate the variable completely: + if (usingStatement.EmbeddedStatement.Descendants.OfType().Any(ident => ident.Identifier == variableName)) { + // variable is used, so we'll create a variable declaration + usingStatement.ResourceAcquisition = new VariableDeclarationStatement { + Type = (AstType)varDecl.Type.Clone(), + Variables = { + new VariableInitializer { + Name = variableName, + Initializer = m1.Get("initializer").Single().Detach() + }.CopyAnnotationsFrom(node.Expression) } - } - return usingStatement; + }.CopyAnnotationsFrom(node); + } else { + // the variable is never used; eliminate it: + usingStatement.ResourceAcquisition = m1.Get("initializer").Single().Detach(); } - return null; + return usingStatement; } internal static VariableDeclarationStatement FindVariableDeclaration(AstNode node, string identifier) @@ -217,6 +251,29 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return null; } + /// + /// Gets whether the old variable value (assigned inside 'targetStatement' or earlier) + /// is read anywhere in the remaining scope of the variable declaration. + /// + bool IsVariableValueUnused(VariableDeclarationStatement varDecl, Statement targetStatement) + { + Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); + BlockStatement block = (BlockStatement)varDecl.Parent; + DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(block, context.CancellationToken); + daa.SetAnalyzedRange(targetStatement, block, startInclusive: false); + daa.Analyze(varDecl.Variables.Single().Name); + return daa.UnassignedVariableUses.Count == 0; + } + + // I used this in the first implementation of the using-statement transform, but now no longer + // because there were problems when multiple using statements were using the same variable + // - no single using statement could be transformed without making the C# code invalid, + // but transforming both would work. + // We now use 'IsVariableValueUnused' which will perform the transform + // even if it results in two variables with the same name and overlapping scopes. + // (this issue could be fixed later by renaming one of the variables) + + // I'm not sure whether the other consumers of 'CanMoveVariableDeclarationIntoStatement' should be changed the same way. bool CanMoveVariableDeclarationIntoStatement(VariableDeclarationStatement varDecl, Statement targetStatement, out Statement declarationPoint) { Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); @@ -233,10 +290,28 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } return true; } + + /// + /// Gets whether there is an assignment to 'variableName' anywhere within the given node. + /// + bool HasAssignment(AstNode root, string variableName) + { + foreach (AstNode node in root.DescendantsAndSelf) { + IdentifierExpression ident = node as IdentifierExpression; + if (ident != null && ident.Identifier == variableName) { + if (ident.Parent is AssignmentExpression && ident.Role == AssignmentExpression.LeftRole + || ident.Parent is DirectionExpression) + { + return true; + } + } + } + return false; + } #endregion - #region foreach - static readonly UsingStatement foreachPattern = new UsingStatement { + #region foreach (generic) + static readonly UsingStatement genericForeachPattern = new UsingStatement { ResourceAcquisition = new VariableDeclarationStatement { Type = new AnyNode("enumeratorType"), Variables = { @@ -270,7 +345,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public ForeachStatement TransformForeach(UsingStatement node) { - Match m = foreachPattern.Match(node); + Match m = genericForeachPattern.Match(node); if (!m.Success) return null; if (!(node.Parent is BlockStatement) && m.Has("variablesOutsideLoop")) { @@ -308,8 +383,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms InExpression = m.Get("collection").Single().Detach(), EmbeddedStatement = newBody }; - if (foreachStatement.InExpression is BaseReferenceExpression) - foreachStatement.InExpression = new ThisReferenceExpression(); + if (foreachStatement.InExpression is BaseReferenceExpression) { + foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression); + } node.ReplaceWith(foreachStatement); foreach (Statement stmt in m.Get("variablesOutsideLoop")) { ((BlockStatement)foreachStatement.Parent).Statements.InsertAfter(null, stmt.Detach()); @@ -318,6 +394,117 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } #endregion + #region foreach (non-generic) + ExpressionStatement getEnumeratorPattern = new ExpressionStatement( + new AssignmentExpression( + new NamedNode("left", new IdentifierExpression()), + new AnyNode("collection").ToExpression().Invoke("GetEnumerator") + )); + + TryCatchStatement nonGenericForeachPattern = new TryCatchStatement { + TryBlock = new BlockStatement { + new WhileStatement { + Condition = new IdentifierExpression().WithName("enumerator").Invoke("MoveNext"), + EmbeddedStatement = new BlockStatement { + new AssignmentExpression( + new IdentifierExpression().WithName("itemVar"), + new Choice { + new Backreference("enumerator").ToExpression().Member("Current"), + new CastExpression { + Type = new AnyNode("castType"), + Expression = new Backreference("enumerator").ToExpression().Member("Current") + } + } + ), + new Repeat(new AnyNode("stmt")).ToStatement() + } + }.WithName("loop") + }, + FinallyBlock = new BlockStatement { + new AssignmentExpression( + new IdentifierExpression().WithName("disposable"), + new Backreference("enumerator").ToExpression().CastAs(new TypePattern(typeof(IDisposable))) + ), + new IfElseStatement { + Condition = new BinaryOperatorExpression { + Left = new Backreference("disposable"), + Operator = BinaryOperatorType.InEquality, + Right = new NullReferenceExpression() + }, + TrueStatement = new BlockStatement { + new Backreference("disposable").ToExpression().Invoke("Dispose") + } + } + }}; + + public ForeachStatement TransformNonGenericForEach(ExpressionStatement node) + { + Match m1 = getEnumeratorPattern.Match(node); + if (!m1.Success) return null; + AstNode tryCatch = node.NextSibling; + Match m2 = nonGenericForeachPattern.Match(tryCatch); + if (!m2.Success) return null; + + IdentifierExpression enumeratorVar = m2.Get("enumerator").Single(); + IdentifierExpression itemVar = m2.Get("itemVar").Single(); + WhileStatement loop = m2.Get("loop").Single(); + + // verify that the getEnumeratorPattern assigns to the same variable as the nonGenericForeachPattern is reading from + if (!enumeratorVar.IsMatch(m1.Get("left").Single())) + return null; + + VariableDeclarationStatement enumeratorVarDecl = FindVariableDeclaration(loop, enumeratorVar.Identifier); + if (enumeratorVarDecl == null || !(enumeratorVarDecl.Parent is BlockStatement)) + return null; + + // Find the declaration of the item variable: + // Because we look only outside the loop, we won't make the mistake of moving a captured variable across the loop boundary + VariableDeclarationStatement itemVarDecl = FindVariableDeclaration(loop, itemVar.Identifier); + if (itemVarDecl == null || !(itemVarDecl.Parent is BlockStatement)) + return null; + + // Now verify that we can move the variable declaration in front of the loop: + Statement declarationPoint; + CanMoveVariableDeclarationIntoStatement(itemVarDecl, loop, out declarationPoint); + // We ignore the return value because we don't care whether we can move the variable into the loop + // (that is possible only with non-captured variables). + // We just care that we can move it in front of the loop: + if (declarationPoint != loop) + return null; + + ForeachStatement foreachStatement = new ForeachStatement(); + foreachStatement.VariableType = itemVarDecl.Type.Clone(); + foreachStatement.VariableName = itemVar.Identifier; + BlockStatement body = new BlockStatement(); + foreachStatement.EmbeddedStatement = body; + ((BlockStatement)node.Parent).Statements.InsertBefore(node, foreachStatement); + + body.Add(node.Detach()); + body.Add((Statement)tryCatch.Detach()); + + // Now that we moved the whole try-catch into the foreach loop; verify that we can + // move the enumerator into the foreach loop: + CanMoveVariableDeclarationIntoStatement(enumeratorVarDecl, foreachStatement, out declarationPoint); + if (declarationPoint != foreachStatement) { + // oops, the enumerator variable can't be moved into the foreach loop + // Undo our AST changes: + ((BlockStatement)foreachStatement.Parent).Statements.InsertBefore(foreachStatement, node.Detach()); + foreachStatement.ReplaceWith(tryCatch); + return null; + } + + // Now create the correct body for the foreach statement: + foreachStatement.InExpression = m1.Get("collection").Single().Detach(); + if (foreachStatement.InExpression is BaseReferenceExpression) { + foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression); + } + body.Statements.Clear(); + body.Statements.AddRange(m2.Get("stmt").Select(stmt => stmt.Detach())); + + return foreachStatement; + } + #endregion + #region for static readonly WhileStatement forPattern = new WhileStatement { Condition = new BinaryOperatorExpression { @@ -515,12 +702,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms Match m = switchOnStringPattern.Match(node); if (!m.Success) return null; - if (m.Has("nonNullDefaultStmt") && !m.Has("nullStmt")) - return null; // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment if (!m.Get("switchVar").Single().IsMatch(m.Get("switchExpr").Single())) { AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression; - if (!m.Get("switchVar").Single().IsMatch(assign.Left)) + if (!(assign != null && m.Get("switchVar").Single().IsMatch(assign.Left))) return null; } FieldReference cachedDictField = m.Get("cachedDict").Single().Annotation(); @@ -551,15 +736,21 @@ namespace ICSharpCode.Decompiler.Ast.Transforms block.Statements.Add(new BreakStatement()); section.Statements.Add(block.Detach()); sw.SwitchSections.Add(section); - if (m.Has("nonNullDefaultStmt")) { - section = new SwitchSection(); - section.CaseLabels.Add(new CaseLabel()); - block = new BlockStatement(); - block.Statements.AddRange(m.Get("nonNullDefaultStmt").Select(s => s.Detach())); - block.Add(new BreakStatement()); - section.Statements.Add(block); - sw.SwitchSections.Add(section); - } + } else if (m.Has("nonNullDefaultStmt")) { + sw.SwitchSections.Add( + new SwitchSection { + CaseLabels = { new CaseLabel { Expression = new NullReferenceExpression() } }, + Statements = { new BlockStatement { new BreakStatement() } } + }); + } + if (m.Has("nonNullDefaultStmt")) { + SwitchSection section = new SwitchSection(); + section.CaseLabels.Add(new CaseLabel()); + BlockStatement block = new BlockStatement(); + block.Statements.AddRange(m.Get("nonNullDefaultStmt").Select(s => s.Detach())); + block.Add(new BreakStatement()); + section.Statements.Add(block); + sw.SwitchSections.Add(section); } node.ReplaceWith(sw); return sw; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs index 21c5326355..ee7e0df6e0 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs @@ -1,4 +1,22 @@ -using System; +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.CSharp; diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs index f91d10f654..ba641e77d2 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs @@ -1,4 +1,22 @@ -using System; +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.PatternMatching; @@ -32,7 +50,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" - if (methodRef != null && methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) + if (methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; @@ -79,7 +97,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return null; } if (methodRef.Name == "op_Implicit" && arguments.Length == 1) { - arguments[0].Remove(); // detach argument + invocationExpression.ReplaceWith(arguments[0]); + return null; + } + if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == AstNode.Roles.Condition) { invocationExpression.ReplaceWith(arguments[0]); return null; } @@ -256,7 +277,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms static bool IsWithoutSideEffects(Expression left) { - return left is ThisReferenceExpression || left is IdentifierExpression || left is TypeReferenceExpression; + return left is ThisReferenceExpression || left is IdentifierExpression || left is TypeReferenceExpression || left is BaseReferenceExpression; } void IAstTransform.Run(AstNode node) diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs index 7bcf7ab367..13730ea1de 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Threading; @@ -25,6 +40,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms new AddCheckedBlocks(), new DeclareVariables(context), // should run after most transforms that modify statements new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables + new DecimalConstantTransform(), new IntroduceUsingDeclarations(context), new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods diff --git a/src/Libraries/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/src/Libraries/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs index 4668b1f8f1..8de45cca56 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs @@ -1,4 +1,22 @@ -using System; +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -14,9 +32,9 @@ namespace ICSharpCode.Decompiler.Ast if (resolveTypeArguments) return BaseTypes(derivedType).Any(t => t.Item == baseType); else { - var comparableBaseType = baseType.Resolve(); + var comparableBaseType = baseType.ResolveOrThrow(); while (derivedType.BaseType != null) { - var resolvedBaseType = derivedType.BaseType.Resolve(); + var resolvedBaseType = derivedType.BaseType.ResolveOrThrow(); if (resolvedBaseType == null) return false; if (comparableBaseType == resolvedBaseType) @@ -27,20 +45,44 @@ namespace ICSharpCode.Decompiler.Ast } } + /// + /// Determines whether one method overrides or hides another method. + /// + /// The method declared in a base type. + /// The method declared in a derived type. + /// true if hides or overrides , + /// otherwise false. public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod) { + if (parentMethod == null) + throw new ArgumentNullException("parentMethod"); + if (childMethod == null) + throw new ArgumentNullException("childMethod"); + if (parentMethod.Name != childMethod.Name) return false; if (parentMethod.HasParameters || childMethod.HasParameters) - if(!parentMethod.HasParameters || ! childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count) + if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count) return false; return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.); } + /// + /// Determines whether a property overrides or hides another property. + /// + /// The property declared in a base type. + /// The property declared in a derived type. + /// true if the hides or overrides , + /// otherwise false. public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty) { + if (parentProperty == null) + throw new ArgumentNullException("parentProperty"); + if (childProperty == null) + throw new ArgumentNullException("childProperty"); + if (parentProperty.Name != childProperty.Name) return false; @@ -51,52 +93,148 @@ namespace ICSharpCode.Decompiler.Ast return FindBaseProperties(childProperty).Any(m => m == parentProperty); } + public static bool IsBaseEvent(EventDefinition parentEvent, EventDefinition childEvent) + { + if (parentEvent.Name != childEvent.Name) + return false; + + return FindBaseEvents(childEvent).Any(m => m == parentEvent); + } + + /// + /// Finds all methods from base types overridden or hidden by the specified method. + /// + /// The method which overrides or hides methods from base types. + /// Methods overriden or hidden by the specified method. public static IEnumerable FindBaseMethods(MethodDefinition method) { + if (method == null) + throw new ArgumentNullException("method"); + var typeContext = CreateGenericContext(method.DeclaringType); var gMethod = typeContext.ApplyTo(method); foreach (var baseType in BaseTypes(method.DeclaringType)) foreach (var baseMethod in baseType.Item.Methods) - if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisbleFrom(baseMethod, method)) { + if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisibleFromDerived(baseMethod, method.DeclaringType)) { yield return baseMethod; - if (!(baseMethod.IsNewSlot ^ baseMethod.IsVirtual)) + if (baseMethod.IsNewSlot == baseMethod.IsVirtual) yield break; } } + /// + /// Finds all properties from base types overridden or hidden by the specified property. + /// + /// The property which overrides or hides properties from base types. + /// Properties overriden or hidden by the specified property. public static IEnumerable FindBaseProperties(PropertyDefinition property) { + if (property == null) + throw new ArgumentNullException("property"); + + if ((property.GetMethod ?? property.SetMethod).HasOverrides) + yield break; + var typeContext = CreateGenericContext(property.DeclaringType); var gProperty = typeContext.ApplyTo(property); + bool isIndexer = property.IsIndexer(); foreach (var baseType in BaseTypes(property.DeclaringType)) foreach (var baseProperty in baseType.Item.Properties) - if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) && IsVisbleFrom(baseProperty, property)) { + if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) + && IsVisibleFromDerived(baseProperty, property.DeclaringType)) { + if (isIndexer != baseProperty.IsIndexer()) + continue; yield return baseProperty; var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod; - if (!(anyPropertyAccessor.IsNewSlot ^ anyPropertyAccessor.IsVirtual)) + if (anyPropertyAccessor.IsNewSlot == anyPropertyAccessor.IsVirtual) + yield break; + } + } + + public static IEnumerable FindBaseEvents(EventDefinition eventDef) + { + if (eventDef == null) + throw new ArgumentNullException("eventDef"); + + var typeContext = CreateGenericContext(eventDef.DeclaringType); + var gEvent = typeContext.ApplyTo(eventDef); + + foreach (var baseType in BaseTypes(eventDef.DeclaringType)) + foreach (var baseEvent in baseType.Item.Events) + if (MatchEvent(baseType.ApplyTo(baseEvent), gEvent) && IsVisibleFromDerived(baseEvent, eventDef.DeclaringType)) { + yield return baseEvent; + var anyEventAccessor = baseEvent.AddMethod ?? baseEvent.RemoveMethod; + if (anyEventAccessor.IsNewSlot == anyEventAccessor.IsVirtual) yield break; } } - private static bool IsVisbleFrom(MethodDefinition baseCandidate, MethodDefinition method) + /// + /// Determinates whether member of the base type is visible from a derived type. + /// + /// The member which visibility is checked. + /// The derived type. + /// true if the member is visible from derived type, othewise false. + public static bool IsVisibleFromDerived(IMemberDefinition baseMember, TypeDefinition derivedType) { - if (baseCandidate.IsPrivate) - return false; - if ((baseCandidate.IsAssembly || baseCandidate.IsFamilyAndAssembly) && baseCandidate.Module != method.Module) + if (baseMember == null) + throw new ArgumentNullException("baseMember"); + if (derivedType == null) + throw new ArgumentNullException("derivedType"); + + var visibility = IsVisibleFromDerived(baseMember); + if (visibility.HasValue) + return visibility.Value; + + if (baseMember.DeclaringType.Module == derivedType.Module) + return true; + // TODO: Check also InternalsVisibleToAttribute. return false; - return true; } - private static bool IsVisbleFrom(PropertyDefinition baseCandidate, PropertyDefinition property) + private static bool? IsVisibleFromDerived(IMemberDefinition member) { - if (baseCandidate.GetMethod != null && property.GetMethod != null && IsVisbleFrom(baseCandidate.GetMethod, property.GetMethod)) - return true; - if (baseCandidate.SetMethod != null && property.SetMethod != null && IsVisbleFrom(baseCandidate.SetMethod, property.SetMethod)) + MethodAttributes attrs = GetAccessAttributes(member) & MethodAttributes.MemberAccessMask; + if (attrs == MethodAttributes.Private) + return false; + if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem) + return null; return true; - return false; + } + + private static MethodAttributes GetAccessAttributes(IMemberDefinition member) + { + var fld = member as FieldDefinition; + if (fld != null) + return (MethodAttributes)fld.Attributes; + + var method = member as MethodDefinition; + if (method != null) + return method.Attributes; + + var prop = member as PropertyDefinition; + if (prop != null) { + return (prop.GetMethod ?? prop.SetMethod).Attributes; + } + + var evnt = member as EventDefinition; + if (evnt != null) { + return (evnt.AddMethod ?? evnt.RemoveMethod).Attributes; + } + + var nestedType = member as TypeDefinition; + if (nestedType != null) { + if (nestedType.IsNestedPrivate) + return MethodAttributes.Private; + if (nestedType.IsNestedAssembly || nestedType.IsNestedFamilyAndAssembly) + return MethodAttributes.Assembly; + return MethodAttributes.Public; + } + + throw new NotSupportedException(); } private static bool MatchMethod(GenericContext candidate, GenericContext method) @@ -109,7 +247,7 @@ namespace ICSharpCode.Decompiler.Ast if (mCandidate.HasOverrides) return false; - if (!IsSameType(candidate.Resolve(mCandidate.ReturnType), method.Resolve(mMethod.ReturnType))) + if (mCandidate.IsSpecialName != method.Item.IsSpecialName) return false; if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) { @@ -130,6 +268,22 @@ namespace ICSharpCode.Decompiler.Ast return true; } + public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType) + { + var candidateContext = CreateGenericContext(candidate.DeclaringType); + var gCandidate = candidateContext.ApplyTo(candidate); + + if (interfaceContextType is GenericInstanceType) { + var methodContext = new GenericContext(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments); + var gMethod = methodContext.ApplyTo(method); + return MatchMethod(gCandidate, gMethod); + } else { + var methodContext = CreateGenericContext(interfaceContextType.Resolve()); + var gMethod = candidateContext.ApplyTo(method); + return MatchMethod(gCandidate, gMethod); + } + } + private static bool MatchProperty(GenericContext candidate, GenericContext property) { var mCandidate = candidate.Item; @@ -140,9 +294,6 @@ namespace ICSharpCode.Decompiler.Ast if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides) return false; - if (!IsSameType(candidate.Resolve(mCandidate.PropertyType), property.Resolve(mProperty.PropertyType))) - return false; - if (mCandidate.HasParameters || mProperty.HasParameters) { if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count) return false; @@ -156,10 +307,29 @@ namespace ICSharpCode.Decompiler.Ast return true; } + private static bool MatchEvent(GenericContext candidate, GenericContext ev) + { + var mCandidate = candidate.Item; + var mEvent = ev.Item; + if (mCandidate.Name != mEvent.Name) + return false; + + if ((mCandidate.AddMethod ?? mCandidate.RemoveMethod).HasOverrides) + return false; + + if (!IsSameType(candidate.ResolveWithContext(mCandidate.EventType), ev.ResolveWithContext(mEvent.EventType))) + return false; + + return true; + } + private static bool MatchParameters(GenericContext baseParameterType, GenericContext parameterType) { - var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType); - var param = parameterType.Resolve(parameterType.Item.ParameterType); + if (baseParameterType.Item.IsIn != parameterType.Item.IsIn || + baseParameterType.Item.IsOut != parameterType.Item.IsOut) + return false; + var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType); + var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType); return IsSameType(baseParam, param); } @@ -170,8 +340,12 @@ namespace ICSharpCode.Decompiler.Ast if (tr1 == null || tr2 == null) return false; + if (tr1.GetType() != tr2.GetType()) + return false; + if (tr1.Name == tr2.Name && tr1.FullName == tr2.FullName) return true; + return false; } @@ -186,10 +360,10 @@ namespace ICSharpCode.Decompiler.Ast var baseType = type.Item.BaseType; var genericBaseType = baseType as GenericInstanceType; if (genericBaseType != null) { - type = new GenericContext(genericBaseType.Resolve(), - genericBaseType.GenericArguments.Select(t => type.Resolve(t))); + type = new GenericContext(genericBaseType.ResolveOrThrow(), + genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t))); } else - type = new GenericContext(baseType.Resolve()); + type = new GenericContext(baseType.ResolveOrThrow()); yield return type; } } @@ -201,21 +375,31 @@ namespace ICSharpCode.Decompiler.Ast : new GenericContext(type); } - struct GenericContext + struct GenericContext where T : class { private static readonly ReadOnlyCollection Empty = new ReadOnlyCollection(new List()); + private static readonly GenericParameter UnresolvedGenericTypeParameter = + new DummyGenericParameterProvider(false).DummyParameter; + private static readonly GenericParameter UnresolvedGenericMethodParameter = + new DummyGenericParameterProvider(true).DummyParameter; public readonly T Item; public readonly ReadOnlyCollection TypeArguments; public GenericContext(T item) { + if (item == null) + throw new ArgumentNullException("item"); + Item = item; TypeArguments = Empty; } public GenericContext(T item, IEnumerable typeArguments) { + if (item == null) + throw new ArgumentNullException("item"); + Item = item; var list = new List(); foreach (var arg in typeArguments) { @@ -231,31 +415,102 @@ namespace ICSharpCode.Decompiler.Ast TypeArguments = typeArguments; } - public TypeReference Resolve(TypeReference type) + public TypeReference ResolveWithContext(TypeReference type) { var genericParameter = type as GenericParameter; - if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) { + if (genericParameter != null) + if (genericParameter.Owner.GenericParameterType == GenericParameterType.Type) return this.TypeArguments[genericParameter.Position]; + else + return genericParameter.Owner.GenericParameterType == GenericParameterType.Type + ? UnresolvedGenericTypeParameter : UnresolvedGenericMethodParameter; + var typeSpecification = type as TypeSpecification; + if (typeSpecification != null) { + var resolvedElementType = ResolveWithContext(typeSpecification.ElementType); + return ReplaceElementType(typeSpecification, resolvedElementType); } - var arrayType = type as ArrayType; + return type.ResolveOrThrow(); + } + + private TypeReference ReplaceElementType(TypeSpecification ts, TypeReference newElementType) + { + var arrayType = ts as ArrayType; if (arrayType != null) { - var resolvedElementType = Resolve(arrayType.ElementType); - if (resolvedElementType == null) - return null; - if (resolvedElementType == arrayType.ElementType) + if (newElementType == arrayType.ElementType) return arrayType; - var newArrayType = new ArrayType(resolvedElementType, arrayType.Rank); + var newArrayType = new ArrayType(newElementType, arrayType.Rank); for (int dimension = 0; dimension < arrayType.Rank; dimension++) newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension]; return newArrayType; } - return type.Resolve(); + var byReferenceType = ts as ByReferenceType; + if (byReferenceType != null) { + return new ByReferenceType(newElementType); + } + // TODO: should we throw an exception instead calling Resolve method? + return ts.ResolveOrThrow(); } - public GenericContext ApplyTo(T2 item) + public GenericContext ApplyTo(T2 item) where T2 : class { return new GenericContext(item, this.TypeArguments); } + + private class DummyGenericParameterProvider : IGenericParameterProvider + { + readonly Mono.Cecil.GenericParameterType type; + readonly Mono.Collections.Generic.Collection parameters; + + public DummyGenericParameterProvider(bool methodTypeParameter) + { + type = methodTypeParameter ? Mono.Cecil.GenericParameterType.Method : + Mono.Cecil.GenericParameterType.Type; + parameters = new Mono.Collections.Generic.Collection(1); + parameters.Add(new GenericParameter(this)); + } + + public GenericParameter DummyParameter + { + get { return parameters[0]; } + } + + bool IGenericParameterProvider.HasGenericParameters + { + get { throw new NotImplementedException(); } + } + + bool IGenericParameterProvider.IsDefinition + { + get { throw new NotImplementedException(); } + } + + ModuleDefinition IGenericParameterProvider.Module + { + get { throw new NotImplementedException(); } + } + + Mono.Collections.Generic.Collection IGenericParameterProvider.GenericParameters + { + get { return parameters; } + } + + GenericParameterType IGenericParameterProvider.GenericParameterType + { + get { return type; } + } + + MetadataToken IMetadataTokenProvider.MetadataToken + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + } } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/CecilExtensions.cs b/src/Libraries/ICSharpCode.Decompiler/CecilExtensions.cs index 5e806e7af2..46d4719573 100644 --- a/src/Libraries/ICSharpCode.Decompiler/CecilExtensions.cs +++ b/src/Libraries/ICSharpCode.Decompiler/CecilExtensions.cs @@ -185,7 +185,15 @@ namespace ICSharpCode.Decompiler else return null; } - + + public static TypeDefinition ResolveOrThrow(this TypeReference typeReference) + { + var resolved = typeReference.Resolve(); + if (resolved == null) + throw new ReferenceResolvingException(); + return resolved; + } + public static bool IsCompilerGenerated(this ICustomAttributeProvider provider) { if (provider != null && provider.HasCustomAttributes) { diff --git a/src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs b/src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs new file mode 100644 index 0000000000..20bcbf2d37 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs @@ -0,0 +1,346 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.ILAst; +using ICSharpCode.NRefactory.CSharp; +using Mono.Cecil; + +namespace ICSharpCode.Decompiler +{ + public enum DecompiledLanguages + { + IL, + CSharp + } + + /// + /// Base class for decompliler classes : AstBuilder & ReflectionDisassembler. + /// + public abstract class BaseCodeMappings + { + /// + /// Gets the code mappings. + /// Key is the metadata token. + /// + public Dictionary> CodeMappings { get; protected set; } + + /// + /// Gets the MembeReference that is decompiled (a MethodDefinition, PropertyDefinition etc.) + /// Key is the metadata token. + /// + public Dictionary DecompiledMemberReferences { get; protected set; } + + /// + /// Create data in the CodeMappings and DecompiledMemberReferences. + /// + /// Token of the current method. + /// Current member (MethodDefinition, PropertyDefinition, EventDefinition). + /// The token is used in CodeMappings; member (and its token) is used in DecompiledMemberReferences. + protected virtual void CreateCodeMappings(int token, MemberReference member) + { + this.CodeMappings.Add(token, new List()); + + int t = member.MetadataToken.ToInt32(); + if (!this.DecompiledMemberReferences.ContainsKey(t)) + this.DecompiledMemberReferences.Add(t, member); + } + } + + /// + /// Maps the source code to IL. + /// + public sealed class SourceCodeMapping + { + /// + /// Gets or sets the source code line number in the output. + /// + public int SourceCodeLine { get; internal set; } + + /// + /// Gets or sets IL Range offset for the source code line. E.g.: 13-19 <-> 135. + /// + public ILRange ILInstructionOffset { get; internal set; } + + /// + /// Gets or sets the member mapping this source code mapping belongs to. + /// + public MemberMapping MemberMapping { get; internal set; } + + /// + /// Retrieves the array that contains the IL range and the missing gaps between ranges. + /// + /// The array representation of the step aranges. + public int[] ToArray(bool isMatch) + { + var currentList = new List(); + + // add list for the current source code line + currentList.AddRange(ILRange.OrderAndJoint(MemberMapping.MemberCodeMappings + .FindAll(m => m.SourceCodeLine == this.SourceCodeLine) + .ConvertAll(m => m.ILInstructionOffset))); + + if (!isMatch) { + // add inverted + currentList.AddRange(MemberMapping.InvertedList); + } else { + // if the current list contains the last mapping, add also the last gap + var lastInverted = MemberMapping.InvertedList.LastOrDefault(); + if (lastInverted != null && lastInverted.From == currentList[currentList.Count - 1].To) + currentList.Add(lastInverted); + } + + // set the output + var resultList = new List(); + foreach (var element in ILRange.OrderAndJoint(currentList)) { + resultList.Add(element.From); + resultList.Add(element.To); + } + + return resultList.ToArray(); + } + } + + /// + /// Stores the method information and its source code mappings. + /// + public sealed class MemberMapping + { + IEnumerable invertedList; + + /// + /// Gets or sets the type of the mapping. + /// + public MemberReference MemberReference { get; internal set; } + + /// + /// Metadata token of the member. + /// + public int MetadataToken { get; internal set; } + + /// + /// Gets or sets the code size for the member mapping. + /// + public int CodeSize { get; internal set; } + + /// + /// Gets or sets the source code mappings. + /// + public List MemberCodeMappings { get; internal set; } + + /// + /// Gets the inverted IL Ranges.
+ /// E.g.: for (0-9, 11-14, 14-18, 21-25) => (9-11,18-21). + ///
+ /// IL Range inverted list. + public IEnumerable InvertedList + { + get { + if (invertedList == null) { + var list = MemberCodeMappings.ConvertAll( + s => new ILRange { From = s.ILInstructionOffset.From, To = s.ILInstructionOffset.To }); + invertedList = ILRange.OrderAndJoint(ILRange.Invert(list, CodeSize)); + } + return invertedList; + } + } + } + + /// + /// Code mappings helper class. + /// + public static class CodeMappings + { + /// + /// Create code mapping for a method. + /// + /// Method to create the mapping for. + /// Source code mapping storage. + /// The actual member reference. + internal static MemberMapping CreateCodeMapping( + this MethodDefinition member, + List codeMappings, + MemberReference actualMemberReference = null) + { + if (member == null || !member.HasBody) + return null; + + if (codeMappings == null) + return null; + + // create IL/CSharp code mappings - used in debugger + MemberMapping currentMemberMapping = null; + + if (codeMappings.Find(map => map.MetadataToken == member.MetadataToken.ToInt32()) == null) { + currentMemberMapping = new MemberMapping() { + MetadataToken = member.MetadataToken.ToInt32(), + MemberCodeMappings = new List(), + MemberReference = actualMemberReference ?? member, + CodeSize = member.Body.CodeSize + }; + + codeMappings.Add(currentMemberMapping); + } + + return currentMemberMapping; + } + + /// + /// Gets source code mapping and metadata token based on type name and line number. + /// + /// Code mappings storage. + /// Member reference name. + /// Line number. + /// Metadata token. + /// + public static SourceCodeMapping GetInstructionByLineNumber( + this List codeMappings, + int lineNumber, + out int metadataToken) + { + if (codeMappings == null) + throw new ArgumentException("CodeMappings storage must be valid!"); + + foreach (var maping in codeMappings) { + var map = maping.MemberCodeMappings.Find(m => m.SourceCodeLine == lineNumber); + if (map != null) { + metadataToken = maping.MetadataToken; + return map; + } + } + + metadataToken = 0; + return null; + } + + /// + /// Gets a mapping given a type, a token and an IL offset. + /// + /// Code mappings storage. + /// Token. + /// IL offset. + /// True, if perfect match. + /// A code mapping. + public static SourceCodeMapping GetInstructionByTokenAndOffset( + this List codeMappings, + int token, + int ilOffset, + out bool isMatch) + { + isMatch = false; + + if (codeMappings == null) + throw new ArgumentNullException("CodeMappings storage must be valid!"); + + var maping = codeMappings.Find(m => m.MetadataToken == token); + + if (maping == null) + return null; + + // try find an exact match + var map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= ilOffset && ilOffset < m.ILInstructionOffset.To); + + if (map == null) { + // get the immediate next one + map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From > ilOffset); + isMatch = false; + if (map == null) + map = maping.MemberCodeMappings.LastOrDefault(); // get the last + + return map; + } + + isMatch = true; + return map; + } + + /// + /// Gets the source code and type name from metadata token and offset. + /// + /// Code mappings storage. + /// Metadata token. + /// IL offset. + /// Type definition. + /// Line number. + /// It is possible to exist to different types from different assemblies with the same metadata token. + public static bool GetInstructionByTokenAndOffset( + this List codeMappings, + int token, + int ilOffset, + out MemberReference member, + out int line) + { + member = null; + line = 0; + + if (codeMappings == null) + throw new ArgumentException("CodeMappings storage must be valid!"); + + var mapping = codeMappings.Find(m => m.MetadataToken == token); + if (mapping == null) + return false; + + var codeMapping = mapping.MemberCodeMappings.Find( + cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To - 1); + if (codeMapping == null) { + codeMapping = mapping.MemberCodeMappings.Find(cm => cm.ILInstructionOffset.From > ilOffset); + if (codeMapping == null) { + codeMapping = mapping.MemberCodeMappings.LastOrDefault(); + if (codeMapping == null) + return false; + } + } + + member = mapping.MemberReference; + line = codeMapping.SourceCodeLine; + return true; + } + } + + /// + /// Decompilation data. Can be used by other applications to store the decompilation data. + /// + public class DecompileInformation + { + /// + /// Gets ot sets the code mappings + /// + public Dictionary> CodeMappings { get; set; } + + /// + /// Gets or sets the local variables. + /// + public ConcurrentDictionary> LocalVariables { get; set; } + + /// + /// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc) + /// + public Dictionary DecompiledMemberReferences { get; set; } + + /// + /// Gets (or internal sets) the AST nodes. + /// + public IEnumerable AstNodes { get; set; } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/DecompilerException.cs b/src/Libraries/ICSharpCode.Decompiler/DecompilerException.cs index c7316f775b..d62b516da4 100644 --- a/src/Libraries/ICSharpCode.Decompiler/DecompilerException.cs +++ b/src/Libraries/ICSharpCode.Decompiler/DecompilerException.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Runtime.Serialization; diff --git a/src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs b/src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs index 6c93f1d440..4d5d62d76c 100644 --- a/src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.ComponentModel; @@ -164,6 +179,51 @@ namespace ICSharpCode.Decompiler } } + bool useDebugSymbols = true; + + /// + /// Gets/Sets whether to use variable names from debug symbols, if available. + /// + public bool UseDebugSymbols { + get { return useDebugSymbols; } + set { + if (useDebugSymbols != value) { + useDebugSymbols = value; + OnPropertyChanged("UseDebugSymbols"); + } + } + } + + bool objectCollectionInitializers = true; + + /// + /// Gets/Sets whether to use C# 3.0 object/collection initializers + /// + public bool ObjectOrCollectionInitializers { + get { return objectCollectionInitializers; } + set { + if (objectCollectionInitializers != value) { + objectCollectionInitializers = value; + OnPropertyChanged("ObjectCollectionInitializers"); + } + } + } + + bool showXmlDocumentation = true; + + /// + /// Gets/Sets whether to include XML documentation comments in the decompiled code + /// + public bool ShowXmlDocumentation { + get { return showXmlDocumentation; } + set { + if (showXmlDocumentation != value) { + showXmlDocumentation = value; + OnPropertyChanged("ShowXmlDocumentation"); + } + } + } + public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) diff --git a/src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 33032d02ef..df66c26504 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -17,11 +17,32 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using Mono.Cecil; using Mono.Cecil.Cil; namespace ICSharpCode.Decompiler.Disassembler { + public enum ILNameSyntax + { + /// + /// class/valuetype + TypeName (built-in types use keyword syntax) + /// + Signature, + /// + /// Like signature, but always refers to type parameters using their position + /// + SignatureNoNamedTypeParameters, + /// + /// [assembly]Full.Type.Name (even for built-in types) + /// + TypeName, + /// + /// Name (but built-in types use keyword syntax) + /// + ShortTypeName + } + public static class DisassemblerHelpers { public static void WriteOffsetReference(ITextOutput writer, Instruction instruction) @@ -35,6 +56,7 @@ namespace ICSharpCode.Decompiler.Disassembler WriteOffsetReference(writer, exceptionHandler.TryStart); writer.Write('-'); WriteOffsetReference(writer, exceptionHandler.TryEnd); + writer.Write(' '); writer.Write(exceptionHandler.HandlerType.ToString()); if (exceptionHandler.FilterStart != null) { writer.Write(' '); @@ -56,8 +78,14 @@ namespace ICSharpCode.Decompiler.Disassembler writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction); writer.Write(": "); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode); - if(null != instruction.Operand) { + if (instruction.Operand != null) { writer.Write(' '); + if (instruction.OpCode == OpCodes.Ldtoken) { + if (instruction.Operand is MethodReference) + writer.Write("method "); + else if (instruction.Operand is FieldReference) + writer.Write("field "); + } WriteOperand(writer, instruction.Operand); } } @@ -82,93 +110,189 @@ namespace ICSharpCode.Decompiler.Disassembler public static void WriteTo(this MethodReference method, ITextOutput writer) { - if (method.HasThis) + if (method.ExplicitThis) { + writer.Write("instance explicit "); + } + else if (method.HasThis) { writer.Write("instance "); - method.ReturnType.WriteTo(writer); + } + method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); writer.Write(' '); if (method.DeclaringType != null) { - method.DeclaringType.WriteTo(writer, true); + method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write("::"); } - writer.WriteReference(method.Name, method); + MethodDefinition md = method as MethodDefinition; + if (md != null && md.IsCompilerControlled) { + writer.WriteReference(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")), method); + } else { + writer.WriteReference(Escape(method.Name), method); + } + GenericInstanceMethod gim = method as GenericInstanceMethod; + if (gim != null) { + writer.Write('<'); + for (int i = 0; i < gim.GenericArguments.Count; i++) { + if (i > 0) + writer.Write(", "); + gim.GenericArguments[i].WriteTo(writer); + } + writer.Write('>'); + } writer.Write("("); var parameters = method.Parameters; for(int i = 0; i < parameters.Count; ++i) { if (i > 0) writer.Write(", "); - parameters[i].ParameterType.WriteTo(writer); + parameters[i].ParameterType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); } writer.Write(")"); } static void WriteTo(this FieldReference field, ITextOutput writer) { - field.FieldType.WriteTo(writer); + field.FieldType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); writer.Write(' '); - field.DeclaringType.WriteTo(writer); + field.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write("::"); - writer.WriteReference(field.Name, field); + writer.WriteReference(Escape(field.Name), field); + } + + static bool IsValidIdentifierCharacter(char c) + { + return c == '_' || c == '$' || c == '@' || c == '?' || c == '`'; + } + + static bool IsValidIdentifier(string identifier) + { + if (string.IsNullOrEmpty(identifier)) + return false; + if (!(char.IsLetter(identifier[0]) || IsValidIdentifierCharacter(identifier[0]))) { + // As a special case, .ctor and .cctor are valid despite starting with a dot + return identifier == ".ctor" || identifier == ".cctor"; + } + for (int i = 1; i < identifier.Length; i++) { + if (!(char.IsLetterOrDigit(identifier[i]) || IsValidIdentifierCharacter(identifier[i]) || identifier[i] == '.')) + return false; + } + return true; + } + + static readonly HashSet ilKeywords = BuildKeywordList( + "abstract", "algorithm", "alignment", "ansi", "any", "arglist", + "array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit", + "blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr", + "bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf", + "char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal", + "default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern", + "false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime", + "filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref", + "fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal", + "implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init", + "initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall", + "iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr", + "lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested", + "newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand", + "noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable", + "notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out", + "permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6", + "prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected", + "public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval", + "rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname", + "static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct", + "synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref", + "unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype", + "vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper", + + // These are not listed as keywords in spec, but ILAsm treats them as such + "property", "type", "flags", "callconv", "strict" + ); + + static HashSet BuildKeywordList(params string[] keywords) + { + HashSet s = new HashSet(keywords); + foreach (var field in typeof(OpCodes).GetFields()) { + s.Add(((OpCode)field.GetValue(null)).Name); + } + return s; } public static string Escape(string identifier) { - return identifier; + if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) { + return identifier; + } else { + // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence, + // but we follow Microsoft's ILDasm and use \'. + return "'" + NRefactory.CSharp.OutputVisitor.ConvertString(identifier).Replace("'", "\\'") + "'"; + } } - public static void WriteTo(this TypeReference type, ITextOutput writer, bool onlyName = false, bool shortName = false) + public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature) { + ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; if (type is PinnedType) { - writer.Write("pinned "); - ((PinnedType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes); + writer.Write(" pinned"); } else if (type is ArrayType) { ArrayType at = (ArrayType)type; - at.ElementType.WriteTo(writer, onlyName, shortName); + at.ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('['); writer.Write(string.Join(", ", at.Dimensions)); writer.Write(']'); } else if (type is GenericParameter) { - writer.WriteReference(type.Name, type); + writer.Write('!'); + if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method) + writer.Write('!'); + if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) + writer.Write(((GenericParameter)type).Position.ToString()); + else + writer.Write(Escape(type.Name)); } else if (type is ByReferenceType) { - ((ByReferenceType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('&'); } else if (type is PointerType) { - ((PointerType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('*'); } else if (type is GenericInstanceType) { - type.GetElementType().WriteTo(writer, onlyName, shortName); + type.GetElementType().WriteTo(writer, syntaxForElementTypes); writer.Write('<'); var arguments = ((GenericInstanceType)type).GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) writer.Write(", "); - arguments[i].WriteTo(writer, onlyName, shortName); + arguments[i].WriteTo(writer, syntaxForElementTypes); } writer.Write('>'); } else if (type is OptionalModifierType) { - writer.Write("modopt("); - ((OptionalModifierType)type).ModifierType.WriteTo(writer, true, shortName); + ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax); + writer.Write(" modopt("); + ((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((OptionalModifierType)type).ElementType.WriteTo(writer, onlyName, shortName); } else if (type is RequiredModifierType) { - writer.Write("modreq("); - ((RequiredModifierType)type).ModifierType.WriteTo(writer, true, shortName); + ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax); + writer.Write(" modreq("); + ((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((RequiredModifierType)type).ElementType.WriteTo(writer, onlyName, shortName); } else { - string name = PrimitiveTypeName(type); - if (name != null) { + string name = PrimitiveTypeName(type.FullName); + if (syntax == ILNameSyntax.ShortTypeName) { + if (name != null) + writer.Write(name); + else + writer.WriteReference(Escape(type.Name), type); + } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) { writer.Write(name); } else { - if (!onlyName) + if (syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) writer.Write(type.IsValueType ? "valuetype " : "class "); if (type.DeclaringType != null) { - type.DeclaringType.WriteTo(writer, true, shortName); + type.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write('/'); writer.WriteReference(Escape(type.Name), type); } else { - if (!type.IsDefinition && type.Scope != null && !shortName && !(type is TypeSpecification)) + if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification)) writer.Write("[{0}]", Escape(type.Scope.Name)); - writer.WriteReference(shortName ? type.Name : type.FullName, type); + writer.WriteReference(Escape(type.FullName), type); } } } @@ -193,7 +317,19 @@ namespace ICSharpCode.Decompiler.Disassembler VariableReference variableRef = operand as VariableReference; if (variableRef != null) { - writer.WriteReference(variableRef.Index.ToString(), variableRef); + if (string.IsNullOrEmpty(variableRef.Name)) + writer.WriteReference(variableRef.Index.ToString(), variableRef); + else + writer.WriteReference(Escape(variableRef.Name), variableRef); + return; + } + + ParameterReference paramRef = operand as ParameterReference; + if (paramRef != null) { + if (string.IsNullOrEmpty(paramRef.Name)) + writer.WriteReference(paramRef.Index.ToString(), paramRef); + else + writer.WriteReference(Escape(paramRef.Name), paramRef); return; } @@ -205,7 +341,7 @@ namespace ICSharpCode.Decompiler.Disassembler TypeReference typeRef = operand as TypeReference; if (typeRef != null) { - typeRef.WriteTo(writer); + typeRef.WriteTo(writer, ILNameSyntax.TypeName); return; } @@ -217,17 +353,52 @@ namespace ICSharpCode.Decompiler.Disassembler string s = operand as string; if (s != null) { - writer.Write("\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""); - return; + writer.Write("\"" + NRefactory.CSharp.OutputVisitor.ConvertString(s) + "\""); + } else if (operand is char) { + writer.Write(((int)(char)operand).ToString()); + } else if (operand is float) { + float val = (float)operand; + if (val == 0) { + writer.Write("0.0"); + } else if (float.IsInfinity(val) || float.IsNaN(val)) { + byte[] data = BitConverter.GetBytes(val); + writer.Write('('); + for (int i = 0; i < data.Length; i++) { + if (i > 0) + writer.Write(' '); + writer.Write(data[i].ToString("X2")); + } + writer.Write(')'); + } else { + writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } + } else if (operand is double) { + double val = (double)operand; + if (val == 0) { + writer.Write("0.0"); + } else if (double.IsInfinity(val) || double.IsNaN(val)) { + byte[] data = BitConverter.GetBytes(val); + writer.Write('('); + for (int i = 0; i < data.Length; i++) { + if (i > 0) + writer.Write(' '); + writer.Write(data[i].ToString("X2")); + } + writer.Write(')'); + } else { + writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } + } else if (operand is bool) { + writer.Write((bool)operand ? "true" : "false"); + } else { + s = ToInvariantCultureString(operand); + writer.Write(s); } - - s = ToInvariantCultureString(operand); - writer.Write(s); } - public static string PrimitiveTypeName(this TypeReference type) + public static string PrimitiveTypeName(string fullName) { - switch (type.FullName) { + switch (fullName) { case "System.SByte": return "int8"; case "System.Int16": @@ -258,6 +429,8 @@ namespace ICSharpCode.Decompiler.Disassembler return "char"; case "System.Object": return "object"; + case "System.IntPtr": + return "native int"; default: return null; } diff --git a/src/Libraries/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/src/Libraries/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 5fc29a9bd9..4c681e3c11 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -88,8 +88,10 @@ namespace ICSharpCode.Decompiler.Disassembler : this(ILStructureType.Root, 0, body.CodeSize) { // Build the tree of exception structures: - foreach (ExceptionHandler eh in body.ExceptionHandlers) { - AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); + for (int i = 0; i < body.ExceptionHandlers.Count; i++) { + ExceptionHandler eh = body.ExceptionHandlers[i]; + if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd)) + AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); if (eh.HandlerType == ExceptionHandlerType.Filter) AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh)); AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh)); diff --git a/src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index 32161a3f8f..2fcde23357 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -20,8 +20,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.FlowAnalysis; +using ICSharpCode.Decompiler.ILAst; using Mono.Cecil; using Mono.Cecil.Cil; @@ -45,13 +47,11 @@ namespace ICSharpCode.Decompiler.Disassembler this.cancellationToken = cancellationToken; } - public void Disassemble(MethodBody body) + public void Disassemble(MethodBody body, MemberMapping methodMapping) { + // start writing IL code MethodDefinition method = body.Method; output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); - if (method.HasOverrides) - foreach (var methodOverride in method.Overrides) - output.WriteLine(".override {0}::{1}", methodOverride.DeclaringType.FullName, methodOverride.Name); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine(".maxstack {0}", body.MaxStackSize); if (method.DeclaringType.Module.Assembly.EntryPoint == method) @@ -66,8 +66,12 @@ namespace ICSharpCode.Decompiler.Disassembler foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "] ", v); v.VariableType.WriteTo(output); - output.Write(' '); - output.Write(DisassemblerHelpers.Escape(v.Name)); + if (!string.IsNullOrEmpty(v.Name)) { + output.Write(' '); + output.Write(DisassemblerHelpers.Escape(v.Name)); + } + if (v.Index + 1 < method.Body.Variables.Count) + output.Write(','); output.WriteLine(); } output.Unindent(); @@ -77,20 +81,49 @@ namespace ICSharpCode.Decompiler.Disassembler if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; - WriteStructureBody(new ILStructure(body), ref inst); + HashSet branchTargets = GetBranchTargets(body.Instructions); + WriteStructureBody(new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.CodeSize); } else { foreach (var inst in method.Body.Instructions) { inst.WriteTo(output); + + if (methodMapping != null) { + // add IL code mappings - used in debugger + methodMapping.MemberCodeMappings.Add( + new SourceCodeMapping() { + SourceCodeLine = output.CurrentLine, + ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? method.Body.CodeSize : inst.Next.Offset }, + MemberMapping = methodMapping + }); + } + output.WriteLine(); } - output.WriteLine(); - foreach (var eh in method.Body.ExceptionHandlers) { - eh.WriteTo(output); + if (method.Body.HasExceptionHandlers) { output.WriteLine(); + foreach (var eh in method.Body.ExceptionHandlers) { + eh.WriteTo(output); + output.WriteLine(); + } } } } + HashSet GetBranchTargets(IEnumerable instructions) + { + HashSet branchTargets = new HashSet(); + foreach (var inst in instructions) { + Instruction target = inst.Operand as Instruction; + if (target != null) + branchTargets.Add(target.Offset); + Instruction[] targets = inst.Operand as Instruction[]; + if (targets != null) + foreach (Instruction t in targets) + branchTargets.Add(t.Offset); + } + return branchTargets; + } + void WriteStructureHeader(ILStructure s) { switch (s.Type) { @@ -104,7 +137,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); break; case ILStructureType.Try: - output.WriteLine(".try {"); + output.WriteLine(".try"); + output.WriteLine("{"); break; case ILStructureType.Handler: switch (s.ExceptionHandler.HandlerType) { @@ -113,22 +147,24 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("catch"); if (s.ExceptionHandler.CatchType != null) { output.Write(' '); - s.ExceptionHandler.CatchType.WriteTo(output); + s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName); } - output.WriteLine(" {"); + output.WriteLine(); break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: - output.WriteLine("finally {"); + output.WriteLine("finally"); break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: - output.WriteLine("fault {"); + output.WriteLine("fault"); break; default: throw new NotSupportedException(); } + output.WriteLine("{"); break; case ILStructureType.Filter: - output.WriteLine("filter {"); + output.WriteLine("filter"); + output.WriteLine("{"); break; default: throw new NotSupportedException(); @@ -136,21 +172,44 @@ namespace ICSharpCode.Decompiler.Disassembler output.Indent(); } - void WriteStructureBody(ILStructure s, ref Instruction inst) + void WriteStructureBody(ILStructure s, HashSet branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { + bool isFirstInstructionInStructure = true; + bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); - WriteStructureBody(child, ref inst); + WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { + if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { + output.WriteLine(); // put an empty line after branches, and in front of branch targets + } inst.WriteTo(output); + + // add IL code mappings - used in debugger + if (currentMethodMapping != null) { + currentMethodMapping.MemberCodeMappings.Add( + new SourceCodeMapping() { + SourceCodeLine = output.CurrentLine, + ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset }, + MemberMapping = currentMethodMapping + }); + } + output.WriteLine(); + + prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch + || inst.OpCode.FlowControl == FlowControl.Cond_Branch + || inst.OpCode.FlowControl == FlowControl.Return + || inst.OpCode.FlowControl == FlowControl.Throw; + inst = inst.Next; } + isFirstInstructionInStructure = false; } } diff --git a/src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index db46995626..2ced5f8d98 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -18,8 +18,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; using System.Threading; - using Mono.Cecil; using Mono.Collections.Generic; @@ -28,13 +30,13 @@ namespace ICSharpCode.Decompiler.Disassembler /// /// Disassembles type and member definitions. /// - public sealed class ReflectionDisassembler + public sealed class ReflectionDisassembler : BaseCodeMappings { ITextOutput output; CancellationToken cancellationToken; - bool detectControlStructure; bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings) MethodBodyDisassembler methodBodyDisassembler; + MemberReference currentMember; public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken) { @@ -42,23 +44,27 @@ namespace ICSharpCode.Decompiler.Disassembler throw new ArgumentNullException("output"); this.output = output; this.cancellationToken = cancellationToken; - this.detectControlStructure = detectControlStructure; this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken); + + this.CodeMappings = new Dictionary>(); + this.DecompiledMemberReferences = new Dictionary(); } #region Disassemble Method EnumNameCollection methodAttributeFlags = new EnumNameCollection() { - { MethodAttributes.Static, "static" }, { MethodAttributes.Final, "final" }, - { MethodAttributes.Virtual, "virtual" }, { MethodAttributes.HideBySig, "hidebysig" }, - { MethodAttributes.Abstract, "abstract" }, { MethodAttributes.SpecialName, "specialname" }, - { MethodAttributes.PInvokeImpl, "pinvokeimpl" }, + { MethodAttributes.PInvokeImpl, null }, // handled separately { MethodAttributes.UnmanagedExport, "export" }, { MethodAttributes.RTSpecialName, "rtspecialname" }, - { MethodAttributes.RequireSecObject, "requiresecobj" }, - { MethodAttributes.NewSlot, "newslot" } + { MethodAttributes.RequireSecObject, "reqsecobj" }, + { MethodAttributes.NewSlot, "newslot" }, + { MethodAttributes.CheckAccessOnOverride, "strict" }, + { MethodAttributes.Abstract, "abstract" }, + { MethodAttributes.Virtual, "virtual" }, + { MethodAttributes.Static, "static" }, + { MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm }; EnumNameCollection methodVisibility = new EnumNameCollection() { @@ -76,7 +82,7 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodCallingConvention.ThisCall, "unmanaged thiscall" }, { MethodCallingConvention.FastCall, "unmanaged fastcall" }, { MethodCallingConvention.VarArg, "vararg" }, - { MethodCallingConvention.Generic, "generic" }, + { MethodCallingConvention.Generic, null }, }; EnumNameCollection methodCodeType = new EnumNameCollection() { @@ -90,10 +96,16 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodImplAttributes.Synchronized, "synchronized" }, { MethodImplAttributes.NoInlining, "noinlining" }, { MethodImplAttributes.NoOptimization, "nooptimization" }, + { MethodImplAttributes.PreserveSig, "preservesig" }, + { MethodImplAttributes.InternalCall, "internalcall" }, + { MethodImplAttributes.ForwardRef, "forwardref" }, }; public void DisassembleMethod(MethodDefinition method) { + // set current member + currentMember = method; + // write method header output.WriteDefinition(".method ", method); DisassembleMethodInternal(method); @@ -108,21 +120,71 @@ namespace ICSharpCode.Decompiler.Disassembler //emit flags WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); + if(method.IsCompilerControlled) output.Write("privatescope "); + + if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) { + output.Write("pinvokeimpl"); + if (method.HasPInvokeInfo && method.PInvokeInfo != null) { + PInvokeInfo info = method.PInvokeInfo; + output.Write("(\"" + NRefactory.CSharp.OutputVisitor.ConvertString(info.Module.Name) + "\""); + + if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name) + output.Write(" as \"" + NRefactory.CSharp.OutputVisitor.ConvertString(info.EntryPoint) + "\""); + + if (info.IsNoMangle) + output.Write(" nomangle"); + + if (info.IsCharSetAnsi) + output.Write(" ansi"); + else if (info.IsCharSetAuto) + output.Write(" autochar"); + else if (info.IsCharSetUnicode) + output.Write(" unicode"); + + if (info.SupportsLastError) + output.Write(" lasterr"); + + if (info.IsCallConvCdecl) + output.Write(" cdecl"); + else if (info.IsCallConvFastcall) + output.Write(" fastcall"); + else if (info.IsCallConvStdCall) + output.Write(" stdcall"); + else if (info.IsCallConvThiscall) + output.Write(" thiscall"); + else if (info.IsCallConvWinapi) + output.Write(" winapi"); + + output.Write(')'); + } + output.Write(' '); + } output.WriteLine(); output.Indent(); - - if (method.HasThis) + if (method.ExplicitThis) { + output.Write("instance explicit "); + } else if (method.HasThis) { output.Write("instance "); + } //call convention WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention); - //return type method.ReturnType.WriteTo(output); output.Write(' '); - output.Write(DisassemblerHelpers.Escape(method.Name)); + if (method.MethodReturnType.HasMarshalInfo) { + WriteMarshalInfo(method.MethodReturnType.MarshalInfo); + } + + if (method.IsCompilerControlled) { + output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8"))); + } else { + output.Write(DisassemblerHelpers.Escape(method.Name)); + } + + WriteTypeParameters(output, method); //( params ) output.Write(" ("); @@ -142,31 +204,455 @@ namespace ICSharpCode.Decompiler.Disassembler WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); output.Unindent(); - if (method.HasBody || method.HasCustomAttributes) { - OpenBlock(defaultCollapsed: isInType); - WriteAttributes(method.CustomAttributes); - - if (method.HasBody) - methodBodyDisassembler.Disassemble(method.Body); - - CloseBlock("End of method " + method.DeclaringType.Name + "." + method.Name); + OpenBlock(defaultCollapsed: isInType); + WriteAttributes(method.CustomAttributes); + if (method.HasOverrides) { + foreach (var methodOverride in method.Overrides) { + output.Write(".override method "); + methodOverride.WriteTo(output); + output.WriteLine(); + } + } + foreach (var p in method.Parameters) { + WriteParameterAttributes(p); + } + WriteSecurityDeclarations(method); + + if (method.HasBody) { + // create IL code mappings - used in debugger + CreateCodeMappings(method.MetadataToken.ToInt32(), currentMember); + MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[method.MetadataToken.ToInt32()], currentMember); + methodBodyDisassembler.Disassemble(method.Body, methodMapping); + } + + CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); + } + + #region Write Security Declarations + void WriteSecurityDeclarations(ISecurityDeclarationProvider secDeclProvider) + { + if (!secDeclProvider.HasSecurityDeclarations) + return; + foreach (var secdecl in secDeclProvider.SecurityDeclarations) { + output.Write(".permissionset "); + switch (secdecl.Action) { + case SecurityAction.Request: + output.Write("request"); + break; + case SecurityAction.Demand: + output.Write("demand"); + break; + case SecurityAction.Assert: + output.Write("assert"); + break; + case SecurityAction.Deny: + output.Write("deny"); + break; + case SecurityAction.PermitOnly: + output.Write("permitonly"); + break; + case SecurityAction.LinkDemand: + output.Write("linkcheck"); + break; + case SecurityAction.InheritDemand: + output.Write("inheritcheck"); + break; + case SecurityAction.RequestMinimum: + output.Write("reqmin"); + break; + case SecurityAction.RequestOptional: + output.Write("reqopt"); + break; + case SecurityAction.RequestRefuse: + output.Write("reqrefuse"); + break; + case SecurityAction.PreJitGrant: + output.Write("prejitgrant"); + break; + case SecurityAction.PreJitDeny: + output.Write("prejitdeny"); + break; + case SecurityAction.NonCasDemand: + output.Write("noncasdemand"); + break; + case SecurityAction.NonCasLinkDemand: + output.Write("noncaslinkdemand"); + break; + case SecurityAction.NonCasInheritance: + output.Write("noncasinheritance"); + break; + default: + output.Write(secdecl.Action.ToString()); + break; + } + output.WriteLine(" = {"); + output.Indent(); + for (int i = 0; i < secdecl.SecurityAttributes.Count; i++) { + SecurityAttribute sa = secdecl.SecurityAttributes[i]; + if (sa.AttributeType.Scope == sa.AttributeType.Module) { + output.Write("class "); + output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(sa.AttributeType))); + } else { + sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName); + } + output.Write(" = {"); + if (sa.HasFields || sa.HasProperties) { + output.WriteLine(); + output.Indent(); + + foreach (CustomAttributeNamedArgument na in sa.Fields) { + output.Write("field "); + WriteSecurityDeclarationArgument(na); + output.WriteLine(); + } + + foreach (CustomAttributeNamedArgument na in sa.Properties) { + output.Write("property "); + WriteSecurityDeclarationArgument(na); + output.WriteLine(); + } + + output.Unindent(); + } + output.Write('}'); + + if (i + 1< secdecl.SecurityAttributes.Count) + output.Write(','); + output.WriteLine(); + } + output.Unindent(); + output.WriteLine("}"); + } + } + + void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na) + { + TypeReference type = na.Argument.Type; + if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) { + output.Write("enum "); + if (type.Scope != type.Module) { + output.Write("class "); + output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type))); + } else { + type.WriteTo(output, ILNameSyntax.TypeName); + } } else { - output.WriteLine(); + type.WriteTo(output); + } + output.Write(' '); + output.Write(DisassemblerHelpers.Escape(na.Name)); + output.Write(" = "); + if (na.Argument.Value is string) { + // secdecls use special syntax for strings + output.Write("string('{0}')", NRefactory.CSharp.OutputVisitor.ConvertString((string)na.Argument.Value).Replace("'", "\'")); + } else { + WriteConstant(na.Argument.Value); + } + } + + string GetAssemblyQualifiedName(TypeReference type) + { + AssemblyNameReference anr = type.Scope as AssemblyNameReference; + if (anr == null) { + ModuleDefinition md = type.Scope as ModuleDefinition; + if (md != null) { + anr = md.Assembly.Name; + } + } + if (anr != null) { + return type.FullName + ", " + anr.FullName; + } else { + return type.FullName; + } + } + #endregion + + #region WriteMarshalInfo + void WriteMarshalInfo(MarshalInfo marshalInfo) + { + output.Write("marshal("); + WriteNativeType(marshalInfo.NativeType, marshalInfo); + output.Write(") "); + } + + void WriteNativeType(NativeType nativeType, MarshalInfo marshalInfo = null) + { + switch (nativeType) { + case NativeType.None: + break; + case NativeType.Boolean: + output.Write("bool"); + break; + case NativeType.I1: + output.Write("int8"); + break; + case NativeType.U1: + output.Write("unsigned int8"); + break; + case NativeType.I2: + output.Write("int16"); + break; + case NativeType.U2: + output.Write("unsigned int16"); + break; + case NativeType.I4: + output.Write("int32"); + break; + case NativeType.U4: + output.Write("unsigned int32"); + break; + case NativeType.I8: + output.Write("int64"); + break; + case NativeType.U8: + output.Write("unsigned int64"); + break; + case NativeType.R4: + output.Write("float32"); + break; + case NativeType.R8: + output.Write("float64"); + break; + case NativeType.LPStr: + output.Write("lpstr"); + break; + case NativeType.Int: + output.Write("int"); + break; + case NativeType.UInt: + output.Write("unsigned int"); + break; + case NativeType.Func: + goto default; // ?? + case NativeType.Array: + ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo; + if (ami == null) + goto default; + if (ami.ElementType != NativeType.Max) + WriteNativeType(ami.ElementType); + output.Write('['); + if (ami.SizeParameterMultiplier == 0) { + output.Write(ami.Size.ToString()); + } else { + if (ami.Size >= 0) + output.Write(ami.Size.ToString()); + output.Write(" + "); + output.Write(ami.SizeParameterIndex.ToString()); + } + output.Write(']'); + break; + case NativeType.Currency: + output.Write("currency"); + break; + case NativeType.BStr: + output.Write("bstr"); + break; + case NativeType.LPWStr: + output.Write("lpwstr"); + break; + case NativeType.LPTStr: + output.Write("lptstr"); + break; + case NativeType.FixedSysString: + output.Write("fixed sysstring[{0}]", ((FixedSysStringMarshalInfo)marshalInfo).Size); + break; + case NativeType.IUnknown: + output.Write("iunknown"); + break; + case NativeType.IDispatch: + output.Write("idispatch"); + break; + case NativeType.Struct: + output.Write("struct"); + break; + case NativeType.IntF: + output.Write("interface"); + break; + case NativeType.SafeArray: + output.Write("safearray "); + SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; + if (sami != null) { + switch (sami.ElementType) { + case VariantType.None: + break; + case VariantType.I2: + output.Write("int16"); + break; + case VariantType.I4: + output.Write("int32"); + break; + case VariantType.R4: + output.Write("float32"); + break; + case VariantType.R8: + output.Write("float64"); + break; + case VariantType.CY: + output.Write("currency"); + break; + case VariantType.Date: + output.Write("date"); + break; + case VariantType.BStr: + output.Write("bstr"); + break; + case VariantType.Dispatch: + output.Write("idispatch"); + break; + case VariantType.Error: + output.Write("error"); + break; + case VariantType.Bool: + output.Write("bool"); + break; + case VariantType.Variant: + output.Write("variant"); + break; + case VariantType.Unknown: + output.Write("iunknown"); + break; + case VariantType.Decimal: + output.Write("decimal"); + break; + case VariantType.I1: + output.Write("int8"); + break; + case VariantType.UI1: + output.Write("unsigned int8"); + break; + case VariantType.UI2: + output.Write("unsigned int16"); + break; + case VariantType.UI4: + output.Write("unsigned int32"); + break; + case VariantType.Int: + output.Write("int"); + break; + case VariantType.UInt: + output.Write("unsigned int"); + break; + default: + output.Write(sami.ElementType.ToString()); + break; + } + } + break; + case NativeType.FixedArray: + output.Write("fixed array"); + FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; + if (fami != null) { + output.Write("[{0}]", fami.Size); + if (fami.ElementType != NativeType.None) { + output.Write(' '); + WriteNativeType(fami.ElementType); + } + } + break; + case NativeType.ByValStr: + output.Write("byvalstr"); + break; + case NativeType.ANSIBStr: + output.Write("ansi bstr"); + break; + case NativeType.TBStr: + output.Write("tbstr"); + break; + case NativeType.VariantBool: + output.Write("variant bool"); + break; + case NativeType.ASAny: + output.Write("as any"); + break; + case NativeType.LPStruct: + output.Write("lpstruct"); + break; + case NativeType.CustomMarshaler: + CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; + if (cmi == null) + goto default; + output.Write("custom(\"{0}\", \"{1}\"", + NRefactory.CSharp.OutputVisitor.ConvertString(cmi.ManagedType.FullName), + NRefactory.CSharp.OutputVisitor.ConvertString(cmi.Cookie)); + if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) { + output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.OutputVisitor.ConvertString(cmi.UnmanagedType)); + } + output.Write(')'); + break; + case NativeType.Error: + output.Write("error"); + break; + default: + output.Write(nativeType.ToString()); + break; } } + #endregion void WriteParameters(Collection parameters) { for (int i = 0; i < parameters.Count; i++) { var p = parameters[i]; + if (p.IsIn) + output.Write("[in] "); + if (p.IsOut) + output.Write("[out] "); + if (p.IsOptional) + output.Write("[opt] "); p.ParameterType.WriteTo(output); output.Write(' '); + if (p.HasMarshalInfo) { + WriteMarshalInfo(p.MarshalInfo); + } output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p); if (i < parameters.Count - 1) output.Write(','); output.WriteLine(); } } + + bool HasParameterAttributes(ParameterDefinition p) + { + return p.HasConstant || p.HasCustomAttributes; + } + + void WriteParameterAttributes(ParameterDefinition p) + { + if (!HasParameterAttributes(p)) + return; + output.Write(".param [{0}]", p.Index + 1); + if (p.HasConstant) { + output.Write(" = "); + WriteConstant(p.Constant); + } + output.WriteLine(); + WriteAttributes(p.CustomAttributes); + } + + void WriteConstant(object constant) + { + if (constant == null) { + output.Write("nullref"); + } else { + string typeName = DisassemblerHelpers.PrimitiveTypeName(constant.GetType().FullName); + if (typeName != null && typeName != "string") { + output.Write(typeName); + output.Write('('); + float? cf = constant as float?; + double? cd = constant as double?; + if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) { + output.Write("0x{0:x8}", BitConverter.ToInt32(BitConverter.GetBytes(cf.Value), 0)); + } else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) { + output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value)); + } else { + DisassemblerHelpers.WriteOperand(output, constant); + } + output.Write(')'); + } else { + DisassemblerHelpers.WriteOperand(output, constant); + } + } + } #endregion #region Disassemble Field @@ -190,22 +676,31 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleField(FieldDefinition field) { + // create mappings for decompiled fields only + this.DecompiledMemberReferences.Add(field.MetadataToken.ToInt32(), field); + output.WriteDefinition(".field ", field); WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); - WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | FieldAttributes.HasDefault), fieldAttributes); + const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA; + WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes); + if (field.HasMarshalInfo) { + WriteMarshalInfo(field.MarshalInfo); + } field.FieldType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(field.Name)); + if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) { + output.Write(" at I_{0:x8}", field.RVA); + } if (field.HasConstant) { output.Write(" = "); - DisassemblerHelpers.WriteOperand(output, field.Constant); + WriteConstant(field.Constant); } + output.WriteLine(); if (field.HasCustomAttributes) { - OpenBlock(false); + output.MarkFoldStart(); WriteAttributes(field.CustomAttributes); - CloseBlock(); - } else { - output.WriteLine(); + output.MarkFoldEnd(); } } #endregion @@ -219,17 +714,33 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleProperty(PropertyDefinition property) { + // set current member + currentMember = property; + output.WriteDefinition(".property ", property); WriteFlags(property.Attributes, propertyAttributes); + if (property.HasThis) + output.Write("instance "); property.PropertyType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(property.Name)); + + output.Write("("); + if (property.HasParameters) { + output.WriteLine(); + output.Indent(); + WriteParameters(property.Parameters); + output.Unindent(); + } + output.Write(")"); + OpenBlock(false); WriteAttributes(property.CustomAttributes); WriteNestedMethod(".get", property.GetMethod); WriteNestedMethod(".set", property.SetMethod); + foreach (var method in property.OtherMethods) { - WriteNestedMethod(".method", method); + WriteNestedMethod(".other", method); } CloseBlock(); } @@ -238,16 +749,10 @@ namespace ICSharpCode.Decompiler.Disassembler { if (method == null) return; - if (detectControlStructure) { - output.WriteDefinition(keyword, method); - output.Write(' '); - DisassembleMethodInternal(method); - } else { - output.Write(keyword); - output.Write(' '); - method.WriteTo(output); - output.WriteLine(); - } + output.Write(keyword); + output.Write(' '); + method.WriteTo(output); + output.WriteLine(); } #endregion @@ -259,18 +764,21 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleEvent(EventDefinition ev) { + // set current member + currentMember = ev; + output.WriteDefinition(".event ", ev); WriteFlags(ev.Attributes, eventAttributes); - ev.EventType.WriteTo(output); + ev.EventType.WriteTo(output, ILNameSyntax.TypeName); output.Write(' '); output.Write(DisassemblerHelpers.Escape(ev.Name)); OpenBlock(false); WriteAttributes(ev.CustomAttributes); - WriteNestedMethod(".add", ev.AddMethod); - WriteNestedMethod(".remove", ev.RemoveMethod); - WriteNestedMethod(".invoke", ev.InvokeMethod); + WriteNestedMethod(".addon", ev.AddMethod); + WriteNestedMethod(".removeon", ev.RemoveMethod); + WriteNestedMethod(".fire", ev.InvokeMethod); foreach (var method in ev.OtherMethods) { - WriteNestedMethod(".method", method); + WriteNestedMethod(".other", method); } CloseBlock(); } @@ -312,6 +820,7 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleType(TypeDefinition type) { + // start writing IL output.WriteDefinition(".class ", type); if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface) @@ -322,14 +831,15 @@ namespace ICSharpCode.Decompiler.Disassembler const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, typeAttributes); - output.Write(DisassemblerHelpers.Escape(type.Name)); + output.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName)); + WriteTypeParameters(output, type); output.MarkFoldStart(defaultCollapsed: isInType); output.WriteLine(); if (type.BaseType != null) { output.Indent(); output.Write("extends "); - type.BaseType.WriteTo(output, true); + type.BaseType.WriteTo(output, ILNameSyntax.TypeName); output.WriteLine(); output.Unindent(); } @@ -342,9 +852,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("implements "); else output.Write(" "); - if (type.Interfaces[index].Namespace != null) - output.Write("{0}.", type.Interfaces[index].Namespace); - output.Write(type.Interfaces[index].Name); + type.Interfaces[index].WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); output.Unindent(); @@ -355,6 +863,7 @@ namespace ICSharpCode.Decompiler.Disassembler bool oldIsInType = isInType; isInType = true; WriteAttributes(type.CustomAttributes); + WriteSecurityDeclarations(type); if (type.HasLayoutInfo) { output.WriteLine(".pack {0}", type.PackingSize); output.WriteLine(".size {0}", type.ClassSize); @@ -377,13 +886,13 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); } - if (type.HasProperties) { - output.WriteLine("// Properties"); - foreach (var prop in type.Properties) { + if (type.HasMethods) { + output.WriteLine("// Methods"); + foreach (var m in type.Methods) { cancellationToken.ThrowIfCancellationRequested(); - DisassembleProperty(prop); + DisassembleMethod(m); + output.WriteLine(); } - output.WriteLine(); } if (type.HasEvents) { output.WriteLine("// Events"); @@ -394,20 +903,53 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); } - if (type.HasMethods) { - output.WriteLine("// Methods"); - var accessorMethods = type.GetAccessorMethods(); - foreach (var m in type.Methods) { + if (type.HasProperties) { + output.WriteLine("// Properties"); + foreach (var prop in type.Properties) { cancellationToken.ThrowIfCancellationRequested(); - if (!(detectControlStructure && accessorMethods.Contains(m))) { - DisassembleMethod(m); - output.WriteLine(); - } + DisassembleProperty(prop); } + output.WriteLine(); } - CloseBlock("End of class " + type.FullName); + CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName)); isInType = oldIsInType; } + + void WriteTypeParameters(ITextOutput output, IGenericParameterProvider p) + { + if (p.HasGenericParameters) { + output.Write('<'); + for (int i = 0; i < p.GenericParameters.Count; i++) { + if (i > 0) + output.Write(", "); + GenericParameter gp = p.GenericParameters[i]; + if (gp.HasReferenceTypeConstraint) { + output.Write("class "); + } else if (gp.HasNotNullableValueTypeConstraint) { + output.Write("valuetype "); + } + if (gp.HasDefaultConstructorConstraint) { + output.Write(".ctor "); + } + if (gp.HasConstraints) { + output.Write('('); + for (int j = 0; j < gp.Constraints.Count; j++) { + if (j > 0) + output.Write(", "); + gp.Constraints[j].WriteTo(output, ILNameSyntax.TypeName); + } + output.Write(") "); + } + if (gp.IsContravariant) { + output.Write('-'); + } else if (gp.IsCovariant) { + output.Write('+'); + } + output.Write(DisassemblerHelpers.Escape(gp.Name)); + } + output.Write('>'); + } + } #endregion #region Helper methods @@ -540,9 +1082,12 @@ namespace ICSharpCode.Decompiler.Disassembler { output.Write(".assembly " + DisassemblerHelpers.Escape(asm.Name.Name)); OpenBlock(false); - Version v = asm.Name.Version; - if (v != null) { - output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); + WriteAttributes(asm.CustomAttributes); + WriteSecurityDeclarations(asm); + if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { + output.Write(".publickey = "); + WriteBlob(asm.Name.PublicKey); + output.WriteLine(); } if (asm.Name.HashAlgorithm != AssemblyHashAlgorithm.None) { output.Write(".hash algorithm 0x{0:x8}", (int)asm.Name.HashAlgorithm); @@ -550,13 +1095,64 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(" // SHA1"); output.WriteLine(); } - if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { - output.Write(".publickey = "); - WriteBlob(asm.Name.PublicKey); - output.WriteLine(); + Version v = asm.Name.Version; + if (v != null) { + output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); } - WriteAttributes(asm.CustomAttributes); CloseBlock(); } + + public void WriteAssemblyReferences(ModuleDefinition module) + { + foreach (var mref in module.ModuleReferences) { + output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(mref.Name)); + } + foreach (var aref in module.AssemblyReferences) { + output.Write(".assembly extern {0}", DisassemblerHelpers.Escape(aref.Name)); + OpenBlock(false); + if (aref.PublicKeyToken != null) { + output.Write(".publickeytoken = "); + WriteBlob(aref.PublicKeyToken); + output.WriteLine(); + } + if (aref.Version != null) { + output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision); + } + CloseBlock(); + } + } + + public void WriteModuleHeader(ModuleDefinition module) + { + if (module.HasExportedTypes) { + foreach (ExportedType exportedType in module.ExportedTypes) { + output.Write(".class extern "); + if (exportedType.IsForwarder) + output.Write("forwarder "); + output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName); + OpenBlock(false); + if (exportedType.DeclaringType != null) + output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName)); + else + output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name)); + CloseBlock(); + } + } + + output.WriteLine(".module {0}", module.Name); + output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant()); + // TODO: imagebase, file alignment, stackreserve, subsystem + output.WriteLine(".corflags 0x{0:x} // {1}", module.Attributes, module.Attributes.ToString()); + + WriteAttributes(module.CustomAttributes); + } + + public void WriteModuleContents(ModuleDefinition module) + { + foreach (TypeDefinition td in module.Types) { + DisassembleType(td); + output.WriteLine(); + } + } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index a0fa8fc16c..9f4ccfd93f 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -64,6 +64,7 @@ + @@ -76,6 +77,7 @@ + @@ -112,14 +114,14 @@ + - + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil - False {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs index e35bb868dc..6c4f824745 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs @@ -1,9 +1,20 @@ -// -// -// -// -// $Revision$ -// +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections; diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs index 9a31e8595b..fafe13e1ae 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs @@ -1,4 +1,22 @@ -using System; +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Diagnostics; using System.IO; using System.Collections.Generic; @@ -73,17 +91,34 @@ namespace ICSharpCode.Decompiler.ILAst } } - var defaultCase = ilSwitch.CaseBlocks.Where(cb => cb.Values == null).SingleOrDefault(); + var defaultCase = ilSwitch.CaseBlocks.SingleOrDefault(cb => cb.Values == null); // If there is no default block, remove empty case blocks if (defaultCase == null || (defaultCase.Body.Count == 1 && defaultCase.Body.Single().Match(ILCode.LoopOrSwitchBreak))) { ilSwitch.CaseBlocks.RemoveAll(b => b.Body.Count == 1 && b.Body.Single().Match(ILCode.LoopOrSwitchBreak)); } } - // Remove redundant return + // Remove redundant return at the end of method if (method.Body.Count > 0 && method.Body.Last().Match(ILCode.Ret) && ((ILExpression)method.Body.Last()).Arguments.Count == 0) { method.Body.RemoveAt(method.Body.Count - 1); } + + // Remove unreachable return statements + bool modified = false; + foreach(ILBlock block in method.GetSelfAndChildrenRecursive()) { + for (int i = 0; i < block.Body.Count - 1;) { + if (block.Body[i].IsUnconditionalControlFlow() && block.Body[i+1].Match(ILCode.Ret)) { + modified = true; + block.Body.RemoveAt(i+1); + } else { + i++; + } + } + } + if (modified) { + // More removals might be possible + new GotoRemoval().RemoveGotos(method); + } } IEnumerable GetParents(ILNode node) @@ -122,14 +157,14 @@ namespace ICSharpCode.Decompiler.ILAst return true; } - ILNode breakBlock = GetParents(gotoExpr).Where(n => n is ILWhileLoop || n is ILSwitch).FirstOrDefault(); + ILNode breakBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop || n is ILSwitch); if (breakBlock != null && target == Exit(breakBlock, new HashSet() { gotoExpr })) { gotoExpr.Code = ILCode.LoopOrSwitchBreak; gotoExpr.Operand = null; return true; } - ILNode continueBlock = GetParents(gotoExpr).Where(n => n is ILWhileLoop).FirstOrDefault(); + ILNode continueBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop); if (continueBlock != null && target == Enter(continueBlock, new HashSet() { gotoExpr })) { gotoExpr.Code = ILCode.LoopContinue; gotoExpr.Operand = null; @@ -191,10 +226,10 @@ namespace ICSharpCode.Decompiler.ILAst } else if (expr.Code == ILCode.Nop) { return Exit(expr, visitedNodes); } else if (expr.Code == ILCode.LoopOrSwitchBreak) { - ILNode breakBlock = GetParents(expr).Where(n => n is ILWhileLoop || n is ILSwitch).First(); + ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch); return Exit(breakBlock, new HashSet() { expr }); } else if (expr.Code == ILCode.LoopContinue) { - ILNode continueBlock = GetParents(expr).Where(n => n is ILWhileLoop).First(); + ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop); return Enter(continueBlock, new HashSet() { expr }); } else { return expr; diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index f9394fbcee..e569c83e84 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -1,7 +1,27 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; + using Mono.Cecil; using Mono.Cecil.Cil; using Cecil = Mono.Cecil; @@ -261,6 +281,8 @@ namespace ICSharpCode.Decompiler.ILAst int varCount = methodDef.Body.Variables.Count; + var exceptionHandlerStarts = new HashSet(methodDef.Body.ExceptionHandlers.Select(eh => instrToByteCode[eh.HandlerStart])); + // Add known states if(methodDef.Body.HasExceptionHandlers) { foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) { @@ -327,7 +349,12 @@ namespace ICSharpCode.Decompiler.ILAst // Find all successors List branchTargets = new List(); if (!byteCode.Code.IsUnconditionalControlFlow()) { - branchTargets.Add(byteCode.Next); + if (exceptionHandlerStarts.Contains(byteCode.Next)) { + // Do not fall though down to exception handler + // It is invalid IL as per ECMA-335 §12.4.2.8.1, but some obfuscators produce it + } else { + branchTargets.Add(byteCode.Next); + } } if (byteCode.Operand is Instruction[]) { foreach(Instruction inst in (Instruction[])byteCode.Operand) { @@ -406,13 +433,12 @@ namespace ICSharpCode.Decompiler.ILAst } } - // Occasionally the compiler generates unreachable code - it can be usually just ignored - var reachableBody = body.Where(b => b.StackBefore != null); - var unreachableBody = body.Where(b => b.StackBefore == null); + // Occasionally the compilers or obfuscators generate unreachable code (which migt be intentonally invalid) + // I belive it is safe to just remove it + body.RemoveAll(b => b.StackBefore == null); // Genertate temporary variables to replace stack - // Unrachable code does not need temporary variables - the values are never pushed on the stack for consuption - foreach(ByteCode byteCode in reachableBody) { + foreach(ByteCode byteCode in body) { int argIdx = 0; int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { @@ -430,19 +456,18 @@ namespace ICSharpCode.Decompiler.ILAst // Try to use single temporary variable insted of several if possilbe (especially useful for dup) // This has to be done after all temporary variables are assigned so we know about all loads - // Unrachable code will not have any StoreTo - foreach(ByteCode byteCode in reachableBody) { + foreach(ByteCode byteCode in body) { if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { var locVars = byteCode.StoreTo; // For each of the variables, find the location where it is loaded - there should be preciesly one - var loadedBy = locVars.Select(locVar => reachableBody.SelectMany(bc => bc.StackBefore).Where(s => s.LoadFrom == locVar).Single()).ToList(); + var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); // We now know that all the variables have a single load, // Let's make sure that they have also a single store - us if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { // Great - we can reduce everything into single variable ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; byteCode.StoreTo = new List() { tmpVar }; - foreach(ByteCode bc in reachableBody) { + foreach(ByteCode bc in body) { for (int i = 0; i < bc.StackBefore.Count; i++) { // Is it one of the variable to be merged? if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { @@ -552,7 +577,7 @@ namespace ICSharpCode.Decompiler.ILAst Loads = new List() { load } }); } else if (storedBy.Length == 1) { - VariableInfo newVar = newVars.Where(v => v.Stores.Contains(storedBy[0])).Single(); + VariableInfo newVar = newVars.Single(v => v.Stores.Contains(storedBy[0])); newVar.Loads.Add(load); } else { List mergeVars = newVars.Where(v => v.Stores.Union(storedBy).Any()).ToList(); @@ -638,12 +663,14 @@ namespace ICSharpCode.Decompiler.ILAst // Find the first and widest scope int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); - var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); + var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); + + // Remember that any part of the body migt have been removed due to unreachability // Cut all instructions up to the try block { - int tryStartIdx; - for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++); + int tryStartIdx = 0; + while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) tryStartIdx++; ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); } @@ -651,24 +678,22 @@ namespace ICSharpCode.Decompiler.ILAst { HashSet nestedEHs = new HashSet(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); - int tryEndIdx; - for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++); + int tryEndIdx = 0; + while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) tryEndIdx++; tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); } // Cut all handlers tryCatchBlock.CatchBlocks = new List(); foreach(ExceptionHandler eh in handlers) { - int startIndex; - for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++); - int endInclusiveIndex; - if (eh.HandlerEnd == null) endInclusiveIndex = body.Count - 1; - // Note that the end(exclusive) instruction may not necessarly be in our body - else for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); - int count = 1 + endInclusiveIndex - startIndex; - HashSet nestedEHs = new HashSet(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); + int handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset; + int startIdx = 0; + while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) startIdx++; + int endIdx = 0; + while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) endIdx++; + HashSet nestedEHs = new HashSet(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset))); ehs.ExceptWith(nestedEHs); - List handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs); + List handlerAst = ConvertToAst(body.CutRange(startIdx, endIdx - startIdx), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { ExceptionType = eh.CatchType, diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index e069c04995..aebda33e82 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -1,3 +1,21 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -24,19 +42,24 @@ namespace ICSharpCode.Decompiler.ILAst SimplifyTernaryOperator, SimplifyNullCoalescing, JoinBasicBlocks, + SimplifyShiftOperators, TransformDecimalCtorToConstant, SimplifyLdObjAndStObj, + SimplifyCustomShortCircuit, TransformArrayInitializers, - TransformCollectionInitializers, + TransformMultidimensionalArrayInitializers, + TransformObjectInitializers, MakeAssignmentExpression, IntroducePostIncrement, InlineVariables2, FindLoops, FindConditions, FlattenNestedMovableBlocks, + RemoveEndFinally, RemoveRedundantCode2, GotoRemoval, DuplicateReturns, + GotoRemoval2, ReduceIfNesting, InlineVariables3, CachedDelegateInitialization, @@ -110,7 +133,10 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return; modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks); - + + if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return; + modified |= block.RunOptimization(SimplifyShiftOperators); + if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return; modified |= block.RunOptimization(TransformDecimalCtorToConstant); modified |= block.RunOptimization(SimplifyLdcI4ConvI8); @@ -118,11 +144,17 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) return; modified |= block.RunOptimization(SimplifyLdObjAndStObj); + if (abortBeforeStep == ILAstOptimizationStep.SimplifyCustomShortCircuit) return; + modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyCustomShortCircuit); + if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers) return; - modified |= block.RunOptimization(Initializers.TransformArrayInitializers); + modified |= block.RunOptimization(TransformArrayInitializers); + + if (abortBeforeStep == ILAstOptimizationStep.TransformMultidimensionalArrayInitializers) return; + modified |= block.RunOptimization(TransformMultidimensionalArrayInitializers); - if (abortBeforeStep == ILAstOptimizationStep.TransformCollectionInitializers) return; - modified |= block.RunOptimization(Initializers.TransformCollectionInitializers); + if (abortBeforeStep == ILAstOptimizationStep.TransformObjectInitializers) return; + modified |= block.RunOptimization(TransformObjectInitializers); if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) return; modified |= block.RunOptimization(MakeAssignmentExpression); @@ -151,6 +183,9 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.FlattenNestedMovableBlocks) return; FlattenBasicBlocks(method); + if (abortBeforeStep == ILAstOptimizationStep.RemoveEndFinally) return; + RemoveEndFinally(method); + if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode2) return; RemoveRedundantCode(method); @@ -160,6 +195,9 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return; DuplicateReturnStatements(method); + if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval2) return; + new GotoRemoval().RemoveGotos(method); + if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting) return; ReduceIfNesting(method); @@ -290,38 +328,81 @@ namespace ICSharpCode.Decompiler.ILAst /// Converts call and callvirt instructions that read/write properties into CallGetter/CallSetter instructions. /// /// CallGetter/CallSetter is used to allow the ILAst to represent "while ((SomeProperty = value) != null)". + /// + /// Also simplifies 'newobj(SomeDelegate, target, ldvirtftn(F, target))' to 'newobj(SomeDelegate, target, ldvirtftn(F))' ///
- void IntroducePropertyAccessInstructions(ILBlock method) + void IntroducePropertyAccessInstructions(ILNode node) { - foreach (ILExpression expr in method.GetSelfAndChildrenRecursive()) { - if (expr.Code == ILCode.Call || expr.Code == ILCode.Callvirt) { - MethodReference cecilMethod = (MethodReference)expr.Operand; - if (cecilMethod.DeclaringType is ArrayType) { - switch (cecilMethod.Name) { - case "Get": - expr.Code = ILCode.CallGetter; - break; - case "Set": - expr.Code = ILCode.CallSetter; - break; - case "Address": - expr.Code = ILCode.CallGetter; - expr.AddPrefix(new ILExpressionPrefix(ILCode.PropertyAddress)); - break; - } - } else { - MethodDefinition cecilMethodDef = cecilMethod.Resolve(); - if (cecilMethodDef != null) { - if (cecilMethodDef.IsGetter) - expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallGetter : ILCode.CallvirtGetter; - else if (cecilMethodDef.IsSetter) - expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallSetter : ILCode.CallvirtSetter; - } + ILExpression parentExpr = node as ILExpression; + if (parentExpr != null) { + for (int i = 0; i < parentExpr.Arguments.Count; i++) { + ILExpression expr = parentExpr.Arguments[i]; + IntroducePropertyAccessInstructions(expr); + IntroducePropertyAccessInstructions(expr, parentExpr, i); + } + } else { + foreach (ILNode child in node.GetChildren()) { + IntroducePropertyAccessInstructions(child); + ILExpression expr = child as ILExpression; + if (expr != null) { + IntroducePropertyAccessInstructions(expr, null, -1); } } } } + void IntroducePropertyAccessInstructions(ILExpression expr, ILExpression parentExpr, int posInParent) + { + if (expr.Code == ILCode.Call || expr.Code == ILCode.Callvirt) { + MethodReference cecilMethod = (MethodReference)expr.Operand; + if (cecilMethod.DeclaringType is ArrayType) { + switch (cecilMethod.Name) { + case "Get": + expr.Code = ILCode.CallGetter; + break; + case "Set": + expr.Code = ILCode.CallSetter; + break; + case "Address": + ByReferenceType brt = cecilMethod.ReturnType as ByReferenceType; + if (brt != null) { + MethodReference getMethod = new MethodReference("Get", brt.ElementType, cecilMethod.DeclaringType); + foreach (var p in cecilMethod.Parameters) + getMethod.Parameters.Add(p); + getMethod.HasThis = cecilMethod.HasThis; + expr.Operand = getMethod; + } + expr.Code = ILCode.CallGetter; + if (parentExpr != null) { + parentExpr.Arguments[posInParent] = new ILExpression(ILCode.AddressOf, null, expr); + } + break; + } + } else { + MethodDefinition cecilMethodDef = cecilMethod.Resolve(); + if (cecilMethodDef != null) { + if (cecilMethodDef.IsGetter) + expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallGetter : ILCode.CallvirtGetter; + else if (cecilMethodDef.IsSetter) + expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallSetter : ILCode.CallvirtSetter; + } + } + } else if (expr.Code == ILCode.Newobj && expr.Arguments.Count == 2) { + // Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'. + ILVariable target; + if (expr.Arguments[0].Match(ILCode.Ldloc, out target) + && expr.Arguments[1].Code == ILCode.Ldvirtftn + && expr.Arguments[1].Arguments.Count == 1 + && expr.Arguments[1].Arguments[0].MatchLdloc(target)) + { + // Remove the 'target' argument from the ldvirtftn instruction. + // It's not needed in the translation to C#, and needs to be eliminated so that the target expression + // can be inlined. + expr.Arguments[1].Arguments.Clear(); + } + } + } + /// /// Group input into a set of blocks that can be later arbitraliby schufled. /// The method adds necessary branches to make control flow between blocks @@ -352,7 +433,7 @@ namespace ICSharpCode.Decompiler.ILAst lastNode.IsUnconditionalControlFlow()) { // Try to reuse the label - ILLabel label = currNode is ILLabel ? ((ILLabel)currNode) : new ILLabel() { Name = "Block_" + (nextLabelIndex++) }; + ILLabel label = currNode as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++).ToString() }; // Terminate the last block if (!lastNode.IsUnconditionalControlFlow()) { @@ -461,6 +542,25 @@ namespace ICSharpCode.Decompiler.ILAst } } + /// + /// Replace endfinally with jump to the end of the finally block + /// + void RemoveEndFinally(ILBlock method) + { + // Go thought the list in reverse so that we do the nested blocks first + foreach(var tryCatch in method.GetSelfAndChildrenRecursive(tc => tc.FinallyBlock != null).Reverse()) { + ILLabel label = new ILLabel() { Name = "EndFinally_" + nextLabelIndex++ }; + tryCatch.FinallyBlock.Body.Add(label); + foreach(var block in tryCatch.FinallyBlock.GetSelfAndChildrenRecursive()) { + for (int i = 0; i < block.Body.Count; i++) { + if (block.Body[i].Match(ILCode.Endfinally)) { + block.Body[i] = new ILExpression(ILCode.Br, label).WithILRanges(((ILExpression)block.Body[i]).ILRanges); + } + } + } + } + } + /// /// Reduce the nesting of conditions. /// It should be done on flat data that already had most gotos removed @@ -510,16 +610,37 @@ namespace ICSharpCode.Decompiler.ILAst // This ensures that a single IL variable is a single C# variable (gets assigned only one name) // The DeclareVariables transformation might then split up the C# variable again if it is used indendently in two separate scopes. Dictionary dict = new Dictionary(); - foreach (ILExpression expr in method.GetSelfAndChildrenRecursive()) { - ILVariable v = expr.Operand as ILVariable; - if (v != null && v.OriginalVariable != null) { + ReplaceVariables( + method, + delegate(ILVariable v) { + if (v.OriginalVariable == null) + return v; ILVariable combinedVariable; if (!dict.TryGetValue(v.OriginalVariable, out combinedVariable)) { dict.Add(v.OriginalVariable, v); combinedVariable = v; } - expr.Operand = combinedVariable; + return combinedVariable; + }); + } + + public static void ReplaceVariables(ILNode node, Func variableMapping) + { + ILExpression expr = node as ILExpression; + if (expr != null) { + ILVariable v = expr.Operand as ILVariable; + if (v != null) + expr.Operand = variableMapping(v); + foreach (ILExpression child in expr.Arguments) + ReplaceVariables(child, variableMapping); + } else { + var catchBlock = node as ILTryCatchBlock.CatchBlock; + if (catchBlock != null && catchBlock.ExceptionVariable != null) { + catchBlock.ExceptionVariable = variableMapping(catchBlock.ExceptionVariable); } + + foreach (ILNode child in node.GetChildren()) + ReplaceVariables(child, variableMapping); } } @@ -648,15 +769,36 @@ namespace ICSharpCode.Decompiler.ILAst // property getters can't be expression statements, but all other method calls can be MethodReference mr = (MethodReference)expr.Operand; return !mr.Name.StartsWith("get_", StringComparison.Ordinal); + case ILCode.CallSetter: + case ILCode.CallvirtSetter: case ILCode.Newobj: case ILCode.Newarr: case ILCode.Stloc: + case ILCode.Stobj: + case ILCode.Stsfld: + case ILCode.Stfld: + case ILCode.Stind_Ref: + case ILCode.Stelem_Any: + case ILCode.Stelem_I: + case ILCode.Stelem_I1: + case ILCode.Stelem_I2: + case ILCode.Stelem_I4: + case ILCode.Stelem_I8: + case ILCode.Stelem_R4: + case ILCode.Stelem_R8: + case ILCode.Stelem_Ref: return true; default: return false; } } + public static ILExpression WithILRanges(this ILExpression expr, IEnumerable ilranges) + { + expr.ILRanges.AddRange(ilranges); + return expr; + } + public static void RemoveTail(this List body, params ILCode[] codes) { for (int i = 0; i < codes.Length; i++) { diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 721458348f..4f3930fcdd 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -1,3 +1,21 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -25,6 +43,7 @@ namespace ICSharpCode.Decompiler.ILAst void AccumulateSelfAndChildrenRecursive(List list, Func predicate) where T:ILNode { + // Note: RemoveEndFinally depends on self coming before children T thisAsT = this as T; if (thisAsT != null && (predicate == null || predicate(thisAsT))) list.Add(thisAsT); @@ -123,6 +142,10 @@ namespace ICSharpCode.Decompiler.ILAst { output.Write("catch "); output.WriteReference(ExceptionType.FullName, ExceptionType); + if (ExceptionVariable != null) { + output.Write(' '); + output.Write(ExceptionVariable.Name); + } output.WriteLine(" {"); output.Indent(); base.WriteTo(output); @@ -210,7 +233,10 @@ namespace ICSharpCode.Decompiler.ILAst public static List OrderAndJoint(IEnumerable input) { - List ranges = input.OrderBy(r => r.From).ToList(); + if (input == null) + throw new ArgumentNullException("Input is null!"); + + List ranges = input.Where(r => r != null).OrderBy(r => r.From).ToList(); for (int i = 0; i < ranges.Count - 1;) { ILRange curr = ranges[i]; ILRange next = ranges[i + 1]; @@ -227,6 +253,12 @@ namespace ICSharpCode.Decompiler.ILAst public static IEnumerable Invert(IEnumerable input, int codeSize) { + if (input == null) + throw new ArgumentNullException("Input is null!"); + + if (codeSize <= 0) + throw new ArgumentException("Code size must be grater than 0"); + var ordered = OrderAndJoint(input); if (ordered.Count == 0) { yield return new ILRange() { From = 0, To = codeSize }; @@ -351,10 +383,10 @@ namespace ICSharpCode.Decompiler.ILAst output.Write(((ILVariable)Operand).Name); if (this.InferredType != null) { output.Write(':'); - this.InferredType.WriteTo(output, true, true); + this.InferredType.WriteTo(output, ILNameSyntax.ShortTypeName); if (this.ExpectedType != null && this.ExpectedType.FullName != this.InferredType.FullName) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } } @@ -372,15 +404,15 @@ namespace ICSharpCode.Decompiler.ILAst output.Write(Code.GetName()); if (this.InferredType != null) { output.Write(':'); - this.InferredType.WriteTo(output, true, true); + this.InferredType.WriteTo(output, ILNameSyntax.ShortTypeName); if (this.ExpectedType != null && this.ExpectedType.FullName != this.InferredType.FullName) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } } else if (this.ExpectedType != null) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } output.Write('('); @@ -397,12 +429,14 @@ namespace ICSharpCode.Decompiler.ILAst } } else if (Operand is MethodReference) { MethodReference method = (MethodReference)Operand; - method.DeclaringType.WriteTo(output, true, true); - output.Write("::"); + if (method.DeclaringType != null) { + method.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName); + output.Write("::"); + } output.WriteReference(method.Name, method); } else if (Operand is FieldReference) { FieldReference field = (FieldReference)Operand; - field.DeclaringType.WriteTo(output, true, true); + field.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write("::"); output.WriteReference(field.Name, field); } else { diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs index e26c8d2655..e7322a770b 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using Mono.Cecil; @@ -238,8 +253,18 @@ namespace ICSharpCode.Decompiler.ILAst LogicOr, NullCoalescing, InitArray, // Array Initializer - InitCollection, // Collection Initializer: first arg is newobj, remaining args are InitCollectionAddMethod method calls - InitCollectionAddMethod, + + // new Class { Prop = 1, Collection = { { 2, 3 }, {4, 5} }} + // is represented as: + // InitObject(newobj Class, + // CallSetter(Prop, InitializedObject, 1), + // InitCollection(CallGetter(Collection, InitializedObject))), + // Call(Add, InitializedObject, 2, 3), + // Call(Add, InitializedObject, 4, 5))) + InitObject, // Object initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements + InitCollection, // Collection initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements + InitializedObject, // Refers the the object being initialized (refers to first arg in parent InitObject or InitCollection instruction) + TernaryOp, // ?: LoopOrSwitchBreak, LoopContinue, @@ -276,9 +301,12 @@ namespace ICSharpCode.Decompiler.ILAst CallSetter, /// Calls the setter of a instance property (or indexer) CallvirtSetter, - /// Simulates getting the address of a property. Used as prefix on CallGetter or CallvirtGetter. - /// Used for postincrement for properties, and to represent the Address() method on multi-dimensional arrays - PropertyAddress + /// Simulates getting the address of the argument instruction. + /// + /// Used for postincrement for properties, and to represent the Address() method on multi-dimensional arrays. + /// Also used when inlining a method call on a value type: "stloc(v, ...); call(M, ldloca(v));" becomes "call(M, AddressOf(...))" + /// + AddressOf } public static class ILCodeUtil diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs index 647f035a7f..be749a6586 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -32,7 +47,13 @@ namespace ICSharpCode.Decompiler.ILAst numLdloca.Clear(); // Analyse the whole method - foreach(ILExpression expr in method.GetSelfAndChildrenRecursive()) { + AnalyzeNode(method); + } + + void AnalyzeNode(ILNode node) + { + ILExpression expr = node as ILExpression; + if (expr != null) { ILVariable locVar = expr.Operand as ILVariable; if (locVar != null) { if (expr.Code == ILCode.Stloc) { @@ -45,6 +66,16 @@ namespace ICSharpCode.Decompiler.ILAst throw new NotSupportedException(expr.Code.ToString()); } } + foreach (ILExpression child in expr.Arguments) + AnalyzeNode(child); + } else { + var catchBlock = node as ILTryCatchBlock.CatchBlock; + if (catchBlock != null && catchBlock.ExceptionVariable != null) { + numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + 1; + } + + foreach (ILNode child in node.GetChildren()) + AnalyzeNode(child); } } @@ -61,6 +92,20 @@ namespace ICSharpCode.Decompiler.ILAst { bool modified = false; List body = block.Body; + if (block is ILTryCatchBlock.CatchBlock && body.Count > 1) { + ILVariable v = ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable; + if (v != null && v.IsGenerated) { + if (numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1) { + ILVariable v2; + ILExpression ldException; + if (body[0].Match(ILCode.Stloc, out v2, out ldException) && ldException.MatchLdloc(v)) { + body.RemoveAt(0); + ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable = v2; + modified = true; + } + } + } + } for(int i = 0; i < body.Count - 1;) { ILVariable locVar; ILExpression expr; @@ -73,7 +118,7 @@ namespace ICSharpCode.Decompiler.ILAst } foreach(ILBasicBlock bb in body.OfType()) { modified |= InlineAllInBasicBlock(bb); - } + } return modified; } @@ -169,7 +214,10 @@ namespace ICSharpCode.Decompiler.ILAst bool InlineIfPossible(ILVariable v, ILExpression inlinedExpression, ILNode next, bool aggressive) { // ensure the variable is accessed only a single time - if (!(numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0)) + if (numStloc.GetOrDefault(v) != 1) + return false; + int ldloc = numLdloc.GetOrDefault(v); + if (ldloc > 1 || ldloc + numLdloca.GetOrDefault(v) != 1) return false; if (next is ILCondition) @@ -180,35 +228,135 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression parent; int pos; if (FindLoadInNext(next as ILExpression, v, inlinedExpression, out parent, out pos) == true) { - if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression)) - return false; + if (ldloc == 0) { + if (!IsGeneratedValueTypeTemporary((ILExpression)next, parent, pos, v, inlinedExpression)) + return false; + } else { + if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression)) + return false; + } // Assign the ranges of the ldloc instruction: inlinedExpression.ILRanges.AddRange(parent.Arguments[pos].ILRanges); - parent.Arguments[pos] = inlinedExpression; - + if (ldloc == 0) { + // it was an ldloca instruction, so we need to use the pseudo-opcode 'addressof' so that the types + // comes out correctly + parent.Arguments[pos] = new ILExpression(ILCode.AddressOf, null, inlinedExpression); + } else { + parent.Arguments[pos] = inlinedExpression; + } return true; } return false; } + + /// + /// Is this a temporary variable generated by the C# compiler for instance method calls on value type values + /// + /// The next top-level expression + /// The direct parent of the load within 'next' + /// Index of the load within 'parent' + /// The variable being inlined. + /// The expression being inlined + bool IsGeneratedValueTypeTemporary(ILExpression next, ILExpression parent, int pos, ILVariable v, ILExpression inlinedExpression) + { + if (pos == 0 && v.Type != null && v.Type.IsValueType) { + // Inlining a value type variable is allowed only if the resulting code will maintain the semantics + // that the method is operating on a copy. + // Thus, we have to disallow inlining of other locals, fields, array elements, dereferenced pointers + switch (inlinedExpression.Code) { + case ILCode.Ldloc: + case ILCode.Stloc: + case ILCode.CompoundAssignment: + case ILCode.Ldelem_Any: + case ILCode.Ldelem_I: + case ILCode.Ldelem_I1: + case ILCode.Ldelem_I2: + case ILCode.Ldelem_I4: + case ILCode.Ldelem_I8: + case ILCode.Ldelem_R4: + case ILCode.Ldelem_R8: + case ILCode.Ldelem_Ref: + case ILCode.Ldelem_U1: + case ILCode.Ldelem_U2: + case ILCode.Ldelem_U4: + case ILCode.Ldobj: + case ILCode.Ldind_Ref: + return false; + case ILCode.Ldfld: + case ILCode.Stfld: + case ILCode.Ldsfld: + case ILCode.Stsfld: + // allow inlining field access only if it's a readonly field + FieldDefinition f = ((FieldReference)inlinedExpression.Operand).Resolve(); + if (!(f != null && f.IsInitOnly)) + return false; + break; + case ILCode.Call: + case ILCode.CallGetter: + // inlining runs both before and after IntroducePropertyAccessInstructions, + // so we have to handle both 'call' and 'callgetter' + MethodReference mr = (MethodReference)inlinedExpression.Operand; + // ensure that it's not an multi-dimensional array getter + if (mr.DeclaringType is ArrayType) + return false; + goto case ILCode.Callvirt; + case ILCode.Callvirt: + case ILCode.CallvirtGetter: + // don't inline foreach loop variables: + mr = (MethodReference)inlinedExpression.Operand; + if (mr.Name == "get_Current" && mr.HasThis) + return false; + break; + case ILCode.Castclass: + case ILCode.Unbox_Any: + // These are valid, but might occur as part of a foreach loop variable. + ILExpression arg = inlinedExpression.Arguments[0]; + if (arg.Code == ILCode.CallGetter || arg.Code == ILCode.CallvirtGetter || arg.Code == ILCode.Call || arg.Code == ILCode.Callvirt) { + mr = (MethodReference)arg.Operand; + if (mr.Name == "get_Current" && mr.HasThis) + return false; // looks like a foreach loop variable, so don't inline it + } + break; + } + + // inline the compiler-generated variable that are used when accessing a member on a value type: + switch (parent.Code) { + case ILCode.Call: + case ILCode.CallGetter: + case ILCode.CallSetter: + case ILCode.Callvirt: + case ILCode.CallvirtGetter: + case ILCode.CallvirtSetter: + MethodReference mr = (MethodReference)parent.Operand; + return mr.HasThis; + case ILCode.Stfld: + case ILCode.Ldfld: + case ILCode.Ldflda: + return true; + } + } + return false; + } + /// + /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. + /// + /// The next top-level expression + /// The direct parent of the load within 'next' + /// The expression being inlined bool NonAggressiveInlineInto(ILExpression next, ILExpression parent, ILExpression inlinedExpression) { - switch (inlinedExpression.Code) { - case ILCode.InitArray: - case ILCode.InitCollection: - case ILCode.DefaultValue: - return true; - } + if (inlinedExpression.Code == ILCode.DefaultValue) + return true; switch (next.Code) { case ILCode.Ret: - return parent.Code == ILCode.Ret; case ILCode.Brtrue: - return parent.Code == ILCode.Brtrue; + return parent == next; case ILCode.Switch: - return parent.Code == ILCode.Switch || parent.Code == ILCode.Sub; + return parent == next || (parent.Code == ILCode.Sub && parent == next.Arguments[0]); default: return false; } @@ -237,12 +385,12 @@ namespace ICSharpCode.Decompiler.ILAst for (int i = 0; i < expr.Arguments.Count; i++) { // Stop when seeing an opcode that does not guarantee that its operands will be evaluated. // Inlining in that case might result in the inlined expresion not being evaluted. - if (i == 1 && (expr.Code == ILCode.LogicAnd || expr.Code == ILCode.LogicOr || expr.Code == ILCode.TernaryOp)) + if (i == 1 && (expr.Code == ILCode.LogicAnd || expr.Code == ILCode.LogicOr || expr.Code == ILCode.TernaryOp || expr.Code == ILCode.NullCoalescing)) return false; ILExpression arg = expr.Arguments[i]; - if (arg.Code == ILCode.Ldloc && arg.Operand == v) { + if ((arg.Code == ILCode.Ldloc || arg.Code == ILCode.Ldloca) && arg.Operand == v) { parent = expr; pos = i; return true; diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs index 29d8695265..5b194b7389 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs @@ -1,10 +1,25 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; - using Mono.Cecil; namespace ICSharpCode.Decompiler.ILAst @@ -12,41 +27,31 @@ namespace ICSharpCode.Decompiler.ILAst /// /// IL AST transformation that introduces array, object and collection initializers. /// - public class Initializers + partial class ILAstOptimizer { - public static bool TransformArrayInitializers(List body, ILExpression expr, int pos) + #region Array Initializers + bool TransformArrayInitializers(List body, ILExpression expr, int pos) { - ILVariable v, v2, v3; + ILVariable v, v3; ILExpression newarrExpr; - TypeReference arrayType; + TypeReference elementType; ILExpression lengthExpr; int arrayLength; if (expr.Match(ILCode.Stloc, out v, out newarrExpr) && - newarrExpr.Match(ILCode.Newarr, out arrayType, out lengthExpr) && + newarrExpr.Match(ILCode.Newarr, out elementType, out lengthExpr) && lengthExpr.Match(ILCode.Ldc_I4, out arrayLength) && - arrayLength > 0) - { - MethodReference methodRef; - ILExpression methodArg1; - ILExpression methodArg2; - FieldDefinition field; - if (body.ElementAtOrDefault(pos + 1).Match(ILCode.Call, out methodRef, out methodArg1, out methodArg2) && - methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" && - methodRef.Name == "InitializeArray" && - methodArg1.Match(ILCode.Ldloc, out v2) && - v == v2 && - methodArg2.Match(ILCode.Ldtoken, out field) && - field != null && field.InitialValue != null) - { - ILExpression[] newArr = new ILExpression[arrayLength]; - if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType), field.InitialValue, newArr)) { - body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr)); - body.RemoveAt(pos + 1); - return true; - } + arrayLength > 0) { + ILExpression[] newArr; + int initArrayPos; + if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out newArr, out initArrayPos)) { + var arrayType = new ArrayType(elementType, 1); + arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength); + body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr)); + body.RemoveAt(initArrayPos); } - - const int maxConsecutiveDefaultValueExpressions = 10; + // Put in a limit so that we don't consume too much memory if the code allocates a huge array + // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler! + const int maxConsecutiveDefaultValueExpressions = 300; List operands = new List(); int numberOfInstructionsToRemove = 0; for (int j = pos + 1; j < body.Count; j++) { @@ -58,10 +63,9 @@ namespace ICSharpCode.Decompiler.ILAst v == v3 && nextExpr.Arguments[1].Match(ILCode.Ldc_I4, out arrayPos) && arrayPos >= operands.Count && - arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions) - { + arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions) { while (operands.Count < arrayPos) - operands.Add(new ILExpression(ILCode.DefaultValue, arrayType)); + operands.Add(new ILExpression(ILCode.DefaultValue, elementType)); operands.Add(nextExpr.Arguments[2]); numberOfInstructionsToRemove++; } else { @@ -69,19 +73,86 @@ namespace ICSharpCode.Decompiler.ILAst } } if (operands.Count == arrayLength) { + var arrayType = new ArrayType(elementType, 1); + arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength); expr.Arguments[0] = new ILExpression(ILCode.InitArray, arrayType, operands); body.RemoveRange(pos + 1, numberOfInstructionsToRemove); + + new ILInlining(method).InlineIfPossible(body, ref pos); + return true; + } + } + return false; + } + + bool TransformMultidimensionalArrayInitializers(List body, ILExpression expr, int pos) + { + ILVariable v; + ILExpression newarrExpr; + MethodReference ctor; + List ctorArgs; + ArrayType arrayType; + if (expr.Match(ILCode.Stloc, out v, out newarrExpr) && + newarrExpr.Match(ILCode.Newobj, out ctor, out ctorArgs) && + (arrayType = (ctor.DeclaringType as ArrayType)) != null && + arrayType.Rank == ctorArgs.Count) { + // Clone the type, so we can muck about with the Dimensions + arrayType = new ArrayType(arrayType.ElementType, arrayType.Rank); + var arrayLengths = new int[arrayType.Rank]; + for (int i = 0; i < arrayType.Rank; i++) { + if (!ctorArgs[i].Match(ILCode.Ldc_I4, out arrayLengths[i])) return false; + if (arrayLengths[i] <= 0) return false; + arrayType.Dimensions[i] = new ArrayDimension(0, arrayLengths[i]); + } + + var totalElements = arrayLengths.Aggregate(1, (t, l) => t * l); + ILExpression[] newArr; + int initArrayPos; + if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, arrayType, totalElements, out newArr, out initArrayPos)) { + var mdArr = Array.CreateInstance(typeof(ILExpression), arrayLengths); + body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr)); + body.RemoveAt(initArrayPos); return true; } } return false; } - + + bool ForwardScanInitializeArrayRuntimeHelper(List body, int pos, ILVariable array, TypeReference arrayType, int arrayLength, out ILExpression[] values, out int foundPos) + { + ILVariable v2; + MethodReference methodRef; + ILExpression methodArg1; + ILExpression methodArg2; + FieldReference fieldRef; + if (body.ElementAtOrDefault(pos).Match(ILCode.Call, out methodRef, out methodArg1, out methodArg2) && + methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" && + methodRef.Name == "InitializeArray" && + methodArg1.Match(ILCode.Ldloc, out v2) && + array == v2 && + methodArg2.Match(ILCode.Ldtoken, out fieldRef)) + { + FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule(); + if (fieldDef != null && fieldDef.InitialValue != null) { + ILExpression[] newArr = new ILExpression[arrayLength]; + if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType.GetElementType()), + fieldDef.InitialValue, newArr)) + { + values = newArr; + foundPos = pos; + return true; + } + } + } + values = null; + foundPos = -1; + return false; + } + static bool DecodeArrayInitializer(TypeCode elementType, byte[] initialValue, ILExpression[] output) { switch (elementType) { case TypeCode.Boolean: - case TypeCode.SByte: case TypeCode.Byte: if (initialValue.Length == output.Length) { for (int j = 0; j < output.Length; j++) { @@ -90,9 +161,15 @@ namespace ICSharpCode.Decompiler.ILAst return true; } return false; - case TypeCode.Char: + case TypeCode.SByte: + if (initialValue.Length == output.Length) { + for (int j = 0; j < output.Length; j++) { + output[j] = new ILExpression(ILCode.Ldc_I4, (int)unchecked((sbyte)initialValue[j])); + } + return true; + } + return false; case TypeCode.Int16: - case TypeCode.UInt16: if (initialValue.Length == output.Length * 2) { for (int j = 0; j < output.Length; j++) { output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToInt16(initialValue, j * 2)); @@ -100,6 +177,15 @@ namespace ICSharpCode.Decompiler.ILAst return true; } return false; + case TypeCode.Char: + case TypeCode.UInt16: + if (initialValue.Length == output.Length * 2) { + for (int j = 0; j < output.Length; j++) { + output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToUInt16(initialValue, j * 2)); + } + return true; + } + return false; case TypeCode.Int32: case TypeCode.UInt32: if (initialValue.Length == output.Length * 4) { @@ -138,50 +224,300 @@ namespace ICSharpCode.Decompiler.ILAst return false; } } - - public static bool TransformCollectionInitializers(List body, ILExpression expr, int pos) + #endregion + + /// + /// Handles both object and collection initializers. + /// + bool TransformObjectInitializers(List body, ILExpression expr, int pos) { - ILVariable v, v2; + if (!context.Settings.ObjectOrCollectionInitializers) + return false; + + Debug.Assert(body[pos] == expr); // should be called for top-level expressions only + ILVariable v; ILExpression newObjExpr; + TypeReference newObjType; + bool isValueType; MethodReference ctor; List ctorArgs; - if (expr.Match(ILCode.Stloc, out v, out newObjExpr) && - newObjExpr.Match(ILCode.Newobj, out ctor, out ctorArgs)) - { - TypeDefinition td = ctor.DeclaringType.Resolve(); - if (td == null || !td.Interfaces.Any(intf => intf.Name == "IEnumerable" && intf.Namespace == "System.Collections")) - return false; - - // This is a collection: we can convert Add() calls into a collection initializer - ILExpression collectionInitializer = new ILExpression(ILCode.InitCollection, null, newObjExpr); - bool anyAdded = false; - while(pos + 1 < body.Count) { - ILExpression nextExpr = body[pos + 1] as ILExpression; - MethodReference addMethod; - List args; - if (nextExpr.Match(ILCode.Callvirt, out addMethod, out args) && - addMethod.Name == "Add" && - addMethod.HasThis && - args.Count >= 2 && - args[0].Match(ILCode.Ldloc, out v2) && - v == v2) - { - nextExpr.Code = ILCode.InitCollectionAddMethod; - nextExpr.Arguments.RemoveAt(0); - collectionInitializer.Arguments.Add(nextExpr); - body.RemoveAt(pos + 1); - anyAdded = true; - } else { + if (expr.Match(ILCode.Stloc, out v, out newObjExpr)) { + if (newObjExpr.Match(ILCode.Newobj, out ctor, out ctorArgs)) { + // v = newObj(ctor, ctorArgs) + newObjType = ctor.DeclaringType; + isValueType = false; + } else if (newObjExpr.Match(ILCode.DefaultValue, out newObjType)) { + // v = defaultvalue(type) + isValueType = true; + } else { + return false; + } + } else if (expr.Match(ILCode.Call, out ctor, out ctorArgs)) { + // call(SomeStruct::.ctor, ldloca(v), remainingArgs) + if (ctorArgs.Count > 0 && ctorArgs[0].Match(ILCode.Ldloca, out v)) { + isValueType = true; + newObjType = ctor.DeclaringType; + ctorArgs = new List(ctorArgs); + ctorArgs.RemoveAt(0); + newObjExpr = new ILExpression(ILCode.Newobj, ctor, ctorArgs); + } else { + return false; + } + } else { + return false; + } + if (newObjType.IsValueType != isValueType) + return false; + + int originalPos = pos; + + // don't use object initializer syntax for closures + if (Ast.Transforms.DelegateConstruction.IsPotentialClosure(context, newObjType.ResolveWithinSameModule())) + return false; + + ILExpression initializer = ParseObjectInitializer(body, ref pos, v, newObjExpr, IsCollectionType(newObjType), isValueType); + + if (initializer.Arguments.Count == 1) // only newobj argument, no initializer elements + return false; + int totalElementCount = pos - originalPos - 1; // totalElementCount: includes elements from nested collections + Debug.Assert(totalElementCount >= initializer.Arguments.Count - 1); + + // Verify that we can inline 'v' into the next instruction: + + if (pos >= body.Count) + return false; // reached end of block, but there should be another instruction which consumes the initialized object + + ILInlining inlining = new ILInlining(method); + if (isValueType) { + // one ldloc for the use of the initialized object + if (inlining.numLdloc.GetOrDefault(v) != 1) + return false; + // one ldloca for each initializer argument, and also for the ctor call (if it exists) + if (inlining.numLdloca.GetOrDefault(v) != totalElementCount + (expr.Code == ILCode.Call ? 1 : 0)) + return false; + // one stloc for the initial store (if no ctor call was used) + if (inlining.numStloc.GetOrDefault(v) != (expr.Code == ILCode.Call ? 0 : 1)) + return false; + } else { + // one ldloc for each initializer argument, and another ldloc for the use of the initialized object + if (inlining.numLdloc.GetOrDefault(v) != totalElementCount + 1) + return false; + if (!(inlining.numStloc.GetOrDefault(v) == 1 && inlining.numLdloca.GetOrDefault(v) == 0)) + return false; + } + ILExpression nextExpr = body[pos] as ILExpression; + if (!inlining.CanInlineInto(nextExpr, v, initializer)) + return false; + + if (expr.Code == ILCode.Stloc) { + expr.Arguments[0] = initializer; + } else { + Debug.Assert(expr.Code == ILCode.Call); + expr.Code = ILCode.Stloc; + expr.Operand = v; + expr.Arguments.Clear(); + expr.Arguments.Add(initializer); + } + // remove all the instructions that were pulled into the initializer + body.RemoveRange(originalPos + 1, pos - originalPos - 1); + + // now that we know that it's an object initializer, change all the first arguments to 'InitializedObject' + ChangeFirstArgumentToInitializedObject(initializer); + + inlining = new ILInlining(method); + inlining.InlineIfPossible(body, ref originalPos); + + return true; + } + + /// + /// Gets whether the type supports collection initializers. + /// + static bool IsCollectionType(TypeReference tr) + { + if (tr == null) + return false; + TypeDefinition td = tr.Resolve(); + while (td != null) { + if (td.Interfaces.Any(intf => intf.Name == "IEnumerable" && intf.Namespace == "System.Collections")) + return true; + td = td.BaseType != null ? td.BaseType.Resolve() : null; + } + return false; + } + + /// + /// Gets whether 'expr' represents a setter in an object initializer. + /// ('CallvirtSetter(Property, v, value)') + /// + static bool IsSetterInObjectInitializer(ILExpression expr) + { + if (expr == null) + return false; + if (expr.Code == ILCode.CallvirtSetter || expr.Code == ILCode.CallSetter || expr.Code == ILCode.Stfld) { + return expr.Arguments.Count == 2; + } + return false; + } + + /// + /// Gets whether 'expr' represents the invocation of an 'Add' method in a collection initializer. + /// + static bool IsAddMethodCall(ILExpression expr) + { + MethodReference addMethod; + List args; + if (expr.Match(ILCode.Callvirt, out addMethod, out args)) { + if (addMethod.Name == "Add" && addMethod.HasThis) { + return args.Count >= 2; + } + } + return false; + } + + /// + /// Parses an object initializer. + /// + /// ILAst block + /// + /// Input: position of the instruction assigning to 'v'. + /// Output: first position after the object initializer + /// + /// The variable that holds the object being initialized + /// The newobj instruction + /// InitObject instruction + ILExpression ParseObjectInitializer(List body, ref int pos, ILVariable v, ILExpression newObjExpr, bool isCollection, bool isValueType) + { + // Take care not to modify any existing ILExpressions in here. + // We just construct new ones around the old ones, any modifications must wait until the whole + // object/collection initializer was analyzed. + ILExpression objectInitializer = new ILExpression(isCollection ? ILCode.InitCollection : ILCode.InitObject, null, newObjExpr); + List initializerStack = new List(); + initializerStack.Add(objectInitializer); + while (++pos < body.Count) { + ILExpression nextExpr = body[pos] as ILExpression; + if (IsSetterInObjectInitializer(nextExpr)) { + if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, false, isValueType)) { + CleanupInitializerStackAfterFailedAdjustment(initializerStack); + break; + } + initializerStack[initializerStack.Count - 1].Arguments.Add(nextExpr); + } else if (IsAddMethodCall(nextExpr)) { + if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, true, isValueType)) { + CleanupInitializerStackAfterFailedAdjustment(initializerStack); break; } + initializerStack[initializerStack.Count - 1].Arguments.Add(nextExpr); + } else { + // can't match any more initializers: end of object initializer + break; + } + } + return objectInitializer; + } + + static bool AdjustInitializerStack(List initializerStack, ILExpression argument, ILVariable v, bool isCollection, bool isValueType) + { + // Argument is of the form 'getter(getter(...(v)))' + // Unpack it into a list of getters: + List getters = new List(); + while (argument.Code == ILCode.CallvirtGetter || argument.Code == ILCode.CallGetter || argument.Code == ILCode.Ldfld) { + getters.Add(argument); + if (argument.Arguments.Count != 1) + return false; + argument = argument.Arguments[0]; + } + // Ensure that the final argument is 'v' + if (isValueType) { + ILVariable loadedVar; + if (!(argument.Match(ILCode.Ldloca, out loadedVar) && loadedVar == v)) + return false; + } else { + if (!argument.MatchLdloc(v)) + return false; + } + // Now compare the getters with those that are currently active on the initializer stack: + int i; + for (i = 1; i <= Math.Min(getters.Count, initializerStack.Count - 1); i++) { + ILExpression g1 = initializerStack[i].Arguments[0]; // getter stored in initializer + ILExpression g2 = getters[getters.Count - i]; // matching getter from argument + if (g1.Operand != g2.Operand) { + // operands differ, so we abort the comparison + break; + } + } + // Remove all initializers from the stack that were not matched with one from the argument: + initializerStack.RemoveRange(i, initializerStack.Count - i); + // Now create new initializers for the remaining arguments: + for (; i <= getters.Count; i++) { + ILExpression g = getters[getters.Count - i]; + MemberReference mr = (MemberReference)g.Operand; + TypeReference returnType; + if (mr is FieldReference) + returnType = TypeAnalysis.GetFieldType((FieldReference)mr); + else + returnType = TypeAnalysis.SubstituteTypeArgs(((MethodReference)mr).ReturnType, mr); + + ILExpression nestedInitializer = new ILExpression( + IsCollectionType(returnType) ? ILCode.InitCollection : ILCode.InitObject, + null, g); + // add new initializer to its parent: + ILExpression parentInitializer = initializerStack[initializerStack.Count - 1]; + if (parentInitializer.Code == ILCode.InitCollection) { + // can't add children to collection initializer + if (parentInitializer.Arguments.Count == 1) { + // convert empty collection initializer to object initializer + parentInitializer.Code = ILCode.InitObject; + } else { + return false; + } } - // ensure we added at least one additional arg to the collection initializer: - if (anyAdded) { - expr.Arguments[0] = collectionInitializer; + parentInitializer.Arguments.Add(nestedInitializer); + initializerStack.Add(nestedInitializer); + } + ILExpression lastInitializer = initializerStack[initializerStack.Count - 1]; + if (isCollection) { + return lastInitializer.Code == ILCode.InitCollection; + } else { + if (lastInitializer.Code == ILCode.InitCollection) { + if (lastInitializer.Arguments.Count == 1) { + // convert empty collection initializer to object initializer + lastInitializer.Code = ILCode.InitObject; + return true; + } else { + return false; + } + } else { return true; } } - return false; + } + + static void CleanupInitializerStackAfterFailedAdjustment(List initializerStack) + { + // There might be empty nested initializers left over; so we'll remove those: + while (initializerStack.Count > 1 && initializerStack[initializerStack.Count - 1].Arguments.Count == 1) { + ILExpression parent = initializerStack[initializerStack.Count - 2]; + Debug.Assert(parent.Arguments.Last() == initializerStack[initializerStack.Count - 1]); + parent.Arguments.RemoveAt(parent.Arguments.Count - 1); + initializerStack.RemoveAt(initializerStack.Count - 1); + } + } + + static void ChangeFirstArgumentToInitializedObject(ILExpression initializer) + { + // Go through all elements in the initializer (so skip the newobj-instr. at the start) + for (int i = 1; i < initializer.Arguments.Count; i++) { + ILExpression element = initializer.Arguments[i]; + if (element.Code == ILCode.InitCollection || element.Code == ILCode.InitObject) { + // nested collection/object initializer + ILExpression getCollection = element.Arguments[0]; + getCollection.Arguments[0] = new ILExpression(ILCode.InitializedObject, null); + ChangeFirstArgumentToInitializedObject(element); // handle the collection elements + } else { + element.Arguments[0] = new ILExpression(ILCode.InitializedObject, null); + } + } } } } diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs index 964b1f84e2..e5409a2e58 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -16,7 +31,7 @@ namespace ICSharpCode.Decompiler.ILAst { Dictionary labelToCfNode = new Dictionary(); - DecompilerContext context; + readonly DecompilerContext context; uint nextLabelIndex = 0; @@ -271,7 +286,7 @@ namespace ICSharpCode.Decompiler.ILAst ILLabel condLabel = caseLabels[i]; // Find or create new case block - ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.Where(b => b.EntryGoto.Operand == condLabel).FirstOrDefault(); + ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel); if (caseBlock == null) { caseBlock = new ILSwitch.CaseBlock() { Values = new List(), diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs index d2a6fd48ef..cc4e5ee5f5 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs index 67368c1fac..b8110651b9 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -75,6 +90,10 @@ namespace ICSharpCode.Decompiler.ILAst expr.Code = ILCode.Stobj; expr.Arguments.Add(new ILExpression(ILCode.DefaultValue, expr.Operand)); modified = true; + } else if (expr.Code == ILCode.Cpobj) { + expr.Code = ILCode.Stobj; + expr.Arguments[1] = new ILExpression(ILCode.Ldobj, expr.Operand, expr.Arguments[1]); + modified = true; } ILExpression arg, arg2; TypeReference type; @@ -425,6 +444,7 @@ namespace ICSharpCode.Decompiler.ILAst #endregion #region IntroducePostIncrement + bool IntroducePostIncrement(List body, ILExpression expr, int pos) { bool modified = IntroducePostIncrementForVariables(body, expr, pos); @@ -437,7 +457,7 @@ namespace ICSharpCode.Decompiler.ILAst } return modified; } - + bool IntroducePostIncrementForVariables(List body, ILExpression expr, int pos) { // Works for variables and static fields/properties @@ -450,19 +470,50 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression exprInit; if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) return false; - if (!(exprInit.Code == ILCode.Ldloc || exprInit.Code == ILCode.Ldsfld || (exprInit.Code == ILCode.CallGetter && exprInit.Arguments.Count == 0))) - return false; + //The next expression ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression; if (nextExpr == null) return false; - if (exprInit.Code == ILCode.CallGetter) { - if (!(nextExpr.Code == ILCode.CallSetter && IsGetterSetterPair(exprInit.Operand, nextExpr.Operand))) - return false; - } else { - if (!(nextExpr.Code == (exprInit.Code == ILCode.Ldloc ? ILCode.Stloc : ILCode.Stsfld) && nextExpr.Operand == exprInit.Operand)) + + ILCode loadInstruction = exprInit.Code; + ILCode storeInstruction = nextExpr.Code; + bool recombineVariable = false; + + // We only recognise local variables, static fields, and static getters with no arguments + switch (loadInstruction) { + case ILCode.Ldloc: + //Must be a matching store type + if (storeInstruction != ILCode.Stloc) + return false; + ILVariable loadVar = (ILVariable)exprInit.Operand; + ILVariable storeVar = (ILVariable)nextExpr.Operand; + if (loadVar != storeVar) { + if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable) + recombineVariable = true; + else + return false; + } + break; + case ILCode.Ldsfld: + if (storeInstruction != ILCode.Stsfld) + return false; + if (exprInit.Operand != nextExpr.Operand) + return false; + break; + case ILCode.CallGetter: + // non-static getters would have the 'this' argument + if (exprInit.Arguments.Count != 0) + return false; + if (storeInstruction != ILCode.CallSetter) + return false; + if (!IsGetterSetterPair(exprInit.Operand, nextExpr.Operand)) + return false; + break; + default: return false; } + ILExpression addExpr = nextExpr.Arguments[0]; int incrementAmount; @@ -470,12 +521,23 @@ namespace ICSharpCode.Decompiler.ILAst if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) return false; - if (exprInit.Code == ILCode.Ldloc) - exprInit.Code = ILCode.Ldloca; - else if (exprInit.Code == ILCode.CallGetter) - exprInit.AddPrefix(new ILExpressionPrefix(ILCode.PropertyAddress)); - else - exprInit.Code = ILCode.Ldsflda; + if (recombineVariable) { + // Split local variable, unsplit these two instances + // replace nextExpr.Operand with exprInit.Operand + ReplaceVariables(method, oldVar => oldVar == nextExpr.Operand ? (ILVariable)exprInit.Operand : oldVar); + } + + switch (loadInstruction) { + case ILCode.Ldloc: + exprInit.Code = ILCode.Ldloca; + break; + case ILCode.Ldsfld: + exprInit.Code = ILCode.Ldsflda; + break; + case ILCode.CallGetter: + exprInit = new ILExpression(ILCode.AddressOf, null, exprInit); + break; + } expr.Arguments[0] = new ILExpression(incrementCode, incrementAmount, exprInit); body.RemoveAt(pos + 1); // TODO ILRanges return true; @@ -567,8 +629,8 @@ namespace ICSharpCode.Decompiler.ILAst if (expr.Code == ILCode.Stobj) { stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue.Arguments[0]); } else if (expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter) { + initialValue = new ILExpression(ILCode.AddressOf, null, initialValue); stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue); - initialValue.AddPrefix(new ILExpressionPrefix(ILCode.PropertyAddress)); } else { stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue); initialValue.Code = (expr.Code == ILCode.Stfld ? ILCode.Ldflda : ILCode.Ldelema); @@ -806,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst return false; } #endregion + + #region SimplifyShiftOperators + static bool SimplifyShiftOperators(List body, ILExpression expr, int pos) + { + // C# compiles "a << b" to "a << (b & 31)", so we will remove the "& 31" if possible. + bool modified = false; + SimplifyShiftOperators(expr, ref modified); + return modified; + } + + static void SimplifyShiftOperators(ILExpression expr, ref bool modified) + { + for (int i = 0; i < expr.Arguments.Count; i++) + SimplifyShiftOperators(expr.Arguments[i], ref modified); + if (expr.Code != ILCode.Shl && expr.Code != ILCode.Shr && expr.Code != ILCode.Shr_Un) + return; + var a = expr.Arguments[1]; + if (a.Code != ILCode.And || a.Arguments[1].Code != ILCode.Ldc_I4 || expr.InferredType == null) + return; + int mask; + switch (expr.InferredType.MetadataType) { + case MetadataType.Int32: + case MetadataType.UInt32: mask = 31; break; + case MetadataType.Int64: + case MetadataType.UInt64: mask = 63; break; + default: return; + } + if ((int)a.Arguments[1].Operand != mask) return; + var res = a.Arguments[0]; + res.ILRanges.AddRange(a.ILRanges); + res.ILRanges.AddRange(a.Arguments[1].ILRanges); + expr.Arguments[1] = res; + modified = true; + } + #endregion } } diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs index 0d71a5907d..f7f2cf8a3f 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -100,7 +115,7 @@ namespace ICSharpCode.Decompiler.ILAst newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr); } } else { - // Ternary operator tends to create long complicated return statements + // Ternary operator tends to create long complicated return statements if (opCode == ILCode.Ret) return false; @@ -141,7 +156,7 @@ namespace ICSharpCode.Decompiler.ILAst // ... // v = NullCoalescing(ldloc(leftVar), rightExpr) // br(endBBLabel) - + ILVariable v, v2; ILExpression leftExpr, leftExpr2; ILVariable leftVar; @@ -150,7 +165,7 @@ namespace ICSharpCode.Decompiler.ILAst ILBasicBlock rightBB; ILExpression rightExpr; if (head.Body.Count >= 3 && - head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) && + head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) && leftExpr.Match(ILCode.Ldloc, out leftVar) && head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) && leftExpr2.MatchLdloc(leftVar) && @@ -219,6 +234,107 @@ namespace ICSharpCode.Decompiler.ILAst return false; } + public bool SimplifyCustomShortCircuit(List body, ILBasicBlock head, int pos) + { + Debug.Assert(body.Contains(head)); + + // --- looking for the following pattern --- + // stloc(targetVar, leftVar) + // brtrue(exitLabel, call(op_False, leftVar) + // br(followingBlock) + // + // FollowingBlock: + // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) + // br(exitLabel) + // --- + + if (head.Body.Count < 3) + return false; + + // looking for: + // stloc(targetVar, leftVar) + ILVariable targetVar; + ILExpression targetVarInitExpr; + if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr)) + return false; + + ILVariable leftVar; + if (!targetVarInitExpr.Match(ILCode.Ldloc, out leftVar)) + return false; + + // looking for: + // brtrue(exitLabel, call(op_False, leftVar) + // br(followingBlock) + ILExpression callExpr; + ILLabel exitLabel; + ILLabel followingBlock; + if(!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock)) + return false; + + if (labelGlobalRefCount[followingBlock] > 1) + return false; + + MethodReference opFalse; + ILExpression opFalseArg; + if (!callExpr.Match(ILCode.Call, out opFalse, out opFalseArg)) + return false; + + // ignore operators other than op_False and op_True + if (opFalse.Name != "op_False" && opFalse.Name != "op_True") + return false; + + if (!opFalseArg.MatchLdloc(leftVar)) + return false; + + ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock]; + + // FollowingBlock: + // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) + // br(exitLabel) + ILVariable _targetVar; + ILExpression opBitwiseCallExpr; + ILLabel _exitLabel; + if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel)) + return false; + + if (_targetVar != targetVar || exitLabel != _exitLabel) + return false; + + MethodReference opBitwise; + ILExpression leftVarExpression; + ILExpression rightExpression; + if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression)) + return false; + + if (!leftVarExpression.MatchLdloc(leftVar)) + return false; + + // ignore operators other than op_BitwiseAnd and op_BitwiseOr + if (opBitwise.Name != "op_BitwiseAnd" && opBitwise.Name != "op_BitwiseOr") + return false; + + // insert: + // stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression) + // br(exitLabel) + ILCode op = opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr; + + if (op == ILCode.LogicAnd && opFalse.Name != "op_False") + return false; + + if (op == ILCode.LogicOr && opFalse.Name != "op_True") + return false; + + ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(op, opFalseArg, rightExpression); + shortCircuitExpr.Operand = opBitwise; + + head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br); + head.Body.Add(new ILExpression(ILCode.Stloc, targetVar, shortCircuitExpr)); + head.Body.Add(new ILExpression(ILCode.Br, exitLabel)); + body.Remove(followingBasicBlock); + + return true; + } + ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right) { // Assuming that the inputs are already left associative diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index be93bdccae..0891f82f14 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -252,6 +267,10 @@ namespace ICSharpCode.Decompiler.ILAst return typeSystem.Boolean; case ILCode.LogicAnd: case ILCode.LogicOr: + // if Operand is set the logic and/or expression is a custom operator + // we can deal with it the same as a normal invocation. + if (expr.Operand != null) + goto case ILCode.Call; if (forceInferChildren) { InferTypeForExpression(expr.Arguments[0], typeSystem.Boolean); InferTypeForExpression(expr.Arguments[1], typeSystem.Boolean); @@ -304,13 +323,7 @@ namespace ICSharpCode.Decompiler.ILAst if (forceInferChildren) { for (int i = 0; i < expr.Arguments.Count; i++) { if (i == 0 && method.HasThis) { - ILExpressionPrefix constraint = expr.GetPrefix(ILCode.Constrained); - if (constraint != null) - InferTypeForExpression(expr.Arguments[i], new ByReferenceType((TypeReference)constraint.Operand)); - else if (method.DeclaringType.IsValueType) - InferTypeForExpression(expr.Arguments[i], new ByReferenceType(method.DeclaringType)); - else - InferTypeForExpression(expr.Arguments[i], method.DeclaringType); + InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(method.DeclaringType, expr.GetPrefix(ILCode.Constrained))); } else { InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(method.Parameters[method.HasThis ? i - 1 : i].ParameterType, method)); } @@ -319,10 +332,7 @@ namespace ICSharpCode.Decompiler.ILAst if (expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter) { return SubstituteTypeArgs(method.Parameters.Last().ParameterType, method); } else { - TypeReference type = SubstituteTypeArgs(method.ReturnType, method); - if (expr.GetPrefix(ILCode.PropertyAddress) != null && !(type is ByReferenceType)) - type = new ByReferenceType(type); - return type; + return SubstituteTypeArgs(method.ReturnType, method); } } case ILCode.Newobj: @@ -335,32 +345,32 @@ namespace ICSharpCode.Decompiler.ILAst } return ctor.DeclaringType; } + case ILCode.InitObject: case ILCode.InitCollection: return InferTypeForExpression(expr.Arguments[0], expectedType); - case ILCode.InitCollectionAddMethod: - { - MethodReference addMethod = (MethodReference)expr.Operand; - if (forceInferChildren) { - for (int i = 0; i < addMethod.Parameters.Count; i++) { - InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(addMethod.Parameters[i].ParameterType, addMethod)); - } - } - return addMethod.DeclaringType; - } + case ILCode.InitializedObject: + // expectedType should always be known due to the parent method call / property setter + Debug.Assert(expectedType != null); + return expectedType; #endregion #region Load/Store Fields case ILCode.Ldfld: - if (forceInferChildren) - InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType); + if (forceInferChildren) { + InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained))); + } return GetFieldType((FieldReference)expr.Operand); case ILCode.Ldsfld: return GetFieldType((FieldReference)expr.Operand); case ILCode.Ldflda: + if (forceInferChildren) { + InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained))); + } + return new ByReferenceType(GetFieldType((FieldReference)expr.Operand)); case ILCode.Ldsflda: return new ByReferenceType(GetFieldType((FieldReference)expr.Operand)); case ILCode.Stfld: if (forceInferChildren) { - InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType); + InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained))); InferTypeForExpression(expr.Arguments[1], GetFieldType((FieldReference)expr.Operand)); } return GetFieldType((FieldReference)expr.Operand); @@ -458,6 +468,21 @@ namespace ICSharpCode.Decompiler.ILAst InferTypeForExpression(expr.Arguments[0], (TypeReference)expr.Operand); } return typeSystem.TypedReference; + case ILCode.Refanytype: + if (forceInferChildren) { + InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference); + } + return new TypeReference("System", "RuntimeTypeHandle", module, module, true); + case ILCode.Refanyval: + if (forceInferChildren) { + InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference); + } + return new ByReferenceType((TypeReference)expr.Operand); + case ILCode.AddressOf: + { + TypeReference t = InferTypeForExpression(expr.Arguments[0], UnpackPointer(expectedType)); + return t != null ? new ByReferenceType(t) : null; + } #endregion #region Arithmetic instructions case ILCode.Not: // bitwise complement @@ -489,14 +514,47 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.Rem_Un: return InferArgumentsInBinaryOperator(expr, false, expectedType); case ILCode.Shl: - case ILCode.Shr: if (forceInferChildren) InferTypeForExpression(expr.Arguments[1], typeSystem.Int32); - return InferTypeForExpression(expr.Arguments[0], typeSystem.Int32); + if (expectedType != null && ( + expectedType.MetadataType == MetadataType.Int32 || expectedType.MetadataType == MetadataType.UInt32 || + expectedType.MetadataType == MetadataType.Int64 || expectedType.MetadataType == MetadataType.UInt64) + ) + return NumericPromotion(InferTypeForExpression(expr.Arguments[0], expectedType)); + else + return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null)); + case ILCode.Shr: case ILCode.Shr_Un: - if (forceInferChildren) - InferTypeForExpression(expr.Arguments[1], typeSystem.Int32); - return InferTypeForExpression(expr.Arguments[0], typeSystem.UInt32); + { + if (forceInferChildren) + InferTypeForExpression(expr.Arguments[1], typeSystem.Int32); + TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null)); + TypeReference expectedInputType = null; + switch (type.MetadataType) { + case MetadataType.Int32: + if (expr.Code == ILCode.Shr_Un) + expectedInputType = typeSystem.UInt32; + break; + case MetadataType.UInt32: + if (expr.Code == ILCode.Shr) + expectedInputType = typeSystem.Int32; + break; + case MetadataType.Int64: + if (expr.Code == ILCode.Shr_Un) + expectedInputType = typeSystem.UInt64; + break; + case MetadataType.UInt64: + if (expr.Code == ILCode.Shr) + expectedInputType = typeSystem.UInt64; + break; + } + if (expectedInputType != null) { + InferTypeForExpression(expr.Arguments[0], expectedInputType); + return expectedInputType; + } else { + return type; + } + } case ILCode.CompoundAssignment: { TypeReference varType = InferTypeForExpression(expr.Arguments[0].Arguments[0], null); @@ -517,9 +575,19 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.Ldc_I4: if (IsBoolean(expectedType) && ((int)expr.Operand == 0 || (int)expr.Operand == 1)) return typeSystem.Boolean; - return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int32; + if (expectedType is PointerType && (int)expr.Operand == 0) + return expectedType; + if (IsIntegerOrEnum(expectedType) && OperandFitsInType(expectedType, (int)expr.Operand)) + return expectedType; + else + return typeSystem.Int32; case ILCode.Ldc_I8: - return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int64; + if (expectedType is PointerType && (long)expr.Operand == 0) + return expectedType; + if (IsIntegerOrEnum(expectedType) && GetInformationAmount(expectedType) >= NativeInt) + return expectedType; + else + return typeSystem.Int64; case ILCode.Ldc_R4: return typeSystem.Single; case ILCode.Ldc_R8: @@ -542,11 +610,13 @@ namespace ICSharpCode.Decompiler.ILAst InferTypeForExpression(expr.Arguments.Single(), typeSystem.Int32); return new ArrayType((TypeReference)expr.Operand); case ILCode.InitArray: - if (forceInferChildren) { + var operandAsArrayType = (ArrayType)expr.Operand; + if (forceInferChildren) + { foreach (ILExpression arg in expr.Arguments) - InferTypeForExpression(arg, (TypeReference)expr.Operand); + InferTypeForExpression(arg, operandAsArrayType.ElementType); } - return new ArrayType((TypeReference)expr.Operand); + return operandAsArrayType; case ILCode.Ldlen: return typeSystem.Int32; case ILCode.Ldelem_U1: @@ -655,6 +725,8 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.Castclass: case ILCode.Unbox_Any: return (TypeReference)expr.Operand; + case ILCode.Unbox: + return new ByReferenceType((TypeReference)expr.Operand); case ILCode.Isinst: { // isinst performs the equivalent of a cast only for reference types; @@ -723,6 +795,41 @@ namespace ICSharpCode.Decompiler.ILAst } } + /// + /// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified, + /// returns the constrained type wrapped in a ByReferenceType. + /// + TypeReference MakeRefIfValueType(TypeReference type, ILExpressionPrefix constrainedPrefix) + { + if (constrainedPrefix != null) + return new ByReferenceType((TypeReference)constrainedPrefix.Operand); + if (type.IsValueType) + return new ByReferenceType(type); + else + return type; + } + + /// + /// Promotes primitive types smaller than int32 to int32. + /// + /// + /// Always promotes to signed int32. + /// + TypeReference NumericPromotion(TypeReference type) + { + if (type == null) + return null; + switch (type.MetadataType) { + case MetadataType.SByte: + case MetadataType.Int16: + case MetadataType.Byte: + case MetadataType.UInt16: + return typeSystem.Int32; + default: + return type; + } + } + TypeReference HandleConversion(int targetBitSize, bool targetSigned, ILExpression arg, TypeReference expectedType, TypeReference targetType) { if (targetBitSize >= NativeInt && expectedType is PointerType) { @@ -743,12 +850,12 @@ namespace ICSharpCode.Decompiler.ILAst return resultType; } - static TypeReference GetFieldType(FieldReference fieldReference) + public static TypeReference GetFieldType(FieldReference fieldReference) { return SubstituteTypeArgs(UnpackModifiers(fieldReference.FieldType), fieldReference); } - static TypeReference SubstituteTypeArgs(TypeReference type, MemberReference member) + public static TypeReference SubstituteTypeArgs(TypeReference type, MemberReference member) { if (type is TypeSpecification) { ArrayType arrayType = type as ArrayType; @@ -821,7 +928,7 @@ namespace ICSharpCode.Decompiler.ILAst return null; } - static TypeReference UnpackModifiers(TypeReference type) + internal static TypeReference UnpackModifiers(TypeReference type) { while (type is OptionalModifierType || type is RequiredModifierType) type = ((TypeSpecification)type).ElementType; @@ -927,7 +1034,7 @@ namespace ICSharpCode.Decompiler.ILAst { if (type == null) return 0; - if (type.IsValueType) { + if (type.IsValueType && !IsArrayPointerOrReference(type)) { // value type might be an enum TypeDefinition typeDef = type.Resolve() as TypeDefinition; if (typeDef != null && typeDef.IsEnum) { @@ -975,7 +1082,9 @@ namespace ICSharpCode.Decompiler.ILAst public static bool IsEnum(TypeReference type) { - if (type == null) + // Arrays/Pointers/ByReference resolve to their element type, but we don't want to consider those to be enums + // However, GenericInstanceTypes, ModOpts etc. should be considered enums. + if (type == null || IsArrayPointerOrReference(type)) return false; // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) TypeDefinition typeDef = type.Resolve() as TypeDefinition; @@ -984,7 +1093,7 @@ namespace ICSharpCode.Decompiler.ILAst static bool? IsSigned(TypeReference type) { - if (type == null) + if (type == null || IsArrayPointerOrReference(type)) return null; // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) TypeDefinition typeDef = type.Resolve() as TypeDefinition; @@ -1011,6 +1120,39 @@ namespace ICSharpCode.Decompiler.ILAst } } + static bool OperandFitsInType(TypeReference type, int num) + { + TypeDefinition typeDef = type.Resolve() as TypeDefinition; + if (typeDef != null && typeDef.IsEnum) { + type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; + } + switch (type.MetadataType) { + case MetadataType.SByte: + return sbyte.MinValue <= num && num <= sbyte.MaxValue; + case MetadataType.Int16: + return short.MinValue <= num && num <= short.MaxValue; + case MetadataType.Byte: + return byte.MinValue <= num && num <= byte.MaxValue; + case MetadataType.Char: + return char.MinValue <= num && num <= char.MaxValue; + case MetadataType.UInt16: + return ushort.MinValue <= num && num <= ushort.MaxValue; + default: + return true; + } + } + + static bool IsArrayPointerOrReference(TypeReference type) + { + TypeSpecification typeSpec = type as TypeSpecification; + while (typeSpec != null) { + if (typeSpec is ArrayType || typeSpec is PointerType || typeSpec is ByReferenceType) + return true; + typeSpec = typeSpec.ElementType as TypeSpecification; + } + return false; + } + public static TypeCode GetTypeCode(TypeReference type) { if (type == null) diff --git a/src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs b/src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs index 3e5825c564..71971273c1 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; @@ -164,7 +179,7 @@ namespace ICSharpCode.Decompiler.ILAst public static bool IsCompilerGeneratorEnumerator(TypeDefinition type) { - if (!(type.Name.StartsWith("<", StringComparison.Ordinal) && type.IsCompilerGenerated())) + if (!(type.DeclaringType != null && type.IsCompilerGenerated())) return false; foreach (TypeReference i in type.Interfaces) { if (i.Namespace == "System.Collections" && i.Name == "IEnumerator") diff --git a/src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs b/src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs index b4374d50b6..608a45c64b 100644 --- a/src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs +++ b/src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs @@ -23,6 +23,9 @@ namespace ICSharpCode.Decompiler { public interface ITextOutput { + int CurrentLine { get; } + int CurrentColumn { get; } + void Indent(); void Unindent(); void Write(char ch); diff --git a/src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs b/src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs index 76721e6664..86a28a5c8c 100644 --- a/src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs +++ b/src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs @@ -23,9 +23,13 @@ namespace ICSharpCode.Decompiler { public sealed class PlainTextOutput : ITextOutput { + const int TAB_SIZE = 4; + readonly TextWriter writer; int indent; bool needsIndent; + int lineNumber = 1; + int columnNumber = 1; public PlainTextOutput(TextWriter writer) { @@ -39,6 +43,14 @@ namespace ICSharpCode.Decompiler this.writer = new StringWriter(); } + public int CurrentLine { + get { return lineNumber; } + } + + public int CurrentColumn { + get { return columnNumber; } + } + public override string ToString() { return writer.ToString(); @@ -60,6 +72,7 @@ namespace ICSharpCode.Decompiler needsIndent = false; for (int i = 0; i < indent; i++) { writer.Write('\t'); + columnNumber += TAB_SIZE - 1; } } } @@ -68,18 +81,22 @@ namespace ICSharpCode.Decompiler { WriteIndent(); writer.Write(ch); + columnNumber++; } public void Write(string text) { WriteIndent(); writer.Write(text); + columnNumber += text.Length; } public void WriteLine() { + lineNumber++; writer.WriteLine(); needsIndent = true; + columnNumber = TAB_SIZE * indent; } public void WriteDefinition(string text, object definition) diff --git a/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs b/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs index c0577c5fcc..a5eb7d728a 100644 --- a/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs +++ b/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs @@ -19,6 +19,8 @@ using System.Runtime.InteropServices; // If you need to expose a type to COM, use [ComVisible(true)] on that type. [assembly: ComVisible(false)] +[assembly: AssemblyVersion("2.0.0.1221")] +[assembly: AssemblyInformationalVersion("2.0.0.1221-26633dc2")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", diff --git a/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs b/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs new file mode 100644 index 0000000000..bec57df5fd --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs @@ -0,0 +1,27 @@ +#region Using directives + +using System; +using System.Resources; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +[assembly: AssemblyTitle("ICSharpCode.Decompiler")] +[assembly: AssemblyDescription("IL decompiler engine")] +[assembly: AssemblyCompany("ic#code")] +[assembly: AssemblyProduct("ILSpy")] +[assembly: AssemblyCopyright("Copyright 2011 AlphaSierraPapa for the SharpDevelop Team")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +[assembly: AssemblyVersion("$INSERTVERSION$")] +[assembly: AssemblyInformationalVersion("$INSERTVERSION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$-$INSERTSHORTCOMMITHASH$")] +[assembly: NeutralResourcesLanguage("en-US")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", + Justification = "AssemblyInformationalVersion does not need to be a parsable version")] diff --git a/src/Libraries/ICSharpCode.Decompiler/ReferenceResolvingException.cs b/src/Libraries/ICSharpCode.Decompiler/ReferenceResolvingException.cs new file mode 100644 index 0000000000..dbceb44b3a --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/ReferenceResolvingException.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Decompiler +{ + /// + /// Represents an error while resolving a reference to a type or a member. + /// + [Serializable] + public class ReferenceResolvingException : Exception + { + /// + /// Initializes a new instance of the class + /// + public ReferenceResolvingException() + { + } + + /// + /// Initializes a new instance of the class + /// + /// A that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. + public ReferenceResolvingException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class + /// + /// A that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. + /// The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception. + public ReferenceResolvingException(string message, Exception inner) + : base(message, inner) + { + } + + /// + /// Initializes a new instance of the class + /// + /// The object that holds the serialized object data. + /// The contextual information about the source or destination. + protected ReferenceResolvingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il b/src/Libraries/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il new file mode 100644 index 0000000000..9e30002790 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il @@ -0,0 +1,59 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +} +.assembly BooleanConsumedAsInteger +{ + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} +.module BooleanConsumedAsInteger.exe +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000003 // ILONLY 32BITREQUIRED + +.class private auto ansi beforefieldinit BooleanConsumedAsInteger.Program extends [mscorlib]System.Object +{ + .method public hidebysig static void Main(string[] args) cil managed + { + .entrypoint + .maxstack 8 + + ret + } + + .method public hidebysig static int32 ReturnBoolAsInt() cil managed + { + ldnull + ldnull + call bool [mscorlib] System.Object::Equals(object, object) + ret + } + + .method public hidebysig static int32 BitwiseOperationOnBool() cil managed + { + ldnull + ldnull + call bool [mscorlib] System.Object::Equals(object, object) + ldc.i4 255 + and + ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Program::.ctor + +} // end of class StackTests.Program + + +// ============================================================= diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs new file mode 100644 index 0000000000..4f493ef20f --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; + +public class CallOverloadedMethod +{ + public void OverloadedMethod(object a) + { + } + + public void OverloadedMethod(int? a) + { + } + + public void OverloadedMethod(string a) + { + } + + public void Call() + { + this.OverloadedMethod("(string)"); + this.OverloadedMethod((object)"(object)"); + this.OverloadedMethod(5); + this.OverloadedMethod((object)5); + this.OverloadedMethod(5L); + this.OverloadedMethod((object)null); + this.OverloadedMethod((string)null); + this.OverloadedMethod((int?)null); + } + + public void CallMethodUsingInterface(List list) + { + ((ICollection)list).Clear(); + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs new file mode 100644 index 0000000000..08c5b39a3f --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs @@ -0,0 +1,66 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +public class CheckedUnchecked +{ + public int Operators(int a, int b) + { + int num = checked(a + b); + int num2 = a + b; + int num3 = checked(a - b); + int num4 = a - b; + int num5 = checked(a * b); + int num6 = a * b; + int num7 = a / b; + int num8 = a % b; + // The division operators / and % only exist in one form (checked vs. unchecked doesn't matter for them) + return num * num2 * num3 * num4 * num5 * num6 * num7 * num8; + } + + public int Cast(int a) + { + short num = checked((short)a); + short num2 = (short)a; + byte b = checked((byte)a); + byte b2 = (byte)a; + return num * num2 * b * b2; + } + + public void ForWithCheckedIteratorAndUncheckedBody(int n) + { + checked + { + for (int i = n + 1; i < n + 1; i++) + { + n = unchecked(i * i); + } + } + } + + public void ForWithCheckedInitializerAndUncheckedIterator(int n) + { + checked + { + int i = n; + for (i -= 10; i < n; i = unchecked(i + 1)) + { + n--; + } + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs new file mode 100644 index 0000000000..552d092ee5 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs @@ -0,0 +1,132 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace ICSharpCode.Decompiler.Tests +{ + static class CodeSampleFileParser + { + public static IEnumerable ListSections(string s) + { + var query = from line in ToLines(s) + let sectionName = ReadSectionName(line) + where sectionName != null + select sectionName; + return query; + } + + public static string GetSection(string sectionName, string s) + { + var lines = ToLines(s); + + bool sectionFound = false; + var sectionText = new StringBuilder(); + + Action parser = null; + + Action commonSectionReader = line => + { + if (IsCommonSectionEnd(line)) + parser = null; + else + sectionText.AppendLine(line); + }; + + Action namedSectionReader = line => + { + string name = ReadSectionName(line); + if (name == null) + sectionText.AppendLine(line); + else if (name != sectionName) + parser = null; + }; + + Action defaultReader = line => + { + if (IsCommonSectionStart(line)) + parser = commonSectionReader; + else if (ReadSectionName(line) == sectionName) + { + parser = namedSectionReader; + sectionFound = true; + } + }; + + foreach(var line in lines) + { + (parser ?? defaultReader)(line); + } + + if (sectionFound) + return sectionText.ToString(); + else + return ""; + } + + public static bool IsCommentOrBlank(string s) + { + if(String.IsNullOrWhiteSpace(s)) + return true; + return s.Trim().StartsWith("//"); + } + + public static string ConcatLines(IEnumerable lines) + { + var buffer = new StringBuilder(); + foreach (var line in lines) + { + buffer.AppendLine(line); + } + return buffer.ToString(); + } + + static string ReadSectionName(string line) + { + line = line.TrimStart(); + if (line.StartsWith("//$$")) + return line.Substring(4).Trim(); + else + return null; + } + + static bool IsCommonSectionStart(string line) + { + return line.Trim() == "//$CS"; + } + + static bool IsCommonSectionEnd(string line) + { + return line.Trim() == "//$CE"; + } + + static IEnumerable ToLines(string s) + { + var reader = new StringReader(s); + string line; + while ((line = reader.ReadLine()) != null) + { + yield return line; + } + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs new file mode 100644 index 0000000000..4130b0b0f7 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs @@ -0,0 +1,41 @@ +using System; +namespace aa +{ + public static class CustomAtributes + { + [Flags] + public enum EnumWithFlag + { + All = 15, + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + Item4 = 8 + } + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute + { + public MyAttribute(CustomAtributes.EnumWithFlag en) + { + } + } + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)] + private static int field; + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)] + public static string Property + { + get + { + return "aa"; + } + } + [Obsolete("some message")] + public static void ObsoletedMethod() + { + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); + AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs new file mode 100644 index 0000000000..892f33bf95 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.CustomAttributes +{ + [TestFixture] + public class CustomAttributeTests : DecompilerTestBase + { + [Test] + public void CustomAttributeSamples() + { + ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributeSamples.cs"); + } + + [Test] + public void CustomAttributesMultiTest() + { + ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributes.cs"); + } + + [Test] + public void AssemblyCustomAttributesMultiTest() + { + ValidateFileRoundtrip(@"CustomAttributes\S_AssemblyCustomAttribute.cs"); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs new file mode 100644 index 0000000000..9d95a4861d --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs @@ -0,0 +1,6 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +[assembly: CLSCompliant(false)] diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs new file mode 100644 index 0000000000..df395b446f --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs @@ -0,0 +1,480 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +//$CS +using System; +//$CE + +//$$ TargetModule (ignored) +//[module: CLSCompliantAttribute(false)] +//$$ ParameterlessAttributeUsage +namespace ParameterLessAttributeUsage +{ + [Flags] + public enum EnumWithFlagsAttribute + { + None = 0 + } +} +//$$ AttributeWithEnumArgument +namespace AttributeWithEnumArgument +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } +} +//$$ AttributeWithEnumExpressionArgument +namespace AttributeWithEnumExpressionArgument +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)] + public class MyAttributeAttribute : Attribute + { + } +} +//$$ AttributeWithStringExpressionArgument +namespace AttributeWithStringExpressionArgument +{ + [Obsolete("message")] + public class ObsoletedClass + { + } +} +//$$ AttributeWithTypeArgument +namespace AttributeWithTypeArgument +{ + [AttributeUsage(AttributeTargets.All)] + public class MyTypeAttribute : Attribute + { + public MyTypeAttribute(Type t) + { + } + } + + [MyType(typeof(Attribute))] + public class SomeClass + { + } +} +//$$ AppliedToEvent +namespace AppliedToEvent +{ + [AttributeUsage(AttributeTargets.Event)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public event EventHandler MyEvent; + } +} +//$$ AppliedToField +namespace AppliedToField +{ + [AttributeUsage(AttributeTargets.Field)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public int Field; + } +} +//$$ AppliedToProperty +namespace AppliedToProperty +{ + public class TestClass + { + [Obsolete("reason")] + public int Property + { + get + { + return 0; + } + } + } +} +//$$ AppliedToPropertyGet +namespace AppliedToPropertyGet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + public int Property + { + [MyAttribute] + get + { + return 0; + } + } + } +} +//$$ AppliedToPropertySet +namespace AppliedToPropertySet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + public int Property + { + get + { + return 3; + } + [MyAttribute] + set + { + } + } + } +} +//$$ AppliedToIndexer +namespace AppliedToIndexer +{ + public class TestClass + { + [Obsolete("reason")] + public int this[int i] + { + get + { + return 0; + } + } + } +} +//$$ AppliedToDelegate +[Obsolete("reason")] +public delegate int AppliedToDelegate(); +//$$ AppliedToMethod +namespace AppliedToMethod +{ + [AttributeUsage(AttributeTargets.Method)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public void Method() + { + } + } +} +//$$ AppliedToInterface +[Obsolete("reason")] +public interface AppliedToInterface +{ +} +//$$ AppliedToStruct +[Obsolete("reason")] +public struct AppliedToStruct +{ + public int Field; +} +//$$ AppliedToParameter +namespace AppliedToParameter +{ + [AttributeUsage(AttributeTargets.Parameter)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public void Method([MyAttribute] int val) + { + } + } +} +//$$ NamedInitializerProperty +namespace NamedInitializerProperty +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class MyAttributeAttribute : Attribute + { + } +} +//$$ NamedInitializerPropertyString +namespace NamedInitializerPropertyString +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public string Prop + { + get + { + return ""; + } + set + { + } + } + } + [MyAttribute(Prop = "value")] + public class MyClass + { + } +} +//$$ NamedInitializerPropertyType +namespace NamedInitializerPropertyType +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public Type Prop + { + get + { + return null; + } + set + { + } + } + } + [MyAttribute(Prop = typeof(Enum))] + public class MyClass + { + } +} +//$$ NamedInitializerPropertyEnum +namespace NamedInitializerPropertyEnum +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public AttributeTargets Prop + { + get + { + return AttributeTargets.All; + } + set + { + } + } + } + [MyAttribute(Prop = (AttributeTargets.Class | AttributeTargets.Method))] + public class MyClass + { + } +} +//$$ NamedInitializerFieldEnum +namespace NamedInitializerFieldEnum +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public AttributeTargets Field; + } + [MyAttribute(Field = (AttributeTargets.Class | AttributeTargets.Method))] + public class MyClass + { + } +} +//$$ TargetReturn +namespace TargetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + [return: MyAttribute] + public int MyMethod() + { + return 5; + } + } +} +//$$ TargetPropertyGetReturn +namespace TargetPropertyGetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + [return: MyAttribute] + get + { + return 3; + } + } + } +} +//$$ TargetPropertySetParam +namespace TargetPropertySetParam +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + [param: MyAttribute] + set + { + } + } + } +} +//$$ TargetPropertySetReturn +namespace TargetPropertySetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + get + { + return 3; + } + [return: MyAttribute] + set + { + } + } + } +} +//$$ TargetPropertyIndexGetReturn +namespace TargetPropertyIndexGetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int this[string s] + { + [return: MyAttribute] + get + { + return 3; + } + } + } +} +//$$ TargetPropertyIndexParamOnlySet +namespace TargetPropertyIndexParamOnlySet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int this[[MyAttribute] string s] + { + set + { + } + } + } +} +//$$ TargetPropertyIndexParamOnlyGet +namespace TargetPropertyIndexParamOnlyGet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int this[[MyAttribute] string s] + { + get + { + return 3; + } + } + } +} +//$$ TargetPropertyIndexSetReturn +namespace TargetPropertyIndexSetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public string this[int index] + { + get + { + return ""; + } + [return: MyAttribute] + set + { + } + } + } +} +//$$ TargetPropertyIndexSetMultiParam +namespace TargetPropertyIndexSetMultiParam +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public int Field; + } + public class MyClass + { + public string this[[MyAttribute(Field = 2)] int index1, [MyAttribute(Field = 3)] int index2] + { + get + { + return ""; + } + [param: MyAttribute] + set + { + } + } + } +} +//$$ ClassAttributeOnTypeParameter +namespace ClassAttributeOnTypeParameter +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass<[MyAttribute] T> + { + } +} +//$$ AttributeOnReturnTypeOfDelegate +namespace AttributeOnReturnTypeOfDelegate +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + [return: MyAttribute] + public delegate void Test(); +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs new file mode 100644 index 0000000000..b75e4e2b04 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs @@ -0,0 +1,64 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace aa +{ + public static class CustomAttributes + { + [Flags] + public enum EnumWithFlag + { + All = 15, + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + Item4 = 8 + } + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute + { + public MyAttribute(object val) + { + } + } + [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)] + private static int field; + [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)] + public static string Property + { + get + { + return "aa"; + } + } + [Obsolete("some message")] + public static void ObsoletedMethod() + { + //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field)); + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); + AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); + } + // No Boxing + [CustomAttributes.MyAttribute(new StringComparison[] + { + StringComparison.Ordinal, + StringComparison.CurrentCulture + })] + public static void ArrayAsAttribute1() + { + } + // Boxing of each array element + [CustomAttributes.MyAttribute(new object[] + { + StringComparison.Ordinal, + StringComparison.CurrentCulture + })] + public static void ArrayAsAttribute2() + { + } + } +} \ No newline at end of file diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs new file mode 100644 index 0000000000..f51908659b --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs @@ -0,0 +1,90 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public static class CustomShortCircuitOperators +{ + private class B + { + public static bool operator true(CustomShortCircuitOperators.B x) + { + return true; + } + + public static bool operator false(CustomShortCircuitOperators.B x) + { + return false; + } + } + + private class C : CustomShortCircuitOperators.B + { + public static CustomShortCircuitOperators.C operator &(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y) + { + return null; + } + + public static CustomShortCircuitOperators.C operator |(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y) + { + return null; + } + + public static bool operator !(CustomShortCircuitOperators.C x) + { + return false; + } + + private static void Main() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + CustomShortCircuitOperators.C c2 = new CustomShortCircuitOperators.C(); + CustomShortCircuitOperators.C c3 = c && c2; + CustomShortCircuitOperators.C c4 = c || c2; + Console.WriteLine(c3.ToString()); + Console.WriteLine(c4.ToString()); + } + + private static void Test2() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + if (c && c) + { + Console.WriteLine(c.ToString()); + } + + if (!(c && c)) + { + Console.WriteLine(c.ToString()); + } + } + + private static void Test3() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + if (c) + { + Console.WriteLine(c.ToString()); + } + if (!c) + { + Console.WriteLine(c.ToString()); + } + } + } +} \ No newline at end of file diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs new file mode 100644 index 0000000000..5eb7012284 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.Decompiler.Tests.Helpers; +using Microsoft.CSharp; +using Mono.Cecil; +using NUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests +{ + public abstract class DecompilerTestBase + { + protected static void ValidateFileRoundtrip(string samplesFileName) + { + var lines = File.ReadAllLines(Path.Combine(@"..\..\Tests", samplesFileName)); + var testCode = RemoveIgnorableLines(lines); + var decompiledTestCode = RoundtripCode(testCode); + CodeAssert.AreEqual(testCode, decompiledTestCode); + } + + static string RemoveIgnorableLines(IEnumerable lines) + { + return CodeSampleFileParser.ConcatLines(lines.Where(l => !CodeSampleFileParser.IsCommentOrBlank(l))); + } + + /// + /// Compiles and decompiles a source code. + /// + /// The source code to copile. + /// The decompilation result of compiled source code. + static string RoundtripCode(string code) + { + DecompilerSettings settings = new DecompilerSettings(); + settings.FullyQualifyAmbiguousTypeNames = false; + AssemblyDefinition assembly = Compile(code); + AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule) { Settings = settings }); + decompiler.AddAssembly(assembly); + new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit); + StringWriter output = new StringWriter(); + decompiler.GenerateCode(new PlainTextOutput(output)); + return output.ToString(); + } + + static AssemblyDefinition Compile(string code) + { + CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); + CompilerParameters options = new CompilerParameters(); + options.ReferencedAssemblies.Add("System.Core.dll"); + CompilerResults results = provider.CompileAssemblyFromSource(options, code); + try + { + if (results.Errors.Count > 0) + { + StringBuilder b = new StringBuilder("Compiler error:"); + foreach (var error in results.Errors) + { + b.AppendLine(error.ToString()); + } + throw new Exception(b.ToString()); + } + return AssemblyDefinition.ReadAssembly(results.PathToAssembly); + } + finally + { + File.Delete(results.PathToAssembly); + results.TempFiles.Delete(); + } + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs new file mode 100644 index 0000000000..5d5071f676 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs @@ -0,0 +1,189 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; + +public static class DelegateConstruction +{ + class InstanceTests + { + public Action CaptureOfThis() + { + return delegate { + CaptureOfThis(); + }; + } + + public Action CaptureOfThisAndParameter(int a) + { + return delegate { + CaptureOfThisAndParameter(a); + }; + } + + public Action CaptureOfThisAndParameterInForEach(int a) + { + foreach (int item in Enumerable.Empty()) { + if (item > 0) { + return delegate { + CaptureOfThisAndParameter(item + a); + }; + } + } + return null; + } + + public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) + { + foreach (int item in Enumerable.Empty()) { + int copyOfItem = item; + if (item > 0) { + return delegate { + CaptureOfThisAndParameter(item + a + copyOfItem); + }; + } + } + return null; + } + } + + public static void Test(this string a) + { + } + + public static Action ExtensionMethodUnbound() + { + return new Action(DelegateConstruction.Test); + } + + public static Action ExtensionMethodBound() + { + return new Action("abc".Test); + } + + public static Action ExtensionMethodBoundOnNull() + { + return new Action(((string)null).Test); + } + + public static object StaticMethod() + { + return new Func(DelegateConstruction.ExtensionMethodBound); + } + + public static object InstanceMethod() + { + return new Func("hello".ToUpper); + } + + public static object InstanceMethodOnNull() + { + return new Func(((string)null).ToUpper); + } + + public static List> AnonymousMethodStoreWithinLoop() + { + List> list = new List>(); + for (int i = 0; i < 10; i++) + { + int counter; + list.Add(delegate(int x) + { + counter = x; + } + ); + } + return list; + } + + public static List> AnonymousMethodStoreOutsideLoop() + { + List> list = new List>(); + int counter; + for (int i = 0; i < 10; i++) + { + list.Add(delegate(int x) + { + counter = x; + } + ); + } + return list; + } + + public static Action StaticAnonymousMethodNoClosure() + { + return delegate + { + Console.WriteLine(); + }; + } + + public static void NameConflict() + { + // i is captured variable, + // j is parameter in anonymous method + // k is local in anonymous method, + // l is local in main method + // Ensure that the decompiler doesn't introduce name conflicts + List> list = new List>(); + for (int l = 0; l < 10; l++) { + int i; + for (i = 0; i < 10; i++) { + list.Add( + delegate (int j) { + for (int k = 0; k < i; k += j) { + Console.WriteLine(); + } + }); + } + } + } + + public static void NameConflict2(int j) + { + List> list = new List>(); + for (int k = 0; k < 10; k++) { + list.Add( + delegate(int i) { + Console.WriteLine(i); + }); + } + } + + public static Action NameConflict3(int i) + { + return delegate(int j) { + for (int k = 0; k < j; k++) { + Console.WriteLine(k); + } + }; + } + + public static Func> CurriedAddition(int a) + { + return b => c => a + b + c; + } + + public static Func>> CurriedAddition2(int a) + { + return b => c => d => a + b + c + d; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs new file mode 100644 index 0000000000..0db35e3573 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs @@ -0,0 +1,128 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Threading; + +public class ExceptionHandling +{ + public void MethodEndingWithEndFinally() + { + try + { + throw null; + } + finally + { + Console.WriteLine(); + } + } + + public void MethodEndingWithRethrow() + { + try + { + throw null; + } + catch + { + throw; + } + } + + public void TryCatchFinally() + { + try + { + Console.WriteLine("Try"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + Console.WriteLine("Finally"); + } + } + + public void TryCatchMultipleHandlers() + { + try + { + Console.WriteLine("Try"); + } + catch (InvalidOperationException ex) + { + Console.WriteLine(ex.Message); + } + catch (Exception ex2) + { + Console.WriteLine(ex2.Message); + } + catch + { + Console.WriteLine("other"); + } + } + + public void NoUsingStatementBecauseTheVariableIsAssignedTo() + { + CancellationTokenSource cancellationTokenSource = null; + try + { + cancellationTokenSource = new CancellationTokenSource(); + } + finally + { + if (cancellationTokenSource != null) + { + cancellationTokenSource.Dispose(); + } + } + } + + public void UsingStatementThatChangesTheVariable() + { + CancellationTokenSource cancellationTokenSource = null; + using (cancellationTokenSource) + { + cancellationTokenSource = new CancellationTokenSource(); + } + } + + public void TwoCatchBlocksWithSameVariable() + { + try + { + Console.WriteLine("Try1"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + try + { + Console.WriteLine("Try2"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Generics.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Generics.cs new file mode 100644 index 0000000000..9b7bd3feaf --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Generics.cs @@ -0,0 +1,105 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; + +public static class Generics +{ + public class MyArray + { + public class NestedClass + { + public T Item1; + public Y Item2; + } + + public enum NestedEnum + { + A, + B + } + + private T[] arr; + + public MyArray(int capacity) + { + this.arr = new T[capacity]; + } + + public void Size(int capacity) + { + Array.Resize(ref this.arr, capacity); + } + + public void Grow(int capacity) + { + if (capacity >= this.arr.Length) + { + this.Size(capacity); + } + } + } + + public interface IInterface + { + void Method1() where T : class; + void Method2() where T : class; + } + + public abstract class Base : Generics.IInterface + { + // constraints must be repeated on implicit interface implementation + public abstract void Method1() where T : class; + + // constraints must not be specified on explicit interface implementation + void Generics.IInterface.Method2() + { + } + } + + public class Derived : Generics.Base + { + // constraints are inherited automatically and must not be specified + public override void Method1() + { + } + } + + private const Generics.MyArray.NestedEnum enumVal = Generics.MyArray.NestedEnum.A; + private static Type type1 = typeof(List<>); + private static Type type2 = typeof(Generics.MyArray<>); + private static Type type3 = typeof(List<>.Enumerator); + private static Type type4 = typeof(Generics.MyArray<>.NestedClass<>); + private static Type type5 = typeof(List[]); + private static Type type6 = typeof(Generics.MyArray<>.NestedEnum); + + public static void MethodWithConstraint() where T : class, S where S : ICloneable, new() + { + } + + public static void MethodWithStructConstraint() where T : struct + { + } + + public static Dictionary.KeyCollection.Enumerator GetEnumerator(Dictionary d, Generics.MyArray.NestedClass nc) + { + // Tests references to inner classes in generic classes + return d.Keys.GetEnumerator(); + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs new file mode 100644 index 0000000000..0a82fb82ac --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using DiffLib; +using NUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.Helpers +{ + public class CodeAssert + { + public static void AreEqual(string input1, string input2) + { + var diff = new StringWriter(); + if (!Compare(input1, input2, diff)) { + Assert.Fail(diff.ToString()); + } + } + + static bool Compare(string input1, string input2, StringWriter diff) + { + var differ = new AlignedDiff( + NormalizeAndSplitCode(input1), + NormalizeAndSplitCode(input2), + new CodeLineEqualityComparer(), + new StringSimilarityComparer(), + new StringAlignmentFilter()); + + bool result = true, ignoreChange; + + int line1 = 0, line2 = 0; + + foreach (var change in differ.Generate()) { + switch (change.Change) { + case ChangeType.Same: + diff.Write("{0,4} {1,4} ", ++line1, ++line2); + diff.Write(" "); + diff.WriteLine(change.Element1); + break; + case ChangeType.Added: + diff.Write(" {1,4} ", line1, ++line2); + result &= ignoreChange = ShouldIgnoreChange(change.Element2); + diff.Write(ignoreChange ? " " : " + "); + diff.WriteLine(change.Element2); + break; + case ChangeType.Deleted: + diff.Write("{0,4} ", ++line1, line2); + result &= ignoreChange = ShouldIgnoreChange(change.Element1); + diff.Write(ignoreChange ? " " : " - "); + diff.WriteLine(change.Element1); + break; + case ChangeType.Changed: + diff.Write("{0,4} ", ++line1, line2); + result = false; + diff.Write("(-) "); + diff.WriteLine(change.Element1); + diff.Write(" {1,4} ", line1, ++line2); + diff.Write("(+) "); + diff.WriteLine(change.Element2); + break; + } + } + + return result; + } + + class CodeLineEqualityComparer : IEqualityComparer + { + private IEqualityComparer baseComparer = EqualityComparer.Default; + + public bool Equals(string x, string y) + { + return baseComparer.Equals( + NormalizeLine(x), + NormalizeLine(y) + ); + } + + public int GetHashCode(string obj) + { + return baseComparer.GetHashCode(NormalizeLine(obj)); + } + } + + private static string NormalizeLine(string line) + { + line = line.Trim(); + var index = line.IndexOf("//"); + if (index >= 0) { + return line.Substring(0, index); + } else if (line.StartsWith("#")) { + return string.Empty; + } else { + return line; + } + } + + private static bool ShouldIgnoreChange(string line) + { + // for the result, we should ignore blank lines and added comments + return NormalizeLine(line) == string.Empty; + } + + private static IEnumerable NormalizeAndSplitCode(string input) + { + return input.Split(new[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.None); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs new file mode 100644 index 0000000000..2519165578 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using ICSharpCode.Decompiler.Ast.Transforms; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.Decompiler.Tests.Helpers +{ + class RemoveCompilerAttribute : DepthFirstAstVisitor, IAstTransform + { + public override object VisitAttribute(NRefactory.CSharp.Attribute attribute, object data) + { + var section = (AttributeSection)attribute.Parent; + SimpleType type = attribute.Type as SimpleType; + if (section.AttributeTarget == "assembly" && + (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion")) + { + attribute.Remove(); + if (section.Attributes.Count == 0) + section.Remove(); + } + if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode") + { + attribute.Remove(); + if (section.Attributes.Count == 0) + section.Remove(); + } + return null; + } + + public void Run(AstNode node) + { + node.AcceptVisitor(this, null); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj new file mode 100644 index 0000000000..a3bcddf9ea --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -0,0 +1,113 @@ + + + + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22} + Debug + x86 + Library + ICSharpCode.Decompiler.Tests + ICSharpCode.Decompiler.Tests + v4.0 + Properties + True + False + 4 + false + False + 67,169,1058,728 + + + x86 + False + Auto + 4194304 + 4096 + + + ..\bin\Debug\ + true + Full + False + DEBUG;TRACE + + + ..\bin\Release\ + false + None + True + TRACE + + + + ..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll + + + False + .\nunit.framework.dll + + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + {984CC812-9470-4A13-AFF9-CC44068D666C} + ICSharpCode.Decompiler + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs new file mode 100644 index 0000000000..e06b680d68 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs @@ -0,0 +1,254 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public class IncrementDecrement +{ + [Flags] + private enum MyEnum + { + None = 0, + One = 1, + Two = 2, + Four = 4 + } + + public class MutableClass + { + public int Field; + + public int Property + { + get; + set; + } + + public uint this[string name] + { + get + { + return 0u; + } + set + { + } + } + } + + private IncrementDecrement.MyEnum enumField; + public static int StaticField; + + public static int StaticProperty + { + get; + set; + } + + private IncrementDecrement.MutableClass M() + { + return new IncrementDecrement.MutableClass(); + } + + private int[,] Array() + { + return null; + } + + private unsafe int* GetPointer() + { + return null; + } + + public int PreIncrementInAddition(int i, int j) + { + return i + ++j; + } + + public int PreIncrementArrayElement(int[] array, int pos) + { + return --array[pos]; + } + + public int PreIncrementInstanceField() + { + return ++this.M().Field; + } + + public int PreIncrementInstanceField2(IncrementDecrement.MutableClass m) + { + return ++m.Field; + } + + public int PreIncrementInstanceProperty() + { + return ++this.M().Property; + } + + public int PreIncrementStaticField() + { + return ++IncrementDecrement.StaticField; + } + + public int PreIncrementStaticProperty() + { + return ++IncrementDecrement.StaticProperty; + } + +// public uint PreIncrementIndexer(string name) +// { +// return ++this.M()[name]; +// } + + public int PreIncrementByRef(ref int i) + { + return ++i; + } + + public unsafe int PreIncrementByPointer() + { + return ++(*this.GetPointer()); + } + + public int PreIncrement2DArray() + { + return ++this.Array()[1, 2]; + } + + public int CompoundAssignInstanceField() + { + return this.M().Field *= 10; + } + + public int CompoundAssignInstanceProperty() + { + return this.M().Property *= 10; + } + + public int CompoundAssignStaticField() + { + return IncrementDecrement.StaticField ^= 100; + } + + public int CompoundAssignStaticProperty() + { + return IncrementDecrement.StaticProperty &= 10; + } + + public int CompoundAssignArrayElement1(int[] array, int pos) + { + return array[pos] *= 10; + } + + public int CompoundAssignArrayElement2(int[] array) + { + return array[Environment.TickCount] *= 10; + } + +// public uint CompoundAssignIndexer(string name) +// { +// return this.M()[name] -= 2; +// } + + public int CompoundAssignIncrement2DArray() + { + return this.Array()[1, 2] %= 10; + } + + public int CompoundAssignByRef(ref int i) + { + return i <<= 2; + } + + public unsafe double CompoundAssignByPointer(double* ptr) + { + return *ptr /= 1.5; + } + + public void CompoundAssignEnum() + { + this.enumField |= IncrementDecrement.MyEnum.Two; + this.enumField &= ~IncrementDecrement.MyEnum.Four; + } + + public int PostIncrementInAddition(int i, int j) + { + return i++ + j; + } + + public void PostIncrementInlineLocalVariable(Func f) + { + int num = 0; + f(num++); + } + + public int PostIncrementArrayElement(int[] array, int pos) + { + return array[pos]--; + } + + public int PostIncrementStaticField() + { + return IncrementDecrement.StaticField++; + } + + public int PostIncrementStaticProperty() + { + return IncrementDecrement.StaticProperty++; + } + + public int PostIncrementInstanceField(IncrementDecrement.MutableClass m) + { + return m.Field++; + } + +// public uint PostIncrementIndexer(string name) +// { +// return this.M()[name]++; +// } + +// public unsafe int PostIncrementOfPointer(int* ptr) +// { +// return *(ptr++); +// } + + public int PostIncrementInstanceField() + { + return this.M().Field--; + } + + public int PostIncrementInstanceProperty() + { + return this.M().Property--; + } + + public int PostIncrement2DArray() + { + return this.Array()[IncrementDecrement.StaticField, IncrementDecrement.StaticProperty]++; + } + + public int PostIncrementByRef(ref int i) + { + return i++; + } + + public unsafe int PostIncrementByPointer() + { + return (*this.GetPointer())++; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/InitializerTests.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/InitializerTests.cs new file mode 100644 index 0000000000..a4ab57fbf8 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/InitializerTests.cs @@ -0,0 +1,869 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; + +public class InitializerTests +{ + private enum MyEnum + { + a, + b + } + + private enum MyEnum2 + { + c, + d + } + + private class Data + { + public List FieldList = new List(); + public InitializerTests.MyEnum a + { + get; + set; + } + public List PropertyList + { + get; + set; + } + + public InitializerTests.Data MoreData + { + get; + set; + } + + public InitializerTests.StructData NestedStruct + { + get; + set; + } + } + + private struct StructData + { + public int Field; + public int Property + { + get; + set; + } + + public InitializerTests.Data MoreData + { + get; + set; + } + + public StructData(int initialValue) + { + this = default(InitializerTests.StructData); + this.Field = initialValue; + this.Property = initialValue; + } + } + + // Helper methods used to ensure initializers used within expressions work correctly + private static void X(object a, object b) + { + } + + private static object Y() + { + return null; + } + + #region Array Initializers + public static void Array1() + { + InitializerTests.X(InitializerTests.Y(), new int[] + { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + }); + } + + public static void Array2(int a, int b, int c) + { + InitializerTests.X(InitializerTests.Y(), new int[] + { + a, + 0, + b, + 0, + c + }); + } + + public static void NestedArray(int a, int b, int c) + { + InitializerTests.X(InitializerTests.Y(), new int[][] + { + new int[] + { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + }, + new int[] + { + a, + b, + c + }, + new int[] + { + 1, + 2, + 3, + 4, + 5, + 6 + } + }); + } + + public static void ArrayBoolean() + { + InitializerTests.X(InitializerTests.Y(), new bool[] + { + true, + false, + true, + false, + false, + false, + true, + true + }); + } + + public static void ArrayByte() + { + InitializerTests.X(InitializerTests.Y(), new byte[] + { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 254, + 255 + }); + } + + public static void ArraySByte() + { + InitializerTests.X(InitializerTests.Y(), new sbyte[] + { + -128, + -127, + 0, + 1, + 2, + 3, + 4, + 127 + }); + } + + public static void ArrayShort() + { + InitializerTests.X(InitializerTests.Y(), new short[] + { + -32768, + -1, + 0, + 1, + 32767 + }); + } + + public static void ArrayUShort() + { + InitializerTests.X(InitializerTests.Y(), new ushort[] + { + 0, + 1, + 32767, + 32768, + 65534, + 65535 + }); + } + + public static void ArrayInt() + { + InitializerTests.X(InitializerTests.Y(), new int[] + { + 1, + -2, + 2000000000, + 4, + 5, + -6, + 7, + 8, + 9, + 10 + }); + } + + public static void ArrayUInt() + { + InitializerTests.X(InitializerTests.Y(), new uint[] + { + 1u, + 2000000000u, + 3000000000u, + 4u, + 5u, + 6u, + 7u, + 8u, + 9u, + 10u + }); + } + + public static void ArrayLong() + { + InitializerTests.X(InitializerTests.Y(), new long[] + { + -4999999999999999999L, + -1L, + 0L, + 1L, + 4999999999999999999L + }); + } + + public static void ArrayULong() + { + InitializerTests.X(InitializerTests.Y(), new ulong[] + { + 1uL, + 2000000000uL, + 3000000000uL, + 4uL, + 5uL, + 6uL, + 7uL, + 8uL, + 4999999999999999999uL, + 9999999999999999999uL + }); + } + + public static void ArrayFloat() + { + InitializerTests.X(InitializerTests.Y(), new float[] + { + -1.5f, + 0f, + 1.5f, + float.NegativeInfinity, + float.PositiveInfinity, + float.NaN + }); + } + + public static void ArrayDouble() + { + InitializerTests.X(InitializerTests.Y(), new double[] + { + -1.5, + 0.0, + 1.5, + double.NegativeInfinity, + double.PositiveInfinity, + double.NaN + }); + } + + public static void ArrayDecimal() + { + InitializerTests.X(InitializerTests.Y(), new decimal[] + { + -100m, + 0m, + 100m, + -79228162514264337593543950335m, + 79228162514264337593543950335m, + 0.0000001m + }); + } + + public static void ArrayString() + { + InitializerTests.X(InitializerTests.Y(), new string[] + { + "", + null, + "Hello", + "World" + }); + } + + public static void ArrayEnum() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.MyEnum[] + { + InitializerTests.MyEnum.a, + InitializerTests.MyEnum.b, + InitializerTests.MyEnum.a, + InitializerTests.MyEnum.b + }); + } + #endregion + + public static void CollectionInitializerList() + { + InitializerTests.X(InitializerTests.Y(), new List + { + 1, + 2, + 3 + }); + } + + public static void CollectionInitializerDictionary() + { + InitializerTests.X(InitializerTests.Y(), new Dictionary + { + { + "First", + 1 + }, + { + "Second", + 2 + }, + { + "Third", + 3 + } + }); + } + + public static void CollectionInitializerDictionaryWithEnumTypes() + { + InitializerTests.X(InitializerTests.Y(), new Dictionary + { + { + InitializerTests.MyEnum.a, + InitializerTests.MyEnum2.c + }, + { + InitializerTests.MyEnum.b, + InitializerTests.MyEnum2.d + } + }); + } + + public static void NotACollectionInitializer() + { + List list = new List(); + list.Add(1); + list.Add(2); + list.Add(3); + InitializerTests.X(InitializerTests.Y(), list); + } + + public static void ObjectInitializer() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + a = InitializerTests.MyEnum.a + }); + } + + public static void NotAObjectInitializer() + { + InitializerTests.Data data = new InitializerTests.Data(); + data.a = InitializerTests.MyEnum.a; + InitializerTests.X(InitializerTests.Y(), data); + } + + public static void ObjectInitializerAssignCollectionToField() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + a = InitializerTests.MyEnum.a, + FieldList = new List + { + InitializerTests.MyEnum2.c, + InitializerTests.MyEnum2.d + } + }); + } + + public static void ObjectInitializerAddToCollectionInField() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + a = InitializerTests.MyEnum.a, + FieldList = + { + InitializerTests.MyEnum2.c, + InitializerTests.MyEnum2.d + } + }); + } + + public static void ObjectInitializerAssignCollectionToProperty() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + a = InitializerTests.MyEnum.a, + PropertyList = new List + { + InitializerTests.MyEnum2.c, + InitializerTests.MyEnum2.d + } + }); + } + + public static void ObjectInitializerAddToCollectionInProperty() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + a = InitializerTests.MyEnum.a, + PropertyList = + { + InitializerTests.MyEnum2.c, + InitializerTests.MyEnum2.d + } + }); + } + + public static void ObjectInitializerWithInitializationOfNestedObjects() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + MoreData = + { + a = InitializerTests.MyEnum.a + } + }); + } + + public static void StructInitializer_DefaultConstructor() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData + { + Field = 1, + Property = 2 + }); + } + + public static void StructInitializer_ExplicitConstructor() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0) + { + Field = 1, + Property = 2 + }); + } + + public static void StructInitializerWithInitializationOfNestedObjects() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData + { + MoreData = + { + a = InitializerTests.MyEnum.a, + FieldList = + { + InitializerTests.MyEnum2.c, + InitializerTests.MyEnum2.d + } + } + }); + } + + public static void StructInitializerWithinObjectInitializer() + { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data + { + NestedStruct = new InitializerTests.StructData(2) + { + Field = 1, + Property = 2 + } + }); + } + + public void MultidimensionalInit() + { + int[,] expr_09 = new int[, ] + { + + { + 0, + 0, + 0, + 0 + }, + + { + 1, + 1, + 1, + 1 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 1, + 1, + 1, + 1 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + } + }; + } + + public void MultidimensionalInit2() + { + int[][,] array = new int[][,] + { + new int[, ] + { + + { + 0, + 0, + 0, + 0 + }, + + { + 1, + 1, + 1, + 1 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 0, + 0 + } + + }, + new int[, ] + { + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + } + + }, + new int[, ] + { + + { + 0, + 0, + 0, + 0 + }, + + { + 1, + 1, + 1, + 1 + }, + + { + 0, + 0, + 0, + 0 + }, + + { + 0, + 0, + 0, + 0 + } + }, + new int[, ] + { + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + }, + + { + 0, + 0, + 1, + 0 + } + + } + }; + } + + public void ArrayOfArrayOfArrayInit() + { + int[][,,] array = new int[][,,] + { + new int[, , ] + { + { + { + 1, + 2, + 3 + }, + { + 4, + 5, + 6 + }, + { + 7, + 8, + 9 + } + }, + { + { + 11, + 12, + 13 + }, + { + 14, + 15, + 16 + }, + { + 17, + 18, + 19 + } + } + }, + + new int[, , ] + { + { + { + 21, + 22, + 23 + }, + { + 24, + 25, + 26 + }, + { + 27, + 28, + 29 + } + }, + { + { + 31, + 32, + 33 + }, + { + 34, + 35, + 36 + }, + { + 37, + 38, + 39 + } + } + } + }; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Loops.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Loops.cs new file mode 100644 index 0000000000..03427a8bdc --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Loops.cs @@ -0,0 +1,74 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; + +public class Loops +{ + public void ForEach(IEnumerable enumerable) + { + foreach (string current in enumerable) + { + current.ToLower(); + } + } + + public void ForEachOverList(List list) + { + // List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface + foreach (string current in list) + { + current.ToLower(); + } + } + + public void ForEachOverNonGenericEnumerable(IEnumerable enumerable) + { + foreach (object current in enumerable) + { + current.ToString(); + } + } + + public void ForEachOverNonGenericEnumerableWithAutomaticCast(IEnumerable enumerable) + { + foreach (int num in enumerable) + { + num.ToString(); + } + } + +// public void ForEachOverArray(string[] array) +// { +// foreach (string text in array) +// { +// text.ToLower(); +// } +// } + + public void ForOverArray(string[] array) + { + for (int i = 0; i < array.Length; i++) + { + array[i].ToLower(); + } + } +} + diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs new file mode 100644 index 0000000000..c3557cee44 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs @@ -0,0 +1,58 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public class MultidimensionalArray +{ + internal class Generic where T : new() + { + private T[,] a = new T[20, 20]; + private S[,][] b = new S[20, 20][]; + + public T this[int i, int j] + { + get + { + return this.a[i, j]; + } + set + { + this.a[i, j] = value; + } + } + + public void TestB(S x, ref S y) + { + this.b[5, 3] = new S[10]; + this.b[5, 3][0] = default(S); + this.b[5, 3][1] = x; + this.b[5, 3][2] = y; + } + + public void PassByReference(ref T arr) + { + this.PassByReference(ref this.a[10, 10]); + } + } + + public int[][,] MakeArray() + { + return new int[10][,]; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/PInvoke.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/PInvoke.cs new file mode 100644 index 0000000000..fe9b9b5bcc --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/PInvoke.cs @@ -0,0 +1,87 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +// P/Invoke and marshalling attribute tests +public class PInvoke +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)] + public struct MarshalAsTest + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public uint[] FixedArray; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)] + public int[] FixedBoolArray; + + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] SafeBStrArray; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string FixedString; + } + + [StructLayout(LayoutKind.Explicit)] + public struct Rect + { + [FieldOffset(0)] + public int left; + [FieldOffset(4)] + public int top; + [FieldOffset(8)] + public int right; + [FieldOffset(12)] + public int bottom; + } + + public static decimal MarshalAttributesOnPropertyAccessors + { + [return: MarshalAs(UnmanagedType.Currency)] + get + { + return 0m; + } + [param: MarshalAs(UnmanagedType.Currency)] + set + { + } + } + + [DllImport("xyz.dll", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input); + + [DllImport("xyz.dll")] + private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar); + + [DllImport("xyz.dll")] + private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar); + + [DllImport("xyz.dll")] + private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar); + + public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o) + { + } + + public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o) + { + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs new file mode 100644 index 0000000000..4bacc06e3e --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs @@ -0,0 +1,81 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Text; + +public class PropertiesAndEvents +{ + public event EventHandler AutomaticEvent; + + [field: NonSerialized] + public event EventHandler AutomaticEventWithInitializer = delegate + { + } + ; + + public event EventHandler CustomEvent + { + add + { + this.AutomaticEvent += value; + } + remove + { + this.AutomaticEvent -= value; + } + } + + public int AutomaticProperty + { + get; + set; + } + + public int CustomProperty + { + get + { + return this.AutomaticProperty; + } + set + { + this.AutomaticProperty = value; + } + } + + public int Getter(StringBuilder b) + { + return b.Length; + } + + public void Setter(StringBuilder b) + { + b.Capacity = 100; + } + + public char IndexerGetter(StringBuilder b) + { + return b[50]; + } + + public void IndexerSetter(StringBuilder b) + { + b[42] = 'b'; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/QueryExpressions.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/QueryExpressions.cs new file mode 100644 index 0000000000..143f3d30ca --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/QueryExpressions.cs @@ -0,0 +1,164 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; + +public class QueryExpressions +{ + public class Customer + { + public int CustomerID; + public IEnumerable Orders; + public string Name; + public string Country; + public string City; + } + + public class Order + { + public int OrderID; + public DateTime OrderDate; + public Customer Customer; + public int CustomerID; + public decimal Total; + public IEnumerable Details; + } + + public class OrderDetail + { + public decimal UnitPrice; + public int Quantity; + } + + public IEnumerable customers; + public IEnumerable orders; + + public object MultipleWhere() + { + return + from c in this.customers + where c.Orders.Count() > 10 + where c.Country == "DE" + select c; + } + + public object SelectManyFollowedBySelect() + { + return + from c in this.customers + from o in c.Orders + select new { c.Name, o.OrderID, o.Total }; + } + + public object SelectManyFollowedByOrderBy() + { + return + from c in this.customers + from o in c.Orders + orderby o.Total descending + select new { c.Name, o.OrderID, o.Total }; + } + + public object MultipleSelectManyFollowedBySelect() + { + return + from c in this.customers + from o in c.Orders + from d in o.Details + select new { c.Name, o.OrderID, d.Quantity }; + } + + public object MultipleSelectManyFollowedByLet() + { + return + from c in this.customers + from o in c.Orders + from d in o.Details + let x = d.Quantity * d.UnitPrice + select new { c.Name, o.OrderID, x }; + } + + public object FromLetWhereSelect() + { + return + from o in this.orders + let t = o.Details.Sum(d => d.UnitPrice * d.Quantity) + where t >= 1000 + select new { o.OrderID, Total = t }; + } + + public object MultipleLet() + { + return + from a in this.customers + let b = a.Country + let c = a.Name + select b + c; + } + + public object Join() + { + return + from c in customers + join o in orders on c.CustomerID equals o.CustomerID + select new { c.Name, o.OrderDate, o.Total }; + } + + public object JoinInto() + { + return + from c in customers + join o in orders on c.CustomerID equals o.CustomerID into co + let n = co.Count() + where n >= 10 + select new { c.Name, OrderCount = n }; + } + + public object OrderBy() + { + return + from o in orders + orderby o.Customer.Name, o.Total descending + select o; + } + + public object GroupBy() + { + return + from c in customers + group c.Name by c.Country; + } + + public object ExplicitType() + { + return + from Customer c in customers + where c.City == "London" + select c; + } + + public object QueryContinuation() + { + return + from c in customers + group c by c.Country into g + select new { Country = g.Key, CustCount = g.Count() }; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/StackTests/StackTests.exe b/src/Libraries/ICSharpCode.Decompiler/Tests/StackTests/StackTests.exe new file mode 100644 index 0000000000000000000000000000000000000000..db6194ad6836b1f6367770a08757a45309c92121 GIT binary patch literal 2048 zcmeHH&ubGw6#jP8rZKg#f+P{NPKkvQG_=-3717vQf3_M)t5OAOqRA z=&cv^APAm32%=E2c+s1u{smt8M+kzK`n}z48>kedC&5SNz4yI0^X7Xqvl$wlMFcBO$j3CwL;XrDI*7utt!R9!Xc*w>xXgsPM*%l1@RD`(15RZAT^ zS5y=BxX!h-#CM0K3j@HQVdCSLk)h??7GWCAMl2v@2GMsJTE&s)5T$6C6W$`r7GnhA znh5fbfL8yvYC|ZCC}XU9CUF0(^T6gmXV#A@fE}zzjQHdV0&=SEo042GIM>2bj4QAGug>P z(N30$r&ir$GTF)MQHjKpsXCBKrB*ZP`b>7zJQ(N34r@*JHj39mFH4@>?^sC591zwl z>z{mrHknQJ%I&3l<;b@8auFg2o2ZqPyOeF%+oZPno@(<=n<*6H*}mfGK0{7`A{B1$ z&voT`x_Y_~NTd-pF-&Lf12x(wgqfn}RITf-q<%1#me@!Un@NeU5SbGrr-bVc;yr@< zYId1cgdyVu8`~t{S4R($etEwe=KSX&eTVlFGV2O$6k8GJvq)2m1iSg_}=WB>2k>M__?K1OmI*VrixfvKEHgL<=x2a9Ab { { "CompilerVersion", "v4.0" } }); + CompilerParameters options = new CompilerParameters(); + options.CompilerOptions = "/unsafe /o-"; + options.ReferencedAssemblies.Add("System.Core.dll"); + CompilerResults results = provider.CompileAssemblyFromSource(options, code); + try { + if (results.Errors.Count > 0) { + StringBuilder b = new StringBuilder("Compiler error:"); + foreach (var error in results.Errors) { + b.AppendLine(error.ToString()); + } + throw new Exception(b.ToString()); + } + return AssemblyDefinition.ReadAssembly(results.PathToAssembly); + } finally { + File.Delete(results.PathToAssembly); + results.TempFiles.Delete(); + } + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs new file mode 100644 index 0000000000..3224debdde --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs @@ -0,0 +1,109 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public class TypeAnalysisTests +{ + public byte SubtractFrom256(byte b) + { + return (byte)(256 - (int)b); + } + + #region Shift + public int LShiftInteger(int num1, int num2) + { + return num1 << num2; + } + + public uint LShiftUnsignedInteger(uint num1, uint num2) + { + return num1 << (int)num2; + } + + public long LShiftLong(long num1, long num2) + { + return num1 << (int)num2; + } + + public ulong LShiftUnsignedLong(ulong num1, ulong num2) + { + return num1 << (int)num2; + } + + public int RShiftInteger(int num1, int num2) + { + return num1 >> num2; + } + + public uint RShiftUnsignedInteger(uint num1, int num2) + { + return num1 >> num2; + } + + public long RShiftLong(long num1, long num2) + { + return num1 >> (int)num2; + } + + public ulong RShiftUnsignedLong(ulong num1, ulong num2) + { + return num1 >> (int)num2; + } + + public int ShiftByte(byte num) + { + return (int)num << 8; + } + + public int RShiftByte(byte num) + { + return num >> 8; + } + + public uint RShiftByteWithZeroExtension(byte num) + { + return (uint)num >> 8; + } + + public int RShiftByteAsSByte(byte num) + { + return (sbyte)num >> 8; + } + + public int RShiftSByte(sbyte num) + { + return num >> 8; + } + + public uint RShiftSByteWithZeroExtension(sbyte num) + { + return (uint)num >> 8; + } + + public int RShiftSByteAsByte(sbyte num) + { + return (byte)num >> 8; + } + #endregion + + public int GetHashCode(long num) + { + return (int)num ^ (int)(num >> 32); + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs new file mode 100644 index 0000000000..fb48d016ed --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.Types +{ + [TestFixture] + public class EnumTests : DecompilerTestBase + { + [Test] + public void EnumSamples() + { + ValidateFileRoundtrip(@"Types\S_EnumSamples.cs"); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs new file mode 100644 index 0000000000..67d81fa30e --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs @@ -0,0 +1,114 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +//$CS +using System; +//$CE + +//$$ SingleValue +public class TS_SingleValue +{ + public AttributeTargets Method() + { + return AttributeTargets.Class; + } +} +//$$ TwoValuesOr +public class TS_TwoValuesOr +{ + public AttributeTargets Method() + { + return AttributeTargets.Class | AttributeTargets.Method; + } +} +//$$ ThreeValuesOr +public class TS_ThreeValuesOr +{ + public AttributeTargets Method() + { + return AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter; + } +} +//$$ UnknownNumericValue +public class TS_UnknownNumericValue +{ + public AttributeTargets Method() + { + return (AttributeTargets)1000000; + } +} +//$$ AllValue +public class TS_AllValue +{ + public AttributeTargets Method() + { + return AttributeTargets.All; + } +} +//$$ ZeroValue +public class TS_ZeroValue +{ + public AttributeTargets Method() + { + return (AttributeTargets)0; + } +} +//$$ PreservingTypeWhenBoxed +public class TS_PreservingTypeWhenBoxed +{ + public object Method() + { + return AttributeTargets.Delegate; + } +} +//$$ PreservingTypeWhenBoxedTwoEnum +public class TS_PreservingTypeWhenBoxedTwoEnum +{ + public object Method() + { + return AttributeTargets.Class | AttributeTargets.Delegate; + } +} +//$$ DeclarationSimpleEnum +public enum TS_DeclarationSimpleEnum +{ + Item1, + Item2 +} +//$$ DeclarationLongBasedEnum +public enum TS_DeclarationLongBasedEnum : long +{ + Item1, + Item2 +} +//$$ DeclarationLongWithInitializers +public enum TS_DeclarationLongWithInitializers : long +{ + Item1, + Item2 = 20L, + Item3 +} +//$$ DeclarationShortWithInitializers +public enum TS_DeclarationShortWithInitializers : short +{ + Item1, + Item2 = 20, + Item3 +} +//$$ DeclarationByteWithInitializers +public enum TS_DeclarationByteWithInitializers : byte +{ + Item1, + Item2 = 20, + Item3 +} +//$$ DeclarationFlags +[Flags] +public enum TS_DeclarationFlags +{ + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + All = 7 +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs new file mode 100644 index 0000000000..99bf4279e3 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs @@ -0,0 +1,17 @@ +using System; + +namespace ClassMultiInterface +{ + public interface IA + { + } + public interface IA2 : IA + { + } + public interface IB + { + } + public class C : IA2, IB + { + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs new file mode 100644 index 0000000000..22458bcfce --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs @@ -0,0 +1,1121 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +//$CS +using System; +//$CE + +//$$ IndexerWithGetOnly +namespace IndexerWithGetOnly +{ + public class MyClass + { + public int this[int i] + { + get + { + return i; + } + } + } +} +//$$ IndexerWithSetOnly +namespace IndexerWithSetOnly +{ + public class MyClass + { + public int this[int i] + { + set + { + } + } + } +} +//$$ IndexerWithMoreParameters +namespace IndexerWithMoreParameters +{ + public class MyClass + { + public int this[int i, string s, Type t] + { + get + { + return 0; + } + } + } +} +//$$ IndexerInGenericClass +namespace IndexerInGenericClass +{ + public class MyClass + { + public int this[T t] + { + get + { + return 0; + } + } + } +} +//$$ OverloadedIndexer +namespace OverloadedIndexer +{ + public class MyClass + { + public int this[int t] + { + get + { + return 0; + } + } + public int this[string s] + { + get + { + return 0; + } + set + { + Console.WriteLine(value + " " + s); + } + } + } +} +//$$ IndexerInInterface +namespace IndexerInInterface +{ + public interface IInterface + { + int this[string s, string s2] + { + set; + } + } +} +//$$ IndexerInterfaceExplicitImplementation +namespace IndexerInterfaceExplicitImplementation +{ + public interface IMyInterface + { + int this[string s] + { + get; + } + } + public class MyClass : IMyInterface + { + int IMyInterface.this[string s] + { + get + { + return 3; + } + } + } +} +//$$ IndexerInterfaceImplementation +namespace IndexerInterfaceImplementation +{ + public interface IMyInterface + { + int this[string s] + { + get; + } + } + public class MyClass : IMyInterface + { + public int this[string s] + { + get + { + return 3; + } + } + } +} +//$$ IndexerAbstract +namespace IndexerAbstract +{ + public abstract class MyClass + { + public abstract int this[string s, string s2] + { + set; + } + protected abstract string this[int index] + { + get; + } + } +} +//$$ MethodExplicit +namespace MethodExplicit +{ + public interface IMyInterface + { + void MyMethod(); + } + public class MyClass : IMyInterface + { + void IMyInterface.MyMethod() + { + } + } +} +//$$ MethodFromInterfaceVirtual +namespace MethodFromInterfaceVirtual +{ + public interface IMyInterface + { + void MyMethod(); + } + public class MyClass : IMyInterface + { + public virtual void MyMethod() + { + } + } +} +//$$ MethodFromInterface +namespace MethodFromInterface +{ + public interface IMyInterface + { + void MyMethod(); + } + public class MyClass : IMyInterface + { + public void MyMethod() + { + } + } +} +//$$ MethodFromInterfaceAbstract +namespace MethodFromInterfaceAbstract +{ + public interface IMyInterface + { + void MyMethod(); + } + public abstract class MyClass : IMyInterface + { + public abstract void MyMethod(); + } +} +//$$ PropertyInterface +namespace PropertyInterface +{ + public interface IMyInterface + { + int MyProperty + { + get; + set; + } + } +} +//$$ PropertyInterfaceExplicitImplementation +namespace PropertyInterfaceExplicitImplementation +{ + public interface IMyInterface + { + int MyProperty + { + get; + set; + } + } + public class MyClass : IMyInterface + { + int IMyInterface.MyProperty + { + get + { + return 0; + } + set + { + } + } + } +} +//$$ PropertyInterfaceImplementation +namespace PropertyInterfaceImplementation +{ + public interface IMyInterface + { + int MyProperty + { + get; + set; + } + } + public class MyClass : IMyInterface + { + public int MyProperty + { + get + { + return 0; + } + set + { + } + } + } +} +//$$ PropertyPrivateGetPublicSet +namespace PropertyPrivateGetPublicSet +{ + public class MyClass + { + public int MyProperty + { + private get + { + return 3; + } + set + { + } + } + } +} +//$$ PropertyPublicGetProtectedSet +namespace PropertyPublicGetProtectedSet +{ + public class MyClass + { + public int MyProperty + { + get + { + return 3; + } + protected set + { + } + } + } +} +//$$ PropertyOverrideDefaultAccessorOnly +namespace PropertyOverrideDefaultAccessorOnly +{ + public class MyClass + { + public virtual int MyProperty + { + get + { + return 3; + } + protected set + { + } + } + } + public class Derived : MyClass + { + public override int MyProperty + { + get + { + return 4; + } + } + } +} +//$$ PropertyOverrideRestrictedAccessorOnly +namespace PropertyOverrideRestrictedAccessorOnly +{ + public class MyClass + { + public virtual int MyProperty + { + get + { + return 3; + } + protected set + { + } + } + } + public class Derived : MyClass + { + public override int MyProperty + { + protected set + { + } + } + } +} +//$$ PropertyOverrideOneAccessor +namespace PropertyOverrideOneAccessor +{ + public class MyClass + { + protected internal virtual int MyProperty + { + get + { + return 3; + } + protected set + { + } + } + } + public class DerivedNew : MyClass + { + public new virtual int MyProperty + { + set + { + } + } + } + public class DerivedOverride : DerivedNew + { + public override int MyProperty + { + set + { + } + } + } +} +//$$ IndexerOverrideRestrictedAccessorOnly +namespace IndexerOverrideRestrictedAccessorOnly +{ + public class MyClass + { + public virtual int this[string s] + { + get + { + return 3; + } + protected set + { + } + } + protected internal virtual int this[int i] + { + protected get + { + return 2; + } + set + { + } + } + } + public class Derived : MyClass + { + protected internal override int this[int i] + { + protected get + { + return 4; + } + } + } +} +//$$ HideProperty +namespace HideProperty +{ + public class A + { + public virtual int P + { + get + { + return 0; + } + set + { + } + } + } + public class B : A + { + private new int P + { + get + { + return 0; + } + set + { + } + } + } + public class C : B + { + public override int P + { + set + { + } + } + } +} +//$$ HideMembers +namespace HideMembers +{ + public class A + { + public int F; + public int Prop + { + get + { + return 3; + } + } + public int G + { + get + { + return 3; + } + } + } + public class B : A + { + public new int F + { + get + { + return 3; + } + } + public new string Prop + { + get + { + return "a"; + } + } + } + public class C : A + { + public new int G; + } + public class D : A + { + public new void F() + { + } + } + public class D1 : D + { + public new int F; + } + public class E : A + { + private new class F + { + } + } +} +//$$ HideMembers2 +namespace HideMembers2 +{ + public class G + { + public int Item + { + get + { + return 1; + } + } + } + public class G2 : G + { + public int this[int i] + { + get + { + return 2; + } + } + } + public class G3 : G2 + { + public new int Item + { + get + { + return 4; + } + } + } + public class H + { + public int this[int j] + { + get + { + return 0; + } + } + } + public class H2 : H + { + public int Item + { + get + { + return 2; + } + } + } + public class H3 : H2 + { + public new string this[int j] + { + get + { + return null; + } + } + } +} +//$$ HideMembers2a +namespace HideMembers2a +{ + public interface IA + { + int this[int i] + { + get; + } + } + public class A : IA + { + int IA.this[int i] + { + get + { + throw new NotImplementedException(); + } + } + } + public class A1 : A + { + public int this[int i] + { + get + { + return 3; + } + } + } +} +//$$ HideMembers3 +namespace HideMembers3 +{ + public class G + { + public void M1(T p) + { + } + public int M2(int t) + { + return 3; + } + } + public class G1 : G + { + public new int M1(int i) + { + return 0; + } + public int M2(T i) + { + return 2; + } + } + public class G2 : G + { + public int M1(T p) + { + return 4; + } + } + public class J + { + public int P + { + get + { + return 2; + } + } + } + public class J2 : J + { + public int get_P; + } +} +//$$ HideMembers4 +namespace HideMembers4 +{ + public class A + { + public void M(T t) + { + } + } + public class A1 : A + { + public new void M(K t) + { + } + public void M(int t) + { + } + } + public class B + { + public void M() + { + } + public void M1() + { + } + public void M2(T t) + { + } + } + public class B1 : B + { + public void M() + { + } + public new void M1() + { + } + public new void M2(R r) + { + } + } + public class C + { + public void M(T t) + { + } + } + public class C1 : C + { + public void M(TT t) + { + } + } +} +//$$ HideMembers5 +namespace HideMembers5 +{ + public class A + { + public void M(int t) + { + } + } + public class A1 : A + { + public void M(ref int t) + { + } + } + public class B + { + public void M(ref int l) + { + } + } + public class B1 : B + { + public void M(out int l) + { + l = 2; + } + public void M(ref long l) + { + } + } +} +//$$ HideMemberSkipNotVisible +namespace HideMemberSkipNotVisible +{ + public class A + { + protected int F; + protected string P + { + get + { + return null; + } + } + } + public class B : A + { + private new string F; + private new int P + { + set + { + } + } + } +} +//$$ HideNestedClass +namespace HideNestedClass +{ + public class A + { + public class N1 + { + } + protected class N2 + { + } + private class N3 + { + } + internal class N4 + { + } + protected internal class N5 + { + } + } + public class B : A + { + public new int N1; + public new int N2; + public int N3; + public new int N4; + public new int N5; + } +} +//$$ HidePropertyReservedMethod +namespace HidePropertyReservedMethod +{ + public class A + { + public int P + { + get + { + return 1; + } + } + } + public class B : A + { + public int get_P() + { + return 2; + } + public void set_P(int value) + { + } + } +} +//$$ HideIndexerDiffAccessor +namespace HideIndexerDiffAccessor +{ + public class A + { + public int this[int i] + { + get + { + return 2; + } + } + } + public class B : A + { + public new int this[int j] + { + set + { + } + } + } +} +//$$ HideIndexerGeneric +namespace HideIndexerGeneric +{ + public class A + { + public virtual int this[T r] + { + get + { + return 0; + } + set + { + } + } + } + public class B : A + { + private new int this[int k] + { + get + { + return 0; + } + set + { + } + } + } + public class C : A + { + public override int this[T s] + { + set + { + } + } + } + public class D : C + { + public new virtual int this[T s] + { + set + { + } + } + } +} +//$$ HideMethod +namespace HideMethod +{ + public class A + { + public virtual void F() + { + } + } + public class B : A + { + private new void F() + { + base.F(); + } + } + public class C : B + { + public override void F() + { + base.F(); + } + } +} +//$$ HideMethodGeneric +namespace HideMethodGeneric +{ + public class A + { + public virtual void F(T s) + { + } + public new static bool Equals(object o1, object o2) + { + return true; + } + } + public class B : A + { + private new void F(string k) + { + } + public void F(int i) + { + } + } + public class C : A + { + public override void F(T r) + { + } + public void G(T t) + { + } + } + public class D : C + { + public new virtual void F(T1 k) + { + } + public virtual void F(T2 k) + { + } + public virtual void G(T2 t) + { + } + } +} +//$$ HideMethodGenericSkipPrivate +namespace HideMethodGenericSkipPrivate +{ + public class A + { + public virtual void F(T t) + { + } + } + public class B : A + { + private new void F(T t) + { + } + private void K() + { + } + } + public class C : B + { + public override void F(T tt) + { + } + public void K() + { + } + } + public class D : B + { + public override void F(int t) + { + } + } +} +//$$ HideMethodGeneric2 +namespace HideMethodGeneric2 +{ + public class A + { + public virtual void F(int i) + { + } + public void K() + { + } + } + public class B : A + { + protected virtual void F(T t) + { + } + public void K() + { + } + } + public class C : B + { + protected override void F(int k) + { + } + public new void K() + { + } + } + public class D : B + { + public override void F(int k) + { + } + public void L() + { + } + } + public class E + { + public void M(T t, T2 t2) + { + } + } + public class F : E + { + public void M(T t1, T t2) + { + } + } +} +//$$ HideMethodDiffSignatures +namespace HideMethodDiffSignatures +{ + public class C1 + { + public virtual void M(T arg) + { + } + } + public class C2 : C1 + { + public new virtual void M(T2 arg) + { + } + } + public class C3 : C2 + { + public new virtual void M(bool arg) + { + } + } +} +//$$ HideMethodStatic +namespace HideMethodStatic +{ + public class A + { + public int N + { + get + { + return 0; + } + } + } + public class B + { + public int N() + { + return 0; + } + } +} +//$$ HideEvent +namespace HideEvent +{ + public class A + { + public virtual event EventHandler E; + public event EventHandler F; + } + public class B : A + { + public new virtual event EventHandler E; + public new event EventHandler F; + } + public class C : B + { + public override event EventHandler E; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs new file mode 100644 index 0000000000..3bb80ed84b --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.Types +{ + [TestFixture] + public class TypeTests : DecompilerTestBase + { + [Test] + public void TypeMemberDeclarations() + { + ValidateFileRoundtrip(@"Types\S_TypeMemberDeclarations.cs"); + } + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs new file mode 100644 index 0000000000..80f5b0371e --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs @@ -0,0 +1,41 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public class UndocumentedExpressions +{ + public static int GetArgCount(__arglist) + { + ArgIterator argIterator = new ArgIterator(__arglist); + return argIterator.GetRemainingCount(); + } + + public static void MakeTypedRef(object o) + { + TypedReference tr = __makeref(o); + UndocumentedExpressions.AcceptTypedRef(tr); + } + + private static void AcceptTypedRef(TypedReference tr) + { + Console.WriteLine("Value is: " + __refvalue(tr, object).ToString()); + Console.WriteLine("Type is: " + __reftype(tr).Name); + __refvalue(tr, object) = 1; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/UnsafeCode.cs new file mode 100644 index 0000000000..198f0fc978 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/UnsafeCode.cs @@ -0,0 +1,114 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public class UnsafeCode +{ + public unsafe int* NullPointer + { + get + { + return null; + } + } + + public unsafe long ConvertDoubleToLong(double d) + { + return *(long*)(&d); + } + + public unsafe void PassRefParameterAsPointer(ref int p) + { + fixed (int* ptr = &p) + { + this.PassPointerAsRefParameter(ptr); + } + } + + public unsafe void PassPointerAsRefParameter(int* p) + { + this.PassRefParameterAsPointer(ref *p); + } + + public unsafe void AddressInMultiDimensionalArray(double[,] matrix) + { + fixed (double* ptr = &matrix[1, 2]) { + this.PointerReferenceExpression(ptr); + } + } + + public unsafe void FixedStringAccess(string text) + { + fixed (char* ptr = text) + { + char* ptr2 = ptr; + while (*ptr2 != 0) + { + *ptr2 = 'A'; + ptr2++; + } + } + } + + public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val) + { + fixed (long* ptr = array) + { + ((double*)ptr)[index] = val; + } + } + + public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val) + { + fixed (long* ptr = &array[index]) + { + *(double*)ptr = val; + } + } + + public unsafe string PointerReferenceExpression(double* d) + { + return d->ToString(); + } + + public unsafe void FixMultipleStrings(string text) + { + fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) + { + *ptr = 'c'; + *userName = 'd'; + *ptr2 = 'e'; + } + } + + public unsafe string StackAlloc(int count) + { + char* ptr = stackalloc char[count]; + for (int i = 0; i < count; i++) + { + ptr[i] = (char)i; + } + return this.PointerReferenceExpression((double*)ptr); + } + + unsafe ~UnsafeCode() + { + this.PassPointerAsRefParameter(this.NullPointer); + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs new file mode 100644 index 0000000000..1d7ec437d8 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs @@ -0,0 +1,162 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +public static class ValueTypes +{ + public struct S + { + public int Field; + + public S(int field) + { + this.Field = field; + } + + public void SetField() + { + this.Field = 5; + } + + public void MethodCalls() + { + this.SetField(); + ValueTypes.S.Test(this); + ValueTypes.S.Test(ref this); + } + + private static void Test(ValueTypes.S byVal) + { + } + + private static void Test(ref ValueTypes.S byRef) + { + } + } + + private static readonly ValueTypes.S ReadOnlyS = default(ValueTypes.S); + private static ValueTypes.S MutableS = default(ValueTypes.S); + + public static void CallMethodViaField() + { + ValueTypes.ReadOnlyS.SetField(); + ValueTypes.MutableS.SetField(); + ValueTypes.S mutableS = ValueTypes.MutableS; + mutableS.SetField(); + } + + public static ValueTypes.S InitObj1() + { + ValueTypes.S result = default(ValueTypes.S); + ValueTypes.MakeArray(); + return result; + } + + public static ValueTypes.S InitObj2() + { + return default(ValueTypes.S); + } + + public static void InitObj3(out ValueTypes.S p) + { + p = default(ValueTypes.S); + } + + public static ValueTypes.S CallValueTypeCtor1() + { + return new ValueTypes.S(10); + } + + public static ValueTypes.S CallValueTypeCtor2() + { + ValueTypes.S result = new ValueTypes.S(10); + return result; + } + + public static ValueTypes.S Copy1(ValueTypes.S p) + { + return p; + } + + public static ValueTypes.S Copy2(ref ValueTypes.S p) + { + return p; + } + + public static void Copy3(ValueTypes.S p, out ValueTypes.S o) + { + o = p; + } + + public static void Copy4(ref ValueTypes.S p, out ValueTypes.S o) + { + o = p; + } + + public static void Copy4b(ref ValueTypes.S p, out ValueTypes.S o) + { + // test passing through by-ref arguments + ValueTypes.Copy4(ref p, out o); + } + + public static void Issue56(int i, out string str) + { + str = "qq"; + str += i.ToString(); + } + + public static void CopyAroundAndModifyField(ValueTypes.S s) + { + ValueTypes.S s2 = s; + s2.Field += 10; + s = s2; + } + + private static int[] MakeArray() + { + return null; + } + + public static void IncrementArrayLocation() + { + ValueTypes.MakeArray()[Environment.TickCount]++; + } + + public static bool Is(object obj) + { + return obj is ValueTypes.S; + } + + public static bool IsNullable(object obj) + { + return obj is ValueTypes.S?; + } + + public static ValueTypes.S? As(object obj) + { + return obj as ValueTypes.S?; + } + + public static ValueTypes.S OnlyChangeTheCopy(ValueTypes.S p) + { + ValueTypes.S s = p; + s.SetField(); + return p; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/YieldReturn.cs b/src/Libraries/ICSharpCode.Decompiler/Tests/YieldReturn.cs new file mode 100644 index 0000000000..7546b194f6 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/YieldReturn.cs @@ -0,0 +1,148 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; + +public static class YieldReturn +{ + public static IEnumerable SimpleYieldReturn() + { + yield return "A"; + yield return "B"; + yield return "C"; + } + + public static IEnumerable YieldReturnInLoop() + { + for (int i = 0; i < 100; i++) { + yield return i; + } + } + + public static IEnumerable YieldReturnWithTryFinally() + { + yield return 0; + try { + yield return 1; + } finally { + Console.WriteLine("Finally!"); + } + yield return 2; + } + + public static IEnumerable YieldReturnInLock1(object o) + { + lock (o) { + yield return 1; + } + } + + public static IEnumerable YieldReturnInLock2(object o) + { + lock (o) { + yield return 1; + o = null; + yield return 2; + } + } + + public static IEnumerable YieldReturnWithNestedTryFinally(bool breakInMiddle) + { + Console.WriteLine("Start of method - 1"); + yield return "Start of method"; + Console.WriteLine("Start of method - 2"); + try { + Console.WriteLine("Within outer try - 1"); + yield return "Within outer try"; + Console.WriteLine("Within outer try - 2"); + try { + Console.WriteLine("Within inner try - 1"); + yield return "Within inner try"; + Console.WriteLine("Within inner try - 2"); + if (breakInMiddle) + yield break; + Console.WriteLine("End of inner try - 1"); + yield return "End of inner try"; + Console.WriteLine("End of inner try - 2"); + } finally { + Console.WriteLine("Inner Finally"); + } + Console.WriteLine("End of outer try - 1"); + yield return "End of outer try"; + Console.WriteLine("End of outer try - 2"); + } finally { + Console.WriteLine("Outer Finally"); + } + Console.WriteLine("End of method - 1"); + yield return "End of method"; + Console.WriteLine("End of method - 2"); + } + + public static IEnumerable YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable input) + { + // outer try-finally block + foreach (string line in input) { + // nested try-finally block + try { + yield return line; + } finally { + Console.WriteLine("Processed " + line); + } + } + yield return "A"; + yield return "B"; + yield return "C"; + yield return "D"; + yield return "E"; + yield return "F"; + // outer try-finally block + foreach (string line in input) + yield return line.ToUpper(); + } + + public static IEnumerable> YieldReturnWithAnonymousMethods1(IEnumerable input) + { + foreach (string line in input) { + yield return () => line; + } + } + + public static IEnumerable> YieldReturnWithAnonymousMethods2(IEnumerable input) + { + foreach (string line in input) { + string copy = line; + yield return () => copy; + } + } + + public static IEnumerable GetEvenNumbers(int n) + { + for (int i = 0; i < n; i++) { + if (i % 2 == 0) + yield return i; + } + } + + public static IEnumerable YieldChars() + { + yield return 'a'; + yield return 'b'; + yield return 'c'; + } +} diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/nunit.framework.dll b/src/Libraries/ICSharpCode.Decompiler/Tests/nunit.framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..875e0984208d52e5c96a409b52996547198af17a GIT binary patch literal 135168 zcmeFad7KB+1;lZ0dvvd~P=gd}W3fDpnK_5dLyY_dZT>Cl}BGR_zv zAYedNWd{SujtBwSL<9syR1jnl42Y(;GZ_dUnB#uyKOAAV@e-T39dS(2_fSq5@r*S(EqRo&0V-<{ayXXED`wWu;~ zak+G4`QR^%JM`dVk1Z`3cgW%6%1e(Ox9He$+wQ*CxG$6rJA6tmmz`);&)v?LT@tPt z^=5ikKetzmGrm5NG3J$oG2;~5_@RI805MDPO=>qeXutfM1v>DPzu=%;vrZKNaP?QN zlo#pUA0*6P0y!p=4A9k!agJ%ILTi6D&KQ&+_?H1ZCxDEZvgGg+mH=*h*_MlC6+5d; z5IJZ{xl%q9D78(?X5IpC=-(_jWJ>w)V@hBYTVb>6!f)sw_-2Q|&n`dnz-J!#%mbf! z;4=?==7G;V@RC0Q^zFD)V~;WdTYYe3AUQd9cRq4 zDmd)b@2_-jIb`qe{PXN<4|wRyzx&rFE8lzV)n9-4k(ICg?S+Ha8@&I$;!c~MwDbB) zdJntwoe|64IC#^+Kh}NePX}g-&%ZL`(y8Bn|9}k=-`hNK(NmB7@{*_iG=1!t2``W8 zd3kYa-_72gKVg^aE*rJm%t@K*4OKCeHeHc-0i7M9w5F{p?Bgxq`Mj=R|?W435g-D5Sg;CK5Vb9Vr|G%YSmw8(b* zyr%n${-xs%U|GRK>GI4T)dUq`rHTo3Vr_@^P)2kf4acYkMOM|&N0Bm6lgLb_453M4wEoF;q zK=8ygC?@6`BI9)wt_6giRBha+#8-VvsJ5Jl$q)~rS{{UKh=))&qGgORDa3g96vr)$ zwb#R-&vq&u3?PKL7dWw>kn5E?L4lf;Yv5V28QRiXG0q4v&L2Xf>296sN!!HoTk{YM zp;nqrMH**)y0GK424`6 zM$UFz@j{{3iu!Gxhu2xP>;QFKNiMeUL!E*P3ij z_9pvglf5LpB>S6ki4GWztDg2u31!TdZ}2e?DkeHaZiKI{ZDk*O+>}*;_++1Ib^ig` zW|nRNue5#O`slFekHC=6rJmdpER5&ul&;j1TLnN%>d9F?AT}2hc~RYvS<2{y)?D%M z)RQn*#j6GD$}DAA_O@o0Zpz>KKmtX`6{n`2T+bJpf^4?-fk-x46=pVdzWHs|kC{}V z3kDa)Az5kC9SiEyN;!Mc2Of=_apngfeyFHcuV|XR?h~E7RA-@21I8VI$2})MfSwJ( za(j%NRI)oTl3d;ZYSVK%KZ+UgPG&T4&*`wthzrl$0$-zxM_d$s>6sK-5wmUen!W81 zx0o7`W=s$MFswQKw5{|jaMl+$0VsO=MXi#a6Vhmq#J+wpPf5=T$vElKcz8$3EFqe2 zD7LCcGU-fdU3xClv7jNNeCoE|)#%z#xv5;y)OBy-xL!vA5h1;vl!Nma^j*zSZ+Y&* zUv+*Ho7x(Vn`ZN=h0O9%o??B zhv-qQN2}W3%6!B#2SYE0!WyS8)0>zlOwpy^L-bsftYe0nCB4kj6 zhPo9D>y>rM1-VQb9z*r@zQQSn_+}w~F>J>3gQrj2HpmOmvbD%(`=Row=@G+2BHDxW zd678=kcFK34Cvk&*7>J)n5Pt7E+;6p?N3gP=ALr|q`3s?77Dir2f*BKmU_R(- z*M})zlkKkS(*uZ6ub9RJh!+|U)xI6m00djKZ?EzpOWR*tzM8(h%3JN*E$@(hyU(va z6dEjk8GoPV#xB4hV&8@YIIM5gtMz9-Ak+<4{=$)$$Y~JcL3#3C#mk%N;<^%AQ#X)q1k|5gn;x zSIa{w!B2783QKKA*gDlU^AUTPUIwx4xIM00Oz99aFa=`yY;ip|b;;5j5x_l7xVn~C z7|8G+qafy1o||f0nL@XTUYrsfyMTUthVOdHfIqAQ{zmISmH0Mc%1j+KHcj)D&Su3D z!Z=AT$vw!(ErhrZiPQttl^EBjh_E5wQAtHb!} zxj8PoX=l>hgP=-ktYW6hXhT)kr)OLu(H6QjDxu@d4v@#`XIf4t>?%fYyT#;ujI{7P z+F}=444E;9;E&u$b=sAUkSeSP1q&jO;(|zAsw*23LlBZK&XWQW>h3nKQ)+b(B2qTT zpbg4;3|d+#l`yH&1&ABlA#i-|sM3!^zc6|QlPc3p=<8>llt!yk%Angdn9-qam*67K zW9iJETzP$zAyvT0fesmyR+H8>p?>gVrpvy7^;w?|rn|rzgaD?y<((nx6wZY{QIIX} zRNf~*!5OUO!lfi*)X8Rx#q#HeB!iW;tgILlz=|azspsvG6Xw*Ie`^&tWO_5@uR=?G zaRXOxQqtvf0T+|yi}90{`-_y`RpS1`U0GLvTeDg+#*S-7LnnNQvSr=+RA~haOiNn1 z50?!^lVRR#;`>2}&yl_yQ+(=6^<-3GF@b_8y^#oFt@%XWd{4rsa=qX$YR&f~X`D5w-!EpLrvo7p}pIHC2vnQv& zr4bM*CLFi&1TKP@^d!F4#P3yp76{Nz&K2=DoPNYc9BPq@VUZOmpzm%j@=ijx2?{{?UbbBgSV z+7?}dUYGR?J6-AL+@(80S*Y6b<^P3{tMVnsm&eqAS#^}q_h-*ugrP_(?^xrOvA(&u z)XAoab}IIathQ53{G(-H+{4xe^aTvm0o?SXJCyhg%Ig(w^2<9jR$jvK@)9>(dCx@t zSW+0KytwxpzPwbc2`ldLqTl!7O zJLorEiBlO5%SqQSfXdlE4ILGxt7rNCpT!b*16$*VAq3kUvnzg4uT`J+Hah)e)V6OY zl^xmQ`fg8*!oi3$(h(})mN13T-chV&HYH5pvZi~s(Gjdk=UiJqK$Eq@D`I%a!2-K7XSLGrhNSr}*XD1)@e8K|FapxGLQ zNfJHNeKZy%3SakqG+TYNjreFfN%vZtX@_S}2N63kJW#}ynCNvoikQbz*hh5oR$^N! z?PrRJ6I)gy0#r^a*e&l&!#dd3e0d?DZ*dItnQ>A_q9dE?ShyYPo&60e4x`;zU)e>p zl@m}kLBTBg9KAB#krGii;{aVyQ2)Lr4(kksYFT_Y)|kH6Fs5S_TSHG5x3$~TzRNKP z3^QKxT{;RDNT-GIvmqr5OmI_uvDqnM5}z$$uE!Nf9bh>2VgA4|Ah6k8+Tg1IAG9=; z7s94;s2Qh9kD@@L0#6S%g`Wq|S7K)PkgZ)jgQ{ZP!owCVZ3J@@jv>gepF$m_&7_{B zBI!ennPIwH_&<(aTUMDsACeD_FRl$ADtfK>-e1dn-J$fkyhpOJAmzkEg{@HrDJJZ9 zW$uT&W8V*M!$c6zt_JVYT~LC&cPF)wjO)rYIeSi!AIt$>ubCMm2jW4Tq@%Q|d(6U~%8WqO6{CUe5+ zdd>3Q6DjXwEbobEgFnWFjQcw=^2#rQt8kv+pp^bt0DnxTKddJjid`8gGnOlzeoFZT z$Ef9X)UPgP#C|}}tsa$8<8eodA_J8{>1=`X2z-<7PBhW(I@7y}L7Ov%1OA(|)gSPg zMM($zh`~FH!6Utp!HnlGKnEu0j0bW^L+)vG`0c?I_|N!7U85hB=1ZeDfF*&^6dKBC1OU9ebI54g+zFetzjOM@ zA=znW63JA5Kv+GQta{uF{}sjz>`KkH=Wxo$g>uk#-iSPKQvttp49q2O&_)eEhgNUU znAkuYOeW_)e9AOude@OYw|o*@(vskse^zEdl^M7?(dlOfY>#A}W1mqewuJE=Ex*~z zw3RUJ%;xHJ{voVZ>rF#yHM~m^wp|g2teR9^>1}wnHR<%z`#ss_Wc~w=yog3&mSM3|_MaH@Q2z@L)GjnZsKqr3;g9y-U7{(fK&2nI_t?!cY^Q7{ex^~E-g zFPKZNl=jzJ70CP5)g4+15+*>T1OKzY+Rv?P*4m(bQkkyK`|Zm#Zh)Gmi&_G2Ojty(7p^h z=@-;Utl!TE{eIyMC}(${4|n&ktg*XCw(Rb$AL`7+UhVJw`_w5cN97+-?2qmGzKr0V z$~!)RG1>szEPl4{vKSsyM0F)*)N;d%g}uK+hm3W5u~tzhzK?Ak5Dg!1>x<6Bqi@7* zfq5fG?v4pmY)4nJJyAzLew%3jli(XIPnd0Ih?bSb9Z9}?2I9|^$kWbedk{{nvU}Rs z2JAP0-HWq3{mj+9mYH~xmT2f{EIN|%%CH5DovQh5A2V!I8LRV*9YKQ+mOx&FpRJtLwD*e zMO`>}^r-+Cxt!qNsnG}Qw}c5nGVl^sn?ZC-SKzmR;fkEJ#4TYt znUn$Q(6;E9&3)ZA`(f1e(|&C232DHh@;USx*NPl-B=k(xGBLAK3pm9DbpHXuEnQx< zr^=F&=O~E0f;F|&1~xo#uPH-X%V6_FXQqBBcGyfP=ZLMPt3o+7*$GYaL=57gT=;B`KGA%93Nu1YK=Nrz9tn(u zI<{c#3^fCvgODF6wj6DKIh=k{OS^!N^~nWD_V*n3Fr+eGgpPR7o?@oOxFrnWejirL zkFiPl%T5LTN_OC&kPV23g8}-n8M1|3C5(ABwydMJ2pt2h)eT#SaZ4B%a3AROQ>`B& z5+kFHF&l&b zqwTfGu^!cy3Kp1Cg)vC1sUMeq!$-*9^bz!1YU#Q*pgwRbx07Kkl8`THztYRQrqOAx zS0xAbTl#(=KmzROPyF0da6dUp9%di z$9ejc=bnHEisL++DbI^6E6rVkjyldWLwTMJ^vtZ~!8k#CzRn4r=)sLiT+bHDb3wp! zYM95BiTswr<5pe@3_2=cqK`Y^Lu8M<+{)>JqEl*kF!vXpM4$(qv^B`rGt2Tg0S|iM zPr$Ra)#C%dX<*CMaWe8^92bi6UzQ+T7 z=hx^{o{+vFnEzY)Fhv*peiqnwL5+RN6S8jzX5T*CD2To%1AQ0P=u@7Mz9E=>eYj%~ zeZLMG2cjxgub9dU&u;=AL`=Y={X#)_Dz5}A2pG#EeGB6rcL1X2xqt~#9_Z1wu{Jzt z38LrWAQlg+(Sw#CJeLQ4I^z@Zpe2Z&s{%b|*63Lq9<&zGb9JESYc+b-h6fWN(ev#< z&x#s7Yr}&%ljxZr==oxe9?YeLXJNo|d<_rgPr|c*z;i-~$CI^8%%RBRRlXE3E%TZD z`+b==6t3nLVY_!hpI0mX!eQ{&41@pXF!+li_y)wJjHhnlVxQpKBlyB4J{mEs_9*_+ zVepp?gTFk259ND>Pw>Z1(eG5-ZsAA-c`!#&8)OWYAvo$Q43Ahd;jkOUZz}k^YVb0? zRye#y`DIM4a7c~fWgM+=7>(j(?3AH1ikI=S!r{`#>spPBkvc>Qfn}#pWL(r?F@l$| z(5-MNjNoUnTyBNK-&)~ioO3H2<|6zuwz(A!ZEJ;>@yV4@Dd2C1{erJnU6lbezl<^# zxfPB;5m~{9WCMmzNmj-fx5AMnlCR)H`34N3d}TawD;z~4vVsrE1`Hut8DHEAhnGN> zbuD9xTj7vm@fzDQj#OUp(ShG&TyQHKIwE?8!^;@qRyagN_+?yhD;yR+5}${i!e1E& zHHCGNxTQUPjnz8cMdOe|L`3IMcdn{MBwn;gT2!uL> z*XdHpA!Ls5{f6AHWA1*xVs$S12>LN`I`-aJgKgfU#As$MeoqJX`n95k_I>84FLBqU z{^tIZ@sLqp+@`*82S^{vCCI~Loas83Q@9KQJ+1n?^kBHre@4r7tTrsVP*DY&CTuMf zJ1tJ@r-GeRe*Mt?A#FM8)3Sw%D%Yb&(ufdSh_klb98kJZ!`2mk4IgIR%y~G*jkPNO z2)C_rLr}nCi)%Bg;<#4naj%rFLn%G0KlQGYPL=M1gKYqV*Oh0ttSjuUrtg<7fX}h0 zUEu0!u}*)xve;KHu{J#am6o5sKEK~WXcOjfHYV-|2ir&I5bZ^iW6C$Nmd>eKw4oRuEAnRVI25-8!w2(&o>~`tMNmb zY;h~D$W!M+JPF{huST|>hjiIJRE$!vHMmi#$5q= zP6KRv9kLa&Fav3nx_c`SXACRDjMHx3O@3G4!`q4ZNy!Q z74q=Dh~^}hrF|KMnY$_pLxEvpHY^|<{H_}k(*s` zVhrH^*PzYQC)8b<33BOSBydT6d3>G!WK79!UQo7TN zeNfW;%(p>jSv`%(&}>U{8;NmVCR<5K3x8(``p|m>TQ`%@t((ZIlQNiJCX$jidIh{u zf-UBUc}o!i31-7z|4xF15)mSkOPE6B9TAxpDjw!-;LN)o_UKj1+|J?_>wqn_@lxj^ zDTB#A_r^9GFNv4lgrCkROhl5^7vLa)j@rIx*W2q3EcHY6|zCM z(VObFb5n$rD{S0mG!F5QM3w%7Rf=%L%Xc%*g(@@;I0J-#3c(Xq8#Jbpa^dg3MBm>9 z##G^5a3%Gp(d$?+smas!RNO%&Lt>B_g=X?22K)vbjNN2vWN8eYY>J(ryj-Pt0VRl? z8(~{s>Yy+dGFflw7!(8Xin-r9sq()dtXWDG%bQ2CYb=`-{`zE?KP~)fT#Uaym6kJB zbV9d|+vp9RfO-ku^-Ha+E49$*;#ktY6x12s0|c!j?bB`jyaBs0_dv{x0a>-9KE+o| zQmNAZ@I*sefV2R)OdU3(da0ficf9+1SvSGiF2(V9S-Ero1k(1`?pk&8*l?S~>&!UX zB(nkb-eO`U+gX3%p(4k_SZtiV2Yz_$|nU!`!SIKwbJ zL^w@>{-B^SfsW>MOtzbQ;IBcs5$~8cXt`58jau3cnX#i_xZ!I`rCiCQbRhjutT;|)Ae z>v6@#UA}-8js-tt! z2IQ^uO2Q{`z81n`dam1Uh;I(~3mzI&jlK{)8KGmoISGomQ_~ns2Ly`9W8vVZcBp==w}($KH2?9b47LO<~+&)a&l8O(`2 zvl6~UJ8Q;^G9R?#hSO+AAhb-flb?l!Ls2|W4;;YmblIHFH6Qkk zXh3Q&?ry|h`GvhFTYKf#^e?BqTZz5)GB+OL{70LK3)@UsZ01FkF`zVI z@FyWZ3k!!0Ww#@H=s)M%Eq?a>tL3)0>oQM8Z*LCrc_U@hyyCnE`@Fv1Woj3zFV2go z3Hc5-i1DVME)!mC=wcgz3EeXtJzNTFtO8HRX#@x&={5cM{|gvVRn@)^9S^%-zU9=R zFSN_vWf`SflYRGtzk)^4EZ&kqJIyxabHyB9tH4rLwxOyf(@eu1`6$wah3(yA4+!}pzOtl zbUBs7I6afxb?9MpP%BJ-5cAWz&6*1i7?(_QQr{ImB4G@w8s$cTsec9@1lgkTurnM3 zfZ$A*uw;>K$Z)vo+JEX!&B^T=fuD`PpA7T27x1W1b20t~@OK^l5Ci6G_@k03#l8pR za@?u-+58Hs)%KR=nN3Wa;iMG3LTazPpm@o zQ|0a|G$&P_T7_n$%9~W7o>X~@Dl|4#o()J3y(%F>vy+Qi9MmQ?S;U@yIkQZs!gA2a zj342|GJOjJlRYQL1Guz5L;Ep@)8`UE*;Eh@^~GM3)@Z;$SeNo+A?2jM&KaP*)uT0R z^W(83VEswTj|0t6Uyx=$vnTR8A{^H|h+uzMkI}q7eHOJgq;r_e;msY+Q(C=Do!jgk za0Qb6nsBaZIFf#y$-7q|2sC`q#yxW>^rKzj8CO=DgN*oi1WFU zwW~h`tSDhGD>`V{;1p+iA&W7sT-cCFO5Y7?Lq3`A+;5>sG&s&&FH=|-gYO=$8(iA@ zWw@hjKwg@aq=n;{Q?l1}ia5z(GJtvjIAX{Zpux)(#~Zv$!-kg8A2dj`x87tO`iWlD z#DZKM53wQcS7FsYUkZH5b|mO5x~G)qAzYWS0{BR864b&x)LBCI>Y-V~zCr;d;A4^X z@yk0^yGO+_2n>BUz0KkIDZSm86wV0dc|dqz9_h$S-@%d^aY??VQ(de0c~s8~_M1?( zRajNJBio0^O+e3zquJJ-rK7`WW-{RTCl;cQw#F=SmhKbh+uK>XT^zTy!-qlDMMCQ9 zb(U@!$Dwcwhi79!hACvGP^Nf-I+Frbrv?I;T0?*-1U3+X9kfO$P_3Cj z05fn1FoghS!^i>oo*-DJz)lma1QY!|3w~RqaXS?ZJ@u}fJ%A8E=<<0&M|~f*J|nEZ z1adDPx00aakuE;j9Y|BW=WYq(~NbQAbj+>PWUR2>f{V5Kd$e7Sh8x5t%S1U%)S>09Y%K z#)*J%f$;-k9N zmy?4~P|`Ng_QGG^HAraXSE0Mr>$?`9&5a!iih8sjT+6BJNL1rSN!M9e#3q!5^*BLP z&b0N4<*J6_5e`Ixd3ZyJg4!&gmGPMpW{Fu0)L%Tt`QkBJ$XwmJ|GREq1N0!iU*l5zIOQe1Q+2W*t!O?O!Zb}yiR&(VAlEY1tc#p;%tQ^MvD zI>xcZ_@s69EX=|L)h|a)UG2$|tVBYCFdt`KU0p2-yJQq)Evo9cs)FL-EI0$0l`A!+ zn%V9OE1(iTXW{2Rt|^Vj@4;To`}{J->S_*4h^Utmo{d}^q~>f?uwk=+(W*KWSihO+|iY|`xu=O|qWpG*)eszSbFL$!b#_RxZ@9R7boiFEW z(noWqFiIyE4J~jjn=?<+$!7chfN~E%AAk`1og8-A$VK5C5&EtOEf{7(fN2a{FqTC; zofPnJH!Nfg4nHM;2-^e}Ns>A(;CUMm*?IU$0Yn&kt*I6)G4iT#zK8(NDr-%*q+Pix zTp)N%3_^GLj0@dsc^rLO*#xfg=d($(HGB;p1?R;{Kb!MkPBa~;oE*vEF6|6vaYAl!mk{HXE`+7Iz8}H6UYw`Z6CPK1 z4$t*n1txu;8V^>QAy=O&&qoY&$RU$##rgC~EQEdoBsq3mavGa)b)lOLFYm2vPI0e6 z_S(&meXh8BI<5i>#&H#08M{_4D%^;Q!*j*@^3g#g*2V87>R~hnQTUsWynTO%&ZBYq z(GEj<772B0T{S=!K1TfaW5fvY5DM|&c9lHn=R-V%LOh6R@}PeX@em5}AcV0BarC!*4bFVyfO%fUpuIto+^ba_+D=s!Sf&~9?y9SMsUUtwy(wOQTQY`0BWYo_MAu&au!!W**un`p?ENK z3Da~I&?`>#pD{VG@d{?5KZUJXVImWL*7VexpEY%apEd1kHatt8HL>5o%-eiP%fhTt z82;45q;Up&s5SnB#G1Mq;F#^&saJRUsBXO=i|2eZ8-pLA|j*X(WBR$FwI&(8OUFdu>` z!*hGCz=AZ(Z~$zOH5Iq?EoA6Py5ah6X{A6+3z(~Bv4Nq4+YK-<6;v=Ul2w|KZVC4v zS=qtw$z=(%20KDwcOc>so8ArXZc$!Or>=Oc+MB^SMSW+0;+DP*c|JMC$r{gN1Pq<5 z;nmQvb=&U9bW7J&I*cB6vio53^TzJJ3bgP2QuXKjV{oULBgyWFIm zZIHd%*_>Otf%$r#{wDDN;zl6yN9Rj7;dgRf6wDtDuUAYal^2brn}sJGhVrfH;wC25 zoIV$4xt)utJ$*6Oj-Yt{+?+mof$VQ6X)Ly8R_}#FoA8_h{Gt`Bm6W*;&%FdbTF&ow zwTwcWaUu?OGOODS)|*SWzy^co;(CFHy{L;KDhPL>`n>m9bL;X%I~-!BjN=xHW%Nt; zZcgD&H17fS%=W2I_i4`Htt^sK?9m;1HFBywfT0TZ| z;beVskLKIzoqbSz!eCq;KU&| zCwt-$zu)C6gf7-mAAY5MR@-4y`FhBQc0Lc0-Cp7B{=631F)xgaI_|1MEZVaesP9l2 zaFCJ@G7rB3St@j7LzW7AHBd%)30=&caCWd)V|Tx7w(oJ5f@w6SkLYYBmZv~n^~5dt zSf503sNhaN_318*(p|XJ=yg$+InXWt-16eET@)yNk4X!X^4X-_jjLX4uZ+^rO`S*T z2B7L;Dj0rjUF-SYQrCXJY4^NyZ1$TGopM)@xxXv^o795Cn0@#nfe%F0tA3~a0A&1A zJ-MF={kmDkxC;ElI~Di|3&So5tTxh&PPx+A7aQ z7i9NbEkfO(AFjrl4*zg)y*9ji&>V2Et9;yK;5-OA{Y(Qk9^{UJB^#nS{mfw8MhKtM zy&(Cg%gg?jBhW}%V5Blh3lCl-!ER>i4u9t%5BqeEF}W&)8%%BbJ2|1F;?IYu?Q1*( zz?@uLE{qG|a%r)A`#?bXTyhoRBsxnc?#^w{~+0NdA^(yksxI)IJ= zuG&&kUdt?A2S4_`^I@Nk9o8G7trrE;fkH)*C-yvl!lU0MS9|okj4kT~zC0%=faX&@ z`~4gCtUp8z=ANNL&Mzdw8~6r(=wz1R^UxQWOZJngr`hQzS5KWi#}9W>=-_Kk`E&Xu z50TNM{PI&r`A90TNV^eOpUxl6E>?^edn6-$-$rcGcjETcde^gZB@=(n8l`*KoH(!s zdNNAKn(a95RL1DffqT5YrY|DrJn<_RHRn8W?uDf*uGjsbmab>0p?*M@Bf#WrF|itl zj88&Ta5U8qCSd$P4KPoP3g#5mx!fQBxt7elq|G?}WDXxu23vKF)8<9GWE1Hhuxg|I z!w~N-_LC@w!)p`dp!X7LB$(fj?w_d0`&B)odb!q#ym)5g0?jSOcS^G-R_(b+dPX7GHV*XulmctWHff`G(cT?x|%YPTk$44o9=%OI~l#Bpu361h}(& z7-JKf#?DG61En7@8;KiTf7gDdt;K$eV>hSrAUFnSl%3M(8RRAScdg2!ok`_~)N(1c z^fN^PA7ako0t&wLFwoTkHb?=h#WV>vV3c#~gG}lO={|6Mgh|b{Wu6JkKUtX%^2_YM z5f%xD%V4znN$)LBmAdR0xSU1OrX_7)idYvKOZ;V0do$VU%Kevqu4^>PDzdDt=xOhq zJ>u;-e->F@4(t5+5&NATa?<{d>Mp8Q^;XWc)sd9w(bkjppcEU zGx$2v&xJGKP4do8KV5;*ffHHHK^Ci=e!5OBOOK$u_I23eDCM!_Fvac}ae{Yg;T)$m z)Vf5WyyFvOiV-6Ec2C^?eLuqftpZiBf9x>!-!1jk7O`A$)@HBz-n?6$9JkpmjetkH z3JdeH`^Uw}l;7vZ%kXiG=Kbx)@O${4!9JDf3j0u9-|O=6 zMBzuU52K}RQc~`Xd>wB2i=V`v>OGA1`={v`gC%C|_t`&x6?xzf_pwXS*Wsg2!Bl5l z`5VYoyD_~Z(S! zzqge84uda0)o*7SGH{{44Uiwb`z^Wo5wXd-rU82l*3X(NdnNgvs5?Lgll~wz4{+sW z4vSdZ#Z)Nx4wl3B#cjQa32Gif5ND`=5cs%=FGOt#UG^1d3=>ix?0d9MLq${B&NjdM zEv~P!&#vW`AlXdM83}QtO7yY7?4craTL3vpo6%b)$=KtTXia z!_-+*c~3}0>*z{4C00j*lRDxRGL*?F?;=VtFzTeyWo(%N;{2_hM zng2?dW{)Itqkn zH;zx41Qnbu4SX94F=M@!Mxh_q_&-y9Or%J29<>c5ZJiR|A+?67D1n~z;Pv<^CI_#> zkKMG`Pu23U4b@vectb#8Olm$OG#@hBd|dhFi-BR%rcwxoXD3|Q}(;kIoU6ah?pFrlPpFrk`PayNNk0|+l1+&XyqRqxIS4Dm# zq3M+0h9Z9!qkYNvzz+K@Hhi8{rl(Fn)ys;h)SP@9izqv<4y(mmMj^G*mvq(W#YdSa z?v{Q5m-r(LXYP4O2Q&9j4xB=$;pht(H|(FZjrg{}gVX*PoxnZ0a&8GrOF>KTgbSRlA= zjS=4CiQmgdqvVyR5lkmeH|56z0CdhZ_VfAt&BMBx7_rS-N%gMd$}V6>(!wnm4fxLG zKN*|FNi{T2*h;TpoDJAC4*G(8f?=~xCiG1P&)2aXSH2A>+49BiIyn3>IKK(^y)V&r z?8k2_{E69iqr4M9@R0eT*8gl^|KFne75tC&zYyquJE~tny#3|2 zwP}@g6YzY1W5%YamlcdFT_wmCeoq~EV?(AsncgvY5x#<#9Jst+I-e5}eX&X-s(X8X zc>y`RC%Fe0WTO}vn}*E?>oGjR{$u2W0lSE=cKA6XAH}RWpERUCIv<>jqaPUlHXuegHG+$Y1oxG&{*jo@NC*-h7*bk<-Fm2$kK=3%Fqb`I;B z`bLAZb4-G5l;h56GB04=VFy?6EY*{K!P0E2h|=2vSvkfMZ_Za0PJ@X5jrg>k}_@*@!J7 zdOht2(&a5W@Tp{-a{r10qMGe;t+3*Eh)9{H68h&8If1*K7PA*Nu_!;&?2ph7YiVfRP#eO0U_^f^5+OP`( zgrBpI2r~5%L4E;ZSP}Ya2HWuU;jE%qUpRsdG9?ysqS3V)s@SlG02^q4m2zBG*lb1k zay~~yh(uBjMzTLmkcn0)X^q6vff-ewZ8Nlo1??+}a(}u?hHx|U4$3zi-M4KRdSE1Od}R^I(erqCGZX~WP&8lf z5VVNS?a&iCvawKZup&C+w6M+?EuwQD(aE${XPg$+8KXsXE)bneYjwtHVVyBrL?`B7 zC_B?yopD-NXN(r;#9A-rX1GOtU8dlh2-p^ez^XL#TO$&M=P-jgCM2Xg1g#?%M ztt)t0o5hd};Vgz?h-4wLrdjZ^Hj5z{!dVQ(5XnM9PqW}$BD27NDGMUm+@Uk|GAsND148;&+QSG%Op&CQ`>Z0gCiL`}V!<}XoW9Vj^#vqjw1B((o7d?#$gP&8lN5VVL+2Cys9U#l}t3+s&0B0Aab zTpbN+?2OaGI%BkmPPPJfg|vklopD-NXN(rn$*^~|=dRHir-gOKXc3(ZLS0m>^=F(G z))}Kkbh7QZE2IV0*cqpVb;f9cPA)t}t*c^u`2Z70#UknUHAJA$d`&~hMRbNDsYYj< z7Stc6o7tL-q#I3Yg~(`jQVVo z73n*)U6cnH)NL->xSz`fqg-h=S>xUnJS2lkXmgGl#TyM%Z2jL?!JNsi4+Eh1@bMqyVjt_JJY(Sz&$!BsAD(4x7m~VIc)X z=r?N;+CD6#fLKPMa7pC*l|f)>AnhQs)gV(CEk>Bd&X~kbF$skkimxEQ81t?%W`$8C zWiDX5V%0?3&CL~=kS7%pG*Z8R-C3UF*M7HfN5#|6e!n{jE0b&2?}j!D)wTr;R1SK{ zeXW76-=Y=4=l7$~ubr#;KaV`KZiPSC@PT?zE?dY0;)PViFp+IDJ}92CBBU=}bKc5m z^FB15cYvrohbA7Y!Xt#c8X*d^zF9OdD?-C*QH)t(h7&ap6;8**Boy}dFq{|iB@I)m z=2ePGD$G9Iyf8ct*%(lAsFD45%9t$l|CfAM)%)rDPIXILr0=4= zwRNEKgdC^{X^T4lTjLz!Bl;Pc@0}#B3uU1Q?uFVG`J69pqx1s%8ElB+Z@rP8M)=I? zCcZF)Ld-V{$coe$|v`6 zJ@juZzFOr^f5b<`V{<&}?9Lkerh>n#2Hz+6dus4_`U5@xjPQhdU%27i7yOYuX03*D*xM*7yu@5c4aR=l^ic)ZI(J0A<%$(Rs)H72SIp!qhV zU#D#FsdM5fEBKIX!0;)_Vy%t&2A?|j^A&t3-+&>MFV>YP`((Vlf)B|C3?bPaRF*eh zkvg5Dc;3MTeG6l_Kz!vDA07B@xO)N218Lh;VcQy@XII5v9mnsc_?qv5@2>dyasIiA z=PV&&{~n4T`kUUkY5bBe;NR8Y_i=Q_-0$hf!a1rVynZD2F*w|Xzw(0BE$E)PNtEL- z?mNr{l#$~ovv{|ORR0r7JNU=jVUH=cqh{T%jpSqqISv#vPM%cM+fsfI(_p&>zUhMC1$;VZV9x82@`qIHwI03&Cb^jwt#ResL+~pE0NBWVD+FUyv=% z(kHQR?xDRr3dk$H2odW;kA0Q7P-x!)%_+SE;*uLsWdF@bOkr9Fg;seQew&mnAy)80 zw;XVx{V+;tz9Bv=VJB_2@D%tYgPBg@Nn96RrUdrb@|6_-8ZhrY*2C{NDeIm!12c1c z&ZL;bDLkcDAo49atI(Abnf?;I)9A^X+(ne}+=bbs$nj9W=5$8oQv13KzQt4g@L>q~ z%t!C<@%aq-v6k2PyWH;CL#1BCuIahcOWv zGP}3pl8TTru@j2t^!GTwBE&rM51Gk7;zEk>yB_v8Xoq~CpxN(Q?D-J94R!R4;QI8y z9SE-?0#YvcKBs5+ZU7c+13Al#gS*_7sSw||IG=vxQTaN&2ru7ri|EvEJXU!-lOcY6 z*OUC{@MvK$Ua$>}P&_6>QM{{oOopO(NAZ{p4T=BWF!;OUcxii1|Gja%)qh_V?;4C< z<`T)bkjC3VgSUey2axJg0Ny~x$1MVibnd0s(A=?;HoywMd_7N!FJlP%uuHW(n8a1z zXRdcD9S|QN(&=Yfl|c-c%S6TRq4c&; zw6zy}S7;so0MbFkG~>`ns;i6y{{Tr&Khv;3D0`*KJ~*W87|N35^fRr>>bpKRmYGd? zPgtojxG9HAz7!rV*$=@Z@3PQuqmi$bCBA&DFDqx2Xf8wXoxBDFqLF3JjK*jM_iWCKwg|Uy&a) zYQTXgna*s{8)+Tr-?O5QF;|m&=+J$#-s=oCpG9M1U*XHFi-E`~;gf6Ccu?70#LnoP zm$HJd-m^QUy=rB5RoTeAn6iQo%kEt(yPL{J=FXHAd{}lLU)CRi<~xH=!TSTRAaM$f z7{?%n@x_&SU;=uFU~uuOwybp)FktW;O&ngKue*8$`9v@Sj=ttN&?C0>GXtrG$#`-j z*$IzJ8+E?KCIl_p;tfZq{5+#!19l|tq>hFDcSk{fE!k6_jJ;-yq53hfHaYmL*dHll zx_3e@g{=`U{N0wnikdAbudtnx!W)X7*u+D%Lc4qap|1>ykLWR-p&n&!9PddGdt5eT|C2=WpbT*ZHojer&k!f8fR7 zw4kaQc2kATMa?gS<6t247#C=}3${FNHk|V6Al%{l>BtGEqHkw!8yie|5b;7CZ(HJ{a(V`MUGHscJ~kbP|BXk+{`Y;MoS&kz zp{(^T&-pPv$_gpmJcDvN?ib>e@?yJZq;`*;BK`s zU6*n7bB6m)YPiCF!jNr6l>8P4u0!lE^i5qKCP)UKP~MnOvidR3Omn6;;uV}?j>FbB zz#+iB_03+o?t%lL551LqGs9|zK*;^U2m7e&F$c$5i(BW^Z-o=wG)13A1;^Az)e?QFpbc4hglp6i2E1xWb z7tw~b8%8wS*lctLUkCz>q4{DcH1|aKy+nA$!O&}a66#wFy-Cp*e0=RosuJfXpdZSj zGkF6DQ{2UjNR;0~FzClw-vkn$!kkk2tFSXL!Hxsv%kPq>7g&v;VheEZM{zpNgz}yS zc7Ckv%c6{DH`u)Y287Mq8|ml$7LY^doh45!@5U(3bf0JN;!HUos6%g+Esu?IbstTp zL9B0}a|gZfHWDomwmgJ8ch}(uTrk>bKW_Jm$jE{^X2UU&yFAC=$r6L-&RWawWPMeXX9q0L>; zxv*nFUArxN3R#t>LS`99wDL~8V)i<~;U*!wjH6`vFcLUY zl^64hV^sM>UU76Pe-$SYF5_5JK8-krsvLi}jJ;wRd$blWW5AZLA(f$8zKvI`fbzMd zvg4KW441LbWnVO1*`-N0q1jUr#=K}~)n&)i{o>XFwqV(ThYsz1-wXB%RJ*yoh+?W1AxM-=J#1Th;` z$F|gMb@0W(co~FVT^laU^~>o`31Q#ty>^~?3<}JV%p(mR# z`We$^ZGdFl zBd4%l?v?9Tr#w6*W!{z4-GJA>*nm9GO8Of~mrP|YXGnU>ROWTRr1@#Q-b&JgB|Uu_ zWxp-yPo`1oS;7Bn8tbKLIz4kuZp!qm*>(Dq=_%7coj!a?@S`_OZkRP2Ax)VFHl*fX zN;-3+bv8s@ zRIt!a0&Qxcodw#_Lc4IS!t4Xc;B=GSg?6~m#+!WvI$ofnSuD`k1?n|R1iD6`4b3uv z9e;QXFwnP{PVg|;!Emr#56NxfrpChC1V^8=yH721w~ zScU^cZb$QwKxII0;Kba=g!5d1b}~;1bQ7Sr%uePRfqrPA=LA|U(9Y)90{vT{UCeI; z>P%ASuI3eiHUgA0dze2-e%lJPm-(xBkRw)8VlVTKKt}*-OUyI>5a=sHn`izh(76Kb zZT=-%ZikjtI3xZ4B!|ZUO-$^MmcoeqjfEV6-m{P^P%fpM9$C$LfSS$zCMmSd0p$SI zCAi;cR}6wV^Ep^YXg`4tGVKX^@bkiXh#4hv%K^2BHT4^^6)B=cFZWS$EfSAK=LfaV7 z5K_Vp8K4L8 zZP_OTx>aZ;^Nc``3Ur)#UZ7_!^pfQF2S7RWx9=s`j{bo;%QcBFjflda*I$8?Ok@%WfqsW~ia;KWH z0<93}G_#&S7g}f|fv&dDrlRE@K&#O9cNW@@0X>sA$IKV#MGGwy=uHdlFHpLUa_5-O z2{Z=KgLnddh(JXP9U;(63oR08PYWF*(4l}okf&?V+;0(~gZrRE$d?Z_KND!Cg`RX0`0GgY)*?frMw#hs!w41SjN$7D4 zjTPuc3(XVgH4E({&^s0y6zD?>oi9*h1M|DZTOS@X2$$&0!ZZSU< zXnjk2LZB%Y`nf=x0h(lPHBX`=#Qq&Xb@+@%G;{>`?peG1H?%Sf}DGS{M=)uHOrdw#=7us*loTQ5u zzAqN~a^|;YuMqUA**oc(U30uYITmRu^^M$EGk@6?x$#I}tY>QWXBw$z_K0e_pIjdr!aOwM0L&goH=Pa6aZT4EEjEosI!)4zCEcv)24H3) z_3haPob#9MAn9C@+P}%S8SDPd)Ru4l8`3e&LtDtwCCrA+Ot)x$8|n7A9&fId^fr-F z9@SRmNtnMibBKEvQepl!b70HgP?p1xCd}tssO|Wcu}BAj8E;Mz{OK)|5(#sE>t^8m zN$W}WI$@q~Jqy>bwo;b)dgd>ndgd+R`A6%G3BT-a+l`6&%QBMYkh*3<+kJuTtF6sw zJDN^t8;$Gl;nc*0c|_8u+E`MzeQ)4ZYC_u;a(zA0+3oi_p4fmGXnz|v>?!F!NE2rN zcIr``SG3ooO|EQjLV9aEZEnv`z;%1R4=Ky&Nt!Spbds7KNzZhQ9E)^4qzUuJNNW3^ zk*pmpwKt01XdT78#*TW}8*la-Memi6Cd^kPJykHuf0l5v6w}Pbqq4XIzd_P_B>jn` zFG%`lN&ipM>}V~;uh1eUw7o3pXeVVl$Bas)%-Atwalf+em@&9sZw%tiOc^r{*Bg$R zkeX)xHioh5qc=UAMu)rk4a%z8{4B>iU-uiNB$9Z4rj+Ksd-wLtipZnPfL&5=$s zv)3Do=Zo{#%OX8g(qn;{X8LhG&72|WHzmDB(px0`zNAk{`jVu-m-KB(O+mbY12t3T z!=As7)bz=57*NbT47P=m^j5)zVcQ?+#2zZW#9&Owe&}9~S269=m%0jO|E^8i8 zNIX$*o(Z6wsW-1%&K*bOxiUCGtQO7&lMkRAXa$8bZ*z7E<5bG?O_Lz8*XLYIPu*@;48S+n_70Oc^(`E3BTU}f-) z0LlS+H-HYtO2#@9{qh}&x%hSg^aZSx94nB<(nzyBfGRk_{x#*y{A|PtSVeh1kZS?d zJjvHdXmSMFJb+FHP5(WbY;F1~RylSNn&!8TnHO+YuoLXd0dyYLX|4~Ti?HVLd;nc( z)-`Vk^r)fE3Fgf8d|OU76U_|)bTj5p&j!#PSn=@+?@TP|j>_7AurFx+#xUhtor}EzHFs zXiIZr0JUHZ;`Ru1Zv=WM0zIKnhOKy}dCfv+Hst{QHN?3Ujl{o4bC)#zO1>bg(DhBf z4nb_wRZh0zDs%_RP=%OZ6?(8~bqIPwINuF&zY?^mMdn9eSIjK4Ab`#@TbtzpbdlM{ ztP!kp_MOdbmPTLiZ0@%-dTAH)jHMme zoCEZVg+AZB8Y?dETIh?-{|m^&13qK^P)85$X4Vntw9HAM?PmD!k2LyocQeb<&VtU} z&F2+@KXdqw$Up$ShgF=5Ea!dAd90=0W}(NMw*mCyfU^bAGXZoZpuQ>0?=*>}d1kJK zSiX5?e+#iz_BN+mh$Y(FTxB7aXm4|~g=qDB^N59L^?dV|g;Fi4#6D&ucE&Kj)|Li9 zJp!F%#Np(I`itsjA=MWD?B=wxv26hJLzp*bc3ogIO$44{#Th32sU%9(x5 z3jy>VPUU|`p$z?bfN8+7cddo($}r7LlOnW!}BuMaR=2T%o^hX>Gk=0J0f zK&O~?c_h|C*mcGQH<^)T7 zyk*P8VdkO$+BR{xGJ^A$kUPTMXKB9&bfkGgA@eTsJIcH-&?AXNE1~5ZQuHJRm`n)MvXzSJk5??U$1UfCVd+QO2W6fn2+DD*O7CK0v z_Z2cnwjKk{o{g#VG(eR^$?PxCZxdf=?MfVHmJ4)lXG8Dg%yH%%fgTmBk2BY)ocQ`U zb6WsyX^u1ACe-<;p_j^L9}CeF6|+PjjzFg+mYAyqV!w25VySs2BzL@7Au#M zI}>M{nVS>RGJM_43!n%uhKlH8%;QoR^t90;q!Zx@QE^94)2{Foy|5xpwDDvs@tMyvqDL z#Q7~VQifdRTxt3QQqHT*{sO5j*O(Im&K9iDU8YdxrM7X-wdQVx;HAlcUJsxt&bLkH zELw(WXxrSm&djmUU)tt4*PFux()?~Pk8Dj&&F@AtaW)}s4>y@r0@2QeSOc884QZ!k zGVO<8um4So^XC(P7p}j(IY0c18M5BADM{)(bvCn z9yQwr&~Kc_%wYlaXXnS}6orsq#r(v4GXyYUu~W<1q)5e_qflQ z?G!S-`F21HEHoXo=gm@uM9cH$0xL%?FPK#pnw0NKykMTPa=rO=+!xGS7Mc#)uT96! zk~_4t;8|I30Cj^lOCTL{UNna(4Q1cKebKB4pt*RicXt3Sbbn)>S4ecOHops??!;>I zmO`0X`6Ci9o2Ff~>~jQ~YN6c)nroqb1X^sNg9JK9A+sodi2Jg+&C<&GMeZx+NegA# z3B6^Z0iiYRs`;HE&{T!6f20J?xdC*%`&+Zba&ip+t+~L`9&cF)+HC7g{A}gqq)XHGdiAg zUpGIt&^8^b-9MQ(EVMVEKbxkxn#2Abzjyy)HVU9O@eK7K3mw|=4xr@$^uGJ1xy?ey zg7&6)CV<{||7tK%$G_9eK!@x7)l3Yadhc&$u7y@~v;bNXK%>03%vBb;xMMt^M=bR1 zj`h9&F|R9>`A)|;=WWxlr{-{9$29M4Gu1*b)=%^PZsrA0pZAVA!9ovpY~}s0xy(XO z1Nw(~&_Xxnw)g&NUbE2eJGS@UHJQCMhj%)5_5NjgEc9PpZ9NbzlGNAJjDCJykep5&PCpb#+#=(Y~Q)q!+te|q~$n?Sr%f;aS{tG z#FpbE7F&od$4Q)SA+{VRag{>Sa-787md2LjCZ4nqTaKG}-9l_RSdiXZY{{_YxQR}M zq~*AYsR4An>m}w{PPPXxag2r79=ybI3$Z_O}q*Lprg5N4Eo=|DL?M9QcN-JCScvVRF>%=c$KIO&Mp0#L z!?&uttCw^__8kZiFbD}@kwsC72}_hcK?PB0k`A%!}(Rk=#Y}6>pooaL{MB^dVcuS*vcbb7sAO1T>(0E8QauuTSkZzPq#N#2un55!p zJY*R26{7KwX>@2b+MQ*rQ;5bxwy{Ma8V@8s?XQxAq$rAZS=e;2gG3phXlothRRp>;-l^EwL z6hT~xv7XVB{^fZK%z?)33SG#E@}@P|4S9FD2O6CmC)Z$y8qZ5fL2-u~w&d=-*{(sx z`wq#$#^;P^{gN&Q8<{7uPCS!2+cnr2%t*$S8j~DxrN(?mT$!=R5m#ocbi@rY&UM5M zF*Z8l%8e}vsM8@?ZoJA!)@Z1)TT1d7{7~b2oi14nHA?2nQd4b*8EY6(sgD%Hjcty& z5k|_%Bq?ijm{G#$Np7XXj1C7HX>69rM=d|fcts&<`BAz(zs=k39%Z;sA)T_EV~ijp znZp=k1fwSfNsck5JK~NoIvjCF80#6W@(sxEZ5(NgnnyZU`NrfIx{fp|7?IAXILeqS z5q54*yN@i0!=g|SPcKf8}HzSQUgccqa!pYo%1@|W%^ zqgMj4(-#zsam_v4ILG&<6lY;=SK{-d}mV~SD62P<-2KGm3` z5bcYn8I6qO&StuCjf$fk?R3LiC$&(GW*E5&QM#E%l#y)f8e=UZ*@893ZY4=tY79?( zTuZHy#Ym=`W%Sf2DrOl~5}|bqJ;xjM3gs0LTB%Smqm2@Y!wMdD9dGPWabpp8f|1FG zL+AL$GpbT(2BVlla~N$_sGiX)3bitFH&Ch1@tw|SghCfGs+UMyQP3CptyJiU%)Xuz zjV&4->X~iq(rA=tj`6)lRi2ZKqJ^9T`hBuzt}%&`?9G#ns6uoqc8al9A?k;DM(QF; zw@Pd*nC+Qwe6G;F1$CZ!V>1r1DDLHgM$bZH+^G_MU(n%MY?LgPD66o;(_-vaXhh)} zPtV~ElL{~PbQl|&81cE(ay{biEZlD_H@@e%%dt%f-Wm-+RtCs#;|^A1?gKbD^^am}FgS z)GD;MFx9%mSgDY^XO?xTaSNkW$S+;2H?}d7mb~6>rQ|U^7npH$T+h{z?39w?T|zQ0ThKfi4kOJJ4a)wHn=9aFn%CqvoD?MoFU;KsRf&wr5oQR-@|? zw?(5n5O<44zXQ5eqi1?fv~DwAQFZ^m=QQh1|RSBLeGaUUbug1<9vVI)sOe`oAel9%*a zY5mUFqtHg6M~%U!NiExfb{f78iJt3qw)L3Nv5e5g;<;WIS)E4bavNP~J!J$>x6vl+ zS>tPs?zCPoURzviLzRfMEXylGs+ zh|Y9gv)(keG5W}$^OrXb<1CVtwSC(NG9t-Ot+$P083)hzj(FP`tI%P+zX6)0P*v}D z#5=}(h2|pe9ivg9Snt1C?;2|qIYp5EEs4-NOZ5`Ejdm-l01gF@b-0p3rI*A&Vu8tnbd zn0ua-99}fS`&Z*>g{q3idjDpuzkuRoOYAkyWhDE3ud#&@d4^=M*LYq^qFv^BzcM~i zXj>5>_gc~-J?2-+b~`(R~MZTHINS3<5JWnAib)mUQAu4rGa~mVs)4j|;Got*~ zczc#8r|U?XjV!Do$2CGbE-y%8i$&5CE|NagUr(vqPt0h%xf6Q zJ4S=d2X(r05VwmF?pO7B$UE5lgpoYUD>Z!^s4O2DbRJo17BQk4MMbGOf|0CInK@e_ zs?iX$!x2|*e(s1HYW`CpYO`Tx;gytwZ295la7L6vx)^RwVkC1IZthlyau{L$O(D{9 zn3;N2T+2xF5JpnVNOOor$zr5gB@ukV^WIVBd`2>dQRY<&Q4XWcTXec~F~+<*0X^+V zH^%IFHRUet`fzhFBg!35H<+VU99hp;^LB^ik>=+P$)n8g9g;_z^RJ2P9A|E2Bz0Dp zkEl4(d5l?nZCtX_tY;)8tISpvN0Q^sZ4Su^=GR)X&^6Jd7o5O{_@3|cmUohw%Sg7% zB=Z%Gjx?%G-}UkQjy0Qi=`3R%Saqj(@ce?q8j*E)v=Esa^-rVb*VTv0B{yWEaT;CtOHD)fORd{X+ zck#_dD(=+2Zvd@SXneswtH#`-&{#&h6q>=veWTPlhtX(->KQdE)XHe1LZ>r&MWG8B z`8G){vA*vh_kN7zj8J1%$~e^FNW>k_=t)5>QEM)B#LY6-sW@uS5!an?$(mH z8*hHDQIcn3gq9vuy4x<*O9g=TL?QZix=)^W*Vu{m0!BwwRB-XYm+ z&eU;uje&WJMoGRU=3<9r)TF%adp+$6(Y>B@ahgVSuP2VyXBGOEnH_O0V!647(dE9E z`}XxMH#af5SiIYJ0MIrWC%*1`DA4l?{j+bm?{xDmM(agVzmdK(%&MEIG?$A${l@vu zGSAg$qVH_;QjG@q&M`MDGysz4n4f4g(RZ%-cZ~-4&NJP=l{&9W8wWH=qlvx?%o>db z_|}^B3JrqJwdNL$Ci;G3-mB37-$mx*3XSeJ8R!oh)%q?r-_q!0-+Ht67Mc6#ev5n? z%%K{!`K~gnG+N=i*8H_b=lgCjuhi%=-zM{Rjc)MWZ2nE7t-f1L&n3_j|OQQ+?KbY>@q|PJz?e*<4 zi#7Vu_ljAik>CHSS+7xs|8;Y{M!o%SnVlL9^uJ?%sZeFVss4A(Nw>=!D*K)2f8VUt zXuf}sS+CHl+^xP3&E**BctO;{_yNDs+18LciZ-+$l?TdTxt9=t|e9-Jjy> zr_d7U?BN=rQHwv_HD053f2Qkrg*y5z_h-2pHCpY@b*qHlmJd8@2LM&=IxA+BB;J?THxHAJHq{DWQN z6gscpR)4AMc#XFE%Uz8cP4o?Ot=4FVf4FOdMo;=jy6)8I1^;MQr$XzYbByax8g2KF zb$z7KMBh=a?-aTbl1ICe?~Y9ztDA_Mj!f5bzQB{hmdS^-J#Lj{#Mtc8hz-G zx?a-hKKHk~KG*0Qe}~I^k1W}1{r35nyZS2hEp-0MHAbVi{b#zSYxJRiwQHe5R`JXJ zH7E_Ib? zloYtaRi#mS;40UAjdBCmxK7uoPhg{KgGMERO|ESkl?85c?b2ve;1<{C8XXn5-R0Y6 z=Ux@K(^ag|l)yc%aT?VI?sLu6Xii|et3#u3;9=K#jhX|$bKRxUNZ(G^qZ%y@{ND9~ zMrQ<`alNV0*@5R>do@}gc*$kmXP4}Tz@J0i%~h(={eib!M{88>d)GBXq5NVq z@Sdwpqolxxu1hsa4}9XsyUV0()IK_sg>67ncS8?i#JpsK9rw z*%}=c_=jt`Mpc1*uB$bgf}gECqERhAN%FQva{?asj~ayoes}Nfc7Dx)pnIG~I|3>0 zkVa1i(%q{ydLfYI-lWmXfgE?IMsEcQ+#hQ6L7TAU8jT7}a?jN0sK9aVW{q+KQ{3lk)F&{*eX~X-fm-+D z8dU|3cfX_2l)xPKKQyWhob1ki$j*IEV4i!JM&Ur6d#Xmwfd==f8oeA?~WT4&stwt{dI^5|G+qr)lSne*?=3QCXnS^N2>H0!5zJG&(BK&-1lL zxq<$k)W-z=yIjnIeGc>t)~F;f*fU9^sz8~iUZW|2VV;#5)dmjpT%*yPz$niH8ifN# zcwW({IdGKcOO0L*jPnE^w{w3hP~|Dn=!3vSPnAYH0@a@R8a)}9;yGQT7Xs5g8#MYf zFw=9ZMqdYx_dKG}{=jU{iweD&`N+!=r>ODb5=ZHvg z-=um^o<@fzHFySSG(0Kd8KKcpNll&!8cj-S@tmkpO;VeuL8JLeOFbPLEl%q2oUhSo zNx$-J(CF->Gd*`|bYaqJPp3xTh&7%!G`ckDY|keOwH9BS^lJ|eJMo`9-8$FfV{|#6 z7o6)UQi#qA&i9lmL_6=bp2Ib&_5H>(Nu!f}7kkduXp!$S&lMWA`L6KXuF(qLRh~~Z zI^TDl=bsu~=G*8={XLcJaxuE!4ZcmDDH?6{{nk^b(RSaho@E;C@ZIjYNTbJncX+O1 zB(!*EJyDI`O?uXI zwnm>Oz2LcAqpy;7c{XdbKj{_E{Tlg#uX+BU(6-`Nliv31*67oucRhdAXn)fCo}U!T zhvY||%%^0H@{8Y1`ouFpqfe7Q^NiK#tE4YH$7-}c=_^l2BVX`a&zTB64xRt>tkdYz zr2U?2HQJAFMr~8*&7`cL+xopmg+a^uqejI+zqQ9smzxz#w!YD*FxbPwL)UCCkLMN# z)2%#(UPkWO)}b1Gnv`pe(rABDfi+d3_aNEZny1mHNqwwFjrJ!MTW2Vgk@;d$iFJ`i zPbCequGZ+Wq*CiPh0g2uVp5s)m_|<}4Ygj-=&_{X*4qkwUi@Ox2mLf8*KbX5nU(sS ztkHS>E)1S-6>79Tc!o7tqpkiktz$LX?q6*kuhB%`8f%e4p8h8W&$f1IR2MwY%6(qu z;OXBOTx-QNiUogTouko;;3d|j8g2JqW^Gm|1v;;=_GwfXyxOXLLF!C_&g-nZG>Qc` zT2E=TBDmRlMWgNh-&&t2L>6+3C0>+T$U<(jk{L-0xx>m;anJR-DtL!=s75yh@3uy1 zbZ2mzHA$oUgZEq8GQTBj(KUwl>Y zX{%kMn}W|!b8Lgz8+ln75ie+J1t8vQ-^q2>Fdtoy?`Gk}U1$vS*w zQ4H?ccq;l^$sbuIQWDQ}zZU%1s#1vR@Ub;tp)J|L^! zoMV$ewH7JVGiOHfUo3iuEUhkv0exm|Q0VZS6O%u;?oy~SXI}DOt)~^51@wirTcNo* z4atAAzSpQZ`Ae(t6{)i>ryXd7Mk|u{S|=*hjJUm4t41r5zp~aVv?6B>(Cr$nP5!&J zOQE$nmjZpF(bdUcTfslc{I1No5vW+9n{#eW{>BeJ@b8PTit5Km3 za~??k&RV0;{+vgXzqhVYD3JSP@(m`$Q^}IpTzOl161I!aG+Y*!+kT!y9~+YwJ6s ze_x;JEs;oU=wF#)dK)#GoZ|AH$4KVx_Fk#cYT@>7kx1O!zc$6=eM_S`DVDeJH7>Qd zyZ?d|zjp>BIc|gAMU3RiIOwHU36u4Z=S%TksL-29v0$qAdW}{DGrhNKwB4WM-J#Iq zxv^lL_Z5v+1bcel(`dWD$orK-wl5slvBH>sSIZi8s{)-sZBI#}XuREXYmu*ADYA$qsL67Mw%(c27`c(*A;?;2R* zeO@7YE5Q=)9);+A0!zI66r$haFY#u+#ku?T_4j*`pF;F@k0suX5{aY%Eh$U9k0`Vw zxHP5ByGNrlQlehGK$7YpG6tNH67v=+Q~=cO9j(xzKuf(RDl~Gy*(s-aPuJ+elx5z{ z8eNw1EAR6PU6*!k$_no%8l3^;e~0puBj*e+eu7B3qXqY;oZ&5Dbh)o%fUC!u-sv*V zcfkNZ&{~DIr1k)MTA}p=vc;L+ze&Ve&h)z9Wu5%={z~s)g`S4wN^h+~)JiM8zmka4 zt@N%_aqkQ`q{k}n0}6dIpcKfrn{;08qj_wVw^$v%T9CdO!EkF){rC++h* zZ+-$Q*Jyxso;SwmNgq9xdx3YYLiAMb1>Ox3;i=qGYpwSyh3Glli@cuqDTgQVjP)gA zoi|sb!>miZgB7CZa4+*dt`I$kdzJT(3ej`8S9{-Ah@QN?#`~2*^i=M(-u(*EbGX-e zeILmD=sDc$y^VV$qUUfodgp&gXqCt>Il0Fs@ADr?)W0NIZ1#FTmS|{6U5}f*g$f-} zvZ%++-VF*(ENSZTTW{tkQgUWVTaPW?F$ygz>F9Bbw^pI0C55hAy=@vr#cke|8lBnW zcJC_+oeRl3y97ep~Wk@NTd83rSv%Uz!mr zROr5vU-!7%J5HgO8PzNFDWh{0@(#QZk{cxww7R(4yHlg)wdO}P)GwF@#r~YhM#@@v;JD8r4PPq^@@n*fmuuD9}GV~4_LrD2S zsT3XxYKp@^U3kynfjLsXPal#T07~y=v%@ZN>)?N#BXgX~`OAwC8ePNNx1S90Tt|B>IyhEcucK zN-6fU3@Xo;po!su-2Nx!6Q8Jww*gXkFWaZoEcMV^b|l}#dlf0{jFmF)b1u@Vow3gF z!Ajzkk=mS+&RE$dbzC0FznH_4-w)PKZyr1_y#|ta?2+X+GL>m%j?P@DE{S#gC7ka0 z(&$UnLo%k2xyu%l`O2P>{O)?3k}~$c%ORUF@!m-qn=?V(;sj6+-aC1q5+=5xtb2Fb zvy5~WgW|oS93~FE84oe%uM_a%d#T;qFGFFDAjFaz7EBVrAKEnMXmcm+I#^ zQp3UM&!_z*vGcf&l6IHxqkWw{3&@gmm;8Co!OH)yY5V!SWURAZzod3fkC&BAy)UWk zyPv1Bucf^7MNSPe?DP)@3(GRd@;gU&_wnWAkbg7T9~$iIWZ0#AqttUSf9uTUU|wY( zdtGOa2Mc%CMmkNrpOi*1#k$2>wzsZ)yg&CBN*+vuTU>HL&2I56a`&iM@}DNZ+sqJ7 z?|QHrIr-h?f1VTXWtX^z%hsLaw7Tx$+#yt2xo#=qFmYUpBW;q})>N}wJnX_}lE{Xg zoB>Gd#v661HHIK;h|x@)e(4zI$bLMI!?MMuA?)In5?-Ic{20><9WwOBI71NM6qkXz z#7!LQEW=iC+=5DyShh~)Q`v0&G8ajm8oJl(e z0X4*mp+v6&#S9MW;@0Vmy{*;m6T{5_~C_H+2(7yI+;z3SmqhT}jD;S5vz zOONUjQxNOsl6#cbm9>yQ*;(@cE{FQg6g8ZCJnZ7Uq>af~$#JXPsRvDQ3a5&P?NnVk zcB;7k?wY%E>{NBg#pLqXGftdi2nrjbiDl$WM0GKllUU}ie1mH(CFza)2Ts+M@07Ij zrS`YWCQBlFgu=f}rfV*C-MjMtJ-Nr*)2>CFW4Cae^Y52AoqN#Ps&S4XC@g8BRs8#8 z&hA#8IL8namNcrH$ zx)VoSSH5$tWsi4fO{IU3V~4^{`TsLCcdd~7w6b}^Cp&&wV2VL_D#-nBxhKb;r~mg zJp*iDN1*Y4>kjraQ-OpUZfZT?1-}c-YRXE9ZYL zl`J9kxYO#SACM)q%lSVgLsoR4R*LiO9HkB4#O<(^sdL;p!*PpB)ZCTtv`J_9|I}35 z*bdCZFt;&+j>( zOqLcapY05cpi!0qYKk1b$9=G{d`el~m3Go!GAgMqvi$g_ax%P*e*`FB6PBcI!m z<&-1$U{CMN;nt8(@5rYb<}+sjQyH%3u-wu#!NisHLAe4U!_?AyMmk60;6#a$wb z@4l|W70<_u+rg_a=uM;5OlN?8BW5!VF(<-w3DadvS1~=0>BUU11YIp|08Pi+yyqlW zr1}MgA2dn^W#b#SrGqN*jRyL5@`J|LIW4IV8g1DN%mbA z&lvQ@#|UelAwDe4$XsIXEzQqd22QeAWH({_6W=(SYzO=GSsbYFS&Ym{hhsvlid*dK`3E_V&!V z96Og|=W^^^j-AV~^@v^WJ&*NVY&MsDkhNFD%02;IQTDeiYJq)O&xp3{(b=DhE6Wy` zpNbpHDiPjWIw!jkX+QRyhql^}?>o}B*-uCKg6u2JN6Ri{dUN&-(EO+DyFpju>%Mc6 z-^!*INXI9cW)GUqc*$)~^hx~-_$|3F?vW?Q5E6trljsSfQG|${K zFo8bRy`mta*8B@w9iFcRj3ed0v`p>(G_p-zUyXCdL9MZ<$4l@VrG-@Y!wQMh z)MKbgoY&#~N(;xR*g46E7y9tk^8Wa0d!{%PG*=7(EyQPIeWI25G3IwLKi441LW3lW z43b=966ai#IBQMftTQQXC-^DiOLJ37iul@mBL%s*I2RY^;^JIfBw6ID>fsZ`u4>Q{ z*HqBKt{Tu0EI*p%$Flr5$d}>k;U^WAi9w<+zf24lA%qJ!e3F=lhrlXD8#u>_D?w{S zEjWwCX`mTm0yuS|8Q~p)A=&f@SU z&`GIJfPR~21nAQ(;QfejBI?!PHS)jwyH-XMce}Xw5 zFzx4#idE^AOsm|_q2=okz9;=G&|vx|rcW^a0CZQX%fsblTFJBy^t<#uUP@aZAnMAz z*KEnJ%)Zy0Sg@V0@0)Ey`&`8$CAshycWOWXsw8g`T79Dx7nUlR{ zI)(Qzt(rmM%}n>qq_De|Xz?tfYnX06p2D3cFg=m^vx(NvVR{nL;<-e3&fR1U&)>u0 z%_np0DI7bG=pLq<=QBUV`~}Qsy19<|^~?`5pXufX<}YMEUax@?Mwp&Tbmyt}q8)ZK z-NPKQm^n=MEG8MzNSq?3osGnq-_#G5vy$mXraPJLX1b?|Q#F&!o@NSnws5LePQ`R1 z)16FrGu_k5sg`i6C7h~_=*}o{b~D`*WtkZ3VY-p&PNwd5iY;Essg`mors6aTSDi-u zl^ov4bSKj_9W1|$<(Z1*6m~CXc@A%6x|3=BuZX|qbWU|Tr(!BrPOc~ zo*CcEt~!f3XA!4<4Taa7O?2})L_2>?bkDg&-RBeCeLknXfWlR4 ziPm38bj@#wZoY`<&WlK(sg;o@tFR$WK5{(7QoHWJ-@1JTYKiSF4%v}p6aW^2JX&_NTPB)3&7Fnf`kEJL!AU zKTAI(5#~xFTaq#`cUSGM>$NDdVk-k28MA@MI=u_Q^aV zvodpP=FH3!Gq1?JHuI*;M>2P1zMlDU=3g`ap7}%OPnn*qq^z{8oUEQ%{jvsT4aqtz z>xit1tkqfPX8k5>eb!Z38?$cCx;^WjtOv4wm(`i|Y}T%dn|8P-k!Wq^S;MYI3xd% z{IU5H@~7q3=120c$={TJXa1x4FXg|N|5^Um`R;<`f{cQ^g5rWh3x*bqE;yUZAD@BuAFLD?BD4;B)vNKroK4~)d}sR#af`SSJJ(I(4*a`Q+%2|>ZQ>qrzqnUy zN9X}qL?jtMRuShj{XC@x;U80oli7o4G1KxMCn9_}hie`5W)9!!;Jnpi1td>Tjq7|n zm3}z?aVq_|-KqZzhs<}WpCR@q<{V63mPeLEmR4%GE{)PUHN2iix$jA%x=2Z>Q%cHQ zO4Bn8A)Jz%=|?-_u8d!Szm4gGOmELj!hyjTnbSZEvl>7T&)NVgvMJw@Ovh#q!w;40 za0S9sb4kxkrn8vNX6ni${wcZ3-K33Zn8Qs>Wxl89t^|Ko?m3|6n|lf9$m|WE z>vFFHy&`ur=&iZ8fW&781{MYi@l1II{jp<`~)F!)_N?USrCg)RY+@9(22w{ge zAUv;-XamzI(+;L9nV!w`0;ZQTy_)G3rtkHXz3>j++;n(Wm6!BWU(6^X8ZJ5(oOc7$ zL6;UC&#{f5q7PBozjn|55uDw9-UA(({S)ZQz8;?tXZQUW;vI#gA>O;Y9W#L1M~>N>2W0gS;=Ta| zpdY990exryjR@JNf8wx|{QH36i2Y%}7*JV9*&}0183QjxY$?;Dna&<~We*dc z(#0N={ALn7Cw`~TGzH$%L~^1%5M#i1CLx>#o*~jfO_6~Z13NjQ*@!Vk7SlY$nAp{2 zf%XTyj6!%Gs43=)F$jl1O|d{6fp8tu zus9N&dZrEHXz&*@jbPtx!oL$e74w227K56i5hcZMKtN5=EG8n{0&0pj?5R!61IK|b zMGXvb8mK8cP!B^aM-5D|jOnjX1N`0r)D$aF13V!EYKrs437{8<+2CA)+L-tXAJOYk z8&hmVJ?Jw(A<$<~b`!hwFz8=UUQ>L5dB_w2V=-u&(FB@qw18$COF(msC}>}!9kicu z8fdYx479)TE6@SP3eXbcOwfVGD$qmmsXbE+GR_7qGky&^)Hn}xm~jE9c5ewI@-7bbc%5$=*h;_pr;tug3dFp2c2)+02(qjfz}x}fz}(p1q~aw zfHoMnfkuowKunDgPv{d0KLk16zz63s41>7 z9z*zAP`u^9cmni#qsioyH$PUo&0;ecN~$^c~|* zpzj*5g1%?G4*I_FCg=yo+n{@lcR@ci-UI!}_yF`{<3rF-jE_Nk;DiLD1{7^&eg-zOajWS9z0dT3K45x5A2R)*51UD#kC@4zJIo%SzcbT7A2l;TcbZwCkC{23 zkDGa*PnZRud(57om*Lye(2uW3o8k(5FWM9v@MUPUv-=RxtMS!lw6l8<=(X-r&`s_k zpqt%8L2q&o2ff*S80c^Dm0?qCagPDL#eD?mt?na1Z^QS0@r!AE+ZScPSA0#e3*YNC z#gFcZpg*~*L51fyP{T6?)bvaPb$Mohx;-_Z9?vXL3ty1Mnh)QKh5x}j&!kle!wF)N_)$hSc?Jbv;jA zFI3ly)%7xUeMw!vQP&^Tb-%hAE~($6t{1E8rRsWxy569!ud3_o>iV|2{!?A|tLslT z-!1j;SJ&@6691sC|5VpBOY$?+HA`LlscV0AJw#nEQ`alh^-6WUL0vbg>rLuNj_PgWOePKuBGZaL|uof>(PEG-=wZf)U{n*m#OOtb-g|ysMG^=d}B@70V!nBfQGuM~e}_#1-1a{TdsW2dy# zw>O5563y++kyu$nTc{~~T1(sFviinGQ5lMb7q+x5tBA$gA`9AMVKH?UNlmb&L{%sj zYHf)$$KoQI6?O2!(Ym%sYb?^z9A{1mN28&I;VGe5-6Ao*qcvO?3)heDs0(+ILsVm= zF5<|ddSP=*TR5(%y1A~gy*`Yzbcyq)H-=&jEp1J4PGx&ztlgP(dRt3txGm4fe5^9|g=}2s*n)XP{QHa`bsI98yG)I25;i#if)dVX;(J<9o*dU&X&8cZ= zZ>vkt8;y0#n}ijU3zw)y#T=kSi^2(}Oa0Q)?kJ>cxoAyoMO>xLoN^#$?V`4Ds6H;t zz1X!5)icA#6k(eX>#L(YO-v<>WUL? zvvF0pAq2MmSS z7ehC(xmSf7!wZp_!*Gvjk2Io@#58zP@|!iWP#rdK+Wxy@IP^B;4!eMvIu*qu9H}RS z>Y$UF*&a`JK0*!!4X3umbU5DinpM%*sKYfaO<@hDwlv4V36a<$9a9r-Y>>k_(!5Y} zY0l60i{KvD-&< z?Q6ynOmfOTZ7dBdZl?#~Cs>`*VXKtNtQ(i+ z6}Ss>+TG&Fsdm)@SI`!V(in59Zm#djni*agcFu8fOgYj>26|{wVliu58sUVR>%v&q zhJ{9gmQs%7<2&G0y6~zoekkR%hAt5m@Kp<&sp%%PwK%&r9#PxkP!2Yhl(2lgm=$ux z>cGu)EwpHjMwZgDRW5l&O?zD(9Alh8OCRlUrCOo2PYO4}eh6dO!9Ch@rjkQ}*rN#T zFjT~ZNMl$9CpNY$2*CtmG=%XiLntb$VPEhs@iJ6{w_HrdDul_DP%GsMOT~gUvK+x0 z$iujJb`a7ElzMxa7heUUOyQ0guLx}q0{@D+(MFU6MuPdp4z))ST3q;MbD285q=_JNCw>Js3pu$}xWP?HOXi+XQFS2FQvg&E70?IcjcD!xT7TPhz zn@Bc>AO}L*rK#{UqKtgBSQw7YW5}dFz767-DhGCku~KOd&zpx$5v)}3SU|b#k;Aqu z!d*8^-8r16EvK4JG|_g8>)Z}2wYgY0)MMaqsiXlowqgQnqj}xARJU$i&hvos9OF!5 z=k1iXc_cT>Q9hD!Vv6UDBiDpt22kxdZ~D^<2AERHs~qPi-=%W5pkMXTJvM#53f zLCrP<9l>fE3Gj<>VQQ3=%?vlF#X06uwMVUPZomP1IL70(p0;k$_&&6*r5y|WrU;I< zLLH)>0`(M{89Gg1s^_UoP4zO|7Iy4RRRcLWYO5u8uG}QfF+j~y(Y6r9ZjQ;SNk_qo z$Tw(vlD@TGHZY$IsAh{NS4nj;JBhq1@sQ4~ja^dr0ma4^v-6HbZ8Z^RuGEJrKMLwR zsX{V=?0!z;2-Z8ocE2kb-X+VC#X&9y>63d;-4YUVtRu$3jbRo_C?*=5TXx$0h{+T=lOwC6yqpvDE!?D{j(4AGZjc5{Cp%(RlzP7V3|TfY z+)TTG_)M9we*mcNwwmw8At`-4Aml#Vk+)qYHYVi(rDfG)N)0!&QL+KW;W5hunT3k1 zXln~C<3&v)t!zlPk{w)a+p?MArWRPQ#8M0I-v##K;L>J13|*2Zi$c49(HNU{oCq%g zSx6z+liXCmJuYoo47XhoUDjNud;^Coae%OZHp|C^7e<4dXqWSG@T~st; z@iM(Vx=0P#>Zmjkw$TbK%h25zK(+DRDfcKX1Ze>^GhE+})osEiJwXKqZ{1?Fe3bX^ zRB>qu6oOJgS&QiiNH(!3$~OF|Eex?w;wx>AR6Gn!O-9R@GdbM6Pz?@yk|jme%`lw! zs!DIlP$bR=dkqfI=@kd~+)BoUrt(!D5^=Em#)sKmwmfpL439uN$cm_NoS8Vo>PQ4~ z6|u>f=CKx5=O;Sg6q(Wj2^yEv8qoP@Pu^BIf;?uiO2*7#?<;5_uOPC)5K#wKR5m`I zf-Y(Xbs#0Cgqs#%R7&rq7W*_JRWPczUrGeMi%kgxU|+o5QhY!j$h=kKA0jDA3hqnUk2rP25hxwaHuIE-huIOq23PD zP=kUljA4Q|e{lr~a2SuYsV$W#5eMl=#ok}@1dP=$waTnUxM&JY593A#mNXQu3N4e& zNm#AP(3D6sZlB3;jcN=MO=ulr)JEzS(@g=MWZJNI=S7oj1~SE{&5{k}jF3&@h)07s zX;m94l6H5BLcVo931BgmDqA2iecQ$2e=YqaH>@Ti`$z| zZcQnHldMQX1g^g8I#x0qlJV{w-x!t~r^FJCpFFvGdQEi=Eqkd`yDWOgN9#g-OcrZv zX{=lng7HF-mrB)`C18COQE7Kw`HB4w;c$nb!K0)pXx9vOB-i3%LZrEVN+jAuClb?J zq7hzrS4Y)3FqKbKM-OzsOzcQUxZZi_O!mN*fR$NYqzTRiM?GOozTsxljP;yaG$t5h z%swu}IvJMJOdd=PJ?A1hDvp^oVZ!*C^J=Q+jCbtQ*h`Wrs8k8M$si8IC;9PRb0gty zOp=TrVUkE3RrBJNB%A{=ie|vVR#G)k^kD%G1!N1w?L;wTHz^Q5E6@tm9S1%iu#Xe9 zHtBb?YHq%ShUiwW#1h*Im#NJrZg{cj+4~z_e#lKE2dU0j_|hpQw|{k1&gPY&=9XsK ziNQ<3LhM@t6jW=NIMZImIQ7UZ*z9OaA;(n%PJBhI#jy;hEnhY6&eJ0a_V#Bcjz(~M zxlA9XlPQ;By8zpUSw+j_f<~=tG#{2EkL76{$A_0?Smro_i3){d4TKbRp>|C6@%1vb ziyT>TURO+RDAXpJ=x{vL#2X$uD4)`fTkMz}T26}_7$29?LkRW|AwhkYMssI|<(Ur8 zd?X?&7lrE<%ZxDA)oA8u*`!oXdy~ltBwIDW0h7I8kWsaS{)V>_Ogi2r_d~< zp0{oY(8clQskArHT#JeARqoj5~%(KIG zPe|{NQ<_$NBMsW@JfrfSi!%xtansqi-5{+t2MD29YImf{88xqJHCvr82ofB{kq}7hjK7^GKe1~Nsj%4{BD$mDQkidH5$z*$k8u@&L z1_YhXfN6JM0>84NcKpO?Gponf$blknSG6TFl*(IS{QR!uBIhhEx~lIl53ZNk-Z*_uZ(3Y#c^c_3wegreep3y zs20b@Vfe76Ex7BJaI2MKE7VbbVj4(eaiAW*=#~biK=+by*my9_-L)QEqpb~o8Rs;O z%PdCq@C{l0h^3u^AOEPqZaki*a&iqVC>tXo=L45^0vJ<6WMMmw^ij8X zB0HM=3av*FiJP@plpIj%pb@ogq55!BsBLj~&6O>!%i#7FIi9VvGliSLq2mD}cwyY^ zc zEMc(|AGpynbsHTHzn*Wj>t#Du^Y!(#7acwfx8IznDfWFkx`%={CeV$Y>BQq{oOIGMg0ZC;8eB}BDc5yM!PM(9B@_!m6$$|dD=bXOm@ z_FJhDMvf3Q=n>q=R833u<~4b9m=-HkC0dK)QBQG93)ZeEU8q&vp2B^f$t|ZLhtuS< zM>wORLw$@2Jgr|=$G7b9glshCcotWeY9c*Sn-CSn*%{rV;fWoUfh!X9tOENtwO<$E z_^ns_HY}|OpiOPG2u;Bahp9-3IaD8>bl^8kb#j)L^B>*!jkdP%BR_o1)4~(Iyhlo% z7R_UImW*ag>aX z!F**OT}}^&7vo6_GzM%eZh5UC+Ws_SxlDHoMNMNEorofk$K$n(J;&4Xp&n1c;5WWF zJ5c9nSmP`vX*FR|Ob6Y3=ChtDbSPc103%dxoa}uAOeBoTYrlcI!2wMUElYUzSK{NK z5~mR1#`((nxJc2lx%H_Od}c4!3B`DCmaH!1NT)hontFW>$KVyX&}eq zQEHAH%5)e`wA3@Vl)Y-ONa9n5C^Fr~na~)*B!F8(cnnFGQJpbB4VsZ31BCx}Zm8pa z1Iw10_SV*xHs?<<(Eb>C*i5ORMm_^~rx&(2hH$$Mr>*=fFYO@k(B3ru^+r^TJ*sY= zeZRgEH!h&kfw!Gh48yNkv1K_$&CP?1{%e0 zaz$1R=n`lQ<2QFPa9M5)?j!<7z$wFT_1eH~g2ZX8YcY5=c#{NH5K8`dPDMI|e=2k} zQeHXpAT=K4s)Vk|xX!|FqN#i~e-_H!C9Zb`>QDhWdWXe$t`$kwf>%pvJ@W-VlLqG2}>nQiPh&m0CHj6Hn7{P2+ka=&4r7g}KM5O^Udk+qtFaHgf4_NY1-8IKcdKyaatbYS?q@JorPj+vGBG{_5OIdfa zVsXgW1GHB>2i=4ITGWB9F=+y~8C$w{D#BBR@KVboR}YN~F|8K0p%!)4II*pppo^@m z2qRBQQqNVx9?2SLT#)@O;5HXM#sX6hP@BQp`cV0)_h>9p47CB(JEBINNRxJqr@6o* zdlrL;L#b$l(U>GVFG85Ewj9YWMBB+$iYV)lqgWIih+BlTXvH*o|H}g8gPYmF4e%{a zPLbsGpw^MrK;uUYw8wQ~+fdI@-Ka&wcz*!;?TEN!D|EE*C}@M+GQ>J<_yB49AGqdS z%5sqQNtB}AT88$aa$y?@N@Y~7mNpjUN~oWgq*3~uBCbid6fVTM(4W04(NE3zCr2@r zmwGz{ZDbpw|If!$i$m(TpO+$glO-j)q_Hi1Y7ytsfSf2dOo*T~PCB@a$yT_pDt=zO zEW^+0%v;DgP!CaFWI2nt-eTy%V#sbtvfHT5AUnoG3QjG9y7La2entgS$`-cgC(4ED zEWJFnl^h{WC?oZv-8*u;cAX1E@?@l^(L=QoNtH-VBNDSmk149GA;h9>dsc(rj8Gd! zdk42Sjcl189^v6Ov2&|qPf~~9u*+VPw#w&Lz)|qLiUQBgNk5*2a=bTEVYW>PONGFYh$WlDV~1=r6r%BD_YsXd+46}ij04-A@D9T7!b^ow5P{{8 zMbJu(Y>c!}FT1qS;%vbQwaJ*Fr z>r~-xcG6wXfy(C0i%aM^39lCtp1F8&647#|A*KtMVle}LGgBAaS=Krw|-JV?fY$M>-U8NaWZ^sYcv>bB2ZOa@7D9{h*Mc!X&Wa{vvRPV2+D=G1FdDSo^A>(PRvdW@ z(#j#-JtwM9;?k8SeYs$bpf)0droQ;{r4~puO+`thE0r$5xn%3Uxu8~~ZCqTBy%e@5 z^aIC^#fA>csnWy|Bkj?iP|0c03k+?IKQB!#HjH-F(wOq3jTQ;oq>%;nMQQbBE=Mj5 zY!9a0bXMGjQ=cp6?SiFv*j@@~6D`}E>;-4eYTChayrPyD0bR$Lvkh$~{#`di!cW_DvPs&8$WVN^ST+@QGNR%j>9IPyIAZmu6 z6LAZW)xbX-Vjtbma*D=3S%5s4iQwgI+P+a+r{uxpP>w!0_D9SAjIMrT(M}}uGg@+N z8zsLNU)G5uDlh^Ld`!{R|B$6nU)YNyG0@g&+j3lQ7s-CoQ`kOMF3q}Zh6g6fP)_6( zOgBF zI;Zu2h(h8(| zNoeFsKNl|rO4UR&PS=@_#)7>e>pp{ZpADsEIUCFQk`6ZFeXi$9eByk2V6D;<(}<#DSh+#MflIROjroWM zbCNvjv{wks&FRXeQG_*6Z}KCwk)W-J?JsDhLjB)_BiIASQ=5o+6`YoQ4julE=Ted1 zrdmf~L)16;H6qte9)if8m2K%<896n{Ei=5^5+}C|N4;T`i*lneNS5{*`t7>zeN4-pkj5NmR<^lO-Dv9vW23UB;GNnBLap0Z26VVQ%aO8%OfOUE~ z>`izk;`M>T1^Z?WT_@sTo_Mh7WYQ#C`4q=i+g{z#sHgswTkT^|miQi2ZMBo^^pNt~ z{Uws9RLUxPjzulvvlopH`)~tgPC7)%9U_b&%P@D-zfv6LOaZ0Wa2Mfqhm%l>Cj2`b znxbe6+F3RT!@nl)hsu^ePq^UDy@B~fFAo#G?aSvLpEqLnd8U=(E;5W196%cQOL3Km z6w~s#th8LWz<+Loh)D!*OBOCGeV_;O=>y$Gf=OB~VMvz{E)i+DkSX;PnMO(qQyH3MQHEO6N+w=%GGtwb&&SGq3<80G zjADskFbL&HR3zxnL?!?w042gStwPf>DNEBrKIsEf+*VJjhyX<)3<5|X>y|bK5$P+p zxvlh7V<}c&c0z@TLKt1;m+RNkPVu8o)km4uE`rKC9$~_)|9EYM+K&e!_xPV`Jp?T$(={h;#VxjrTkI?@fXc)u%%z@~kv@y8tT25B)ps0` zD(;R|wX#>X`H<0U6t{~RD5Eah%#E~;3%Snj_;t>X2e8M%s&(md9IOJ9#{p%A#5~k|KKK{vQg|4!H?q!+ zw$6=Cod87fpC7YGYDy|XUg7ppO30dpew3oHFck_Zl$>mbfCaFo2l8Cl{Xlz0iqcQw}DI~OFC8n|ekQ5WrVq%jTjrK3? zKN?JG_47UV&CaeYDf%z7?A{;eoqO)R=bn4+xtDX_%jeTX6p_ezraz=@E}9m(h=2$T zz~)u!q~n3fOnb~S?J+G#hY*3FdZc>9;=$^m#SDuSWf`@?(}t!3@oaV0Vg}P{G3iAP zC8cAmIn_ffW*HNq%i?mm9N3s%){uO4Zb+1Zj$cON7`6$eH9I7A%oC^4+ul5>Q$~ZV z#ibp&Vo%Y-hOqdUrp&}?P#wP2ijw*pr%~nDU1Z82x%MSYQI}?o~|^X z$!V@V$YLMy=fhV9iIAbsdpTC(5~9#Yo`_-e%M3Ppw0W9QvbY>G+ya1*=NU^S8HO`W zm5V%gKrrGZe&Dl;f>K!GXVPT3w8Ted3=C38;ec4p2+FE8Fv{({6f1ezYCmzcy%&^% zmzm4OUeHNXC&>YaLt8o-$fQZtPJKosPorEqVuD%9m9eLhl_9D5*-r_?mqAhO;)POu zG?7^CuBGj+S-Y((;-I=xGEk`q)~%K1G4k*Oc$&#W#3eVRq!wo>+Zphg#5EBeIhS~*9Te7-)H#hfxCva28x$h-m?$0?MApm8i{KA%EK2%66e zS}3GY5`q>A8hlM#;A*EO#T6x({U$$542vaBu7m2i#9}VXFwSLEQB56FITFeji)o&O zDn_Xp@f3=X3W|;cs)+^M*rucn5(#k(rOP85CsN`VkWA!7VUkL9(vj+MF&mFnTHR1eRS>fr@aO<|L2$OX>iGl4cGaH2Y8?QB#Btl`8qvCu>VwAjYHVI$md z0@1L3&@fb$2_$i~o|bKN$^x28QlQ8Xr~uGZoElDi8nv=!C$9ZZB z#brzvSklz}R%;Wsmo#5ilhkalC1!h>*4}CgFl(BwUuYO$3NKlB*}^Ldu|)*Gst{X5 z;WAN|0VcW_V9H^DDZ&6#gaM`q1B}QFFspjAWo3X_cB^G&fLWF=x_~SL%(COkngOO5 z1I${(f(jBAmm(}KMOa)y!QxVc#ia;~3ni6WTqt|`r|^=6mo2=akp2mNRU!RTxXj?J z)X+uo`Ss2MWDcBDaNfEzXoJaii!PtD@Vs^3EPEg; zfrH5kdBMWhY_+^#;cM#Dg=|)vV#s*eJ_UTPhE%2fn$bU!g=rZDw(~6tSed5hex><> zQ!dUrX>YccthL%VTe!A)g73k2*{0_`2hl$5zRB-=XhXxJQlEcsY$^O|&HdBIilcuy zKlXOv4__a7<%K6de=Pg2=a0WUI5YKj{@1_x+UvX4{qeh}e)6%UufDkc%^#K?+yB-{2gUuNR_xBYDAEsq>|X44y=-tv!EzS$@Rm%j7kHy(U-dgr^}y8G|J zm+s%bss40fcmEIaKl<$FZhxz>>#vzNUw`S@dw$#h$y2T)zq`}tj6$Dj7!OL^1U+!H zb1T^&5Ayfz--{PBp2|LK2-pe*Sb!Nm$-!Tll5}H{l8~BL60{39hPHS+7Et5!F5cLp z&0UC=4Ou@4D$8%Ie~f)l4peGT-Qqh<*D~aq8q5U1K148r>OkmGWu^H~$wDiS{>IQA zsJ1F`$bm~#!vNLsMJ+0kZ=b9limDAAj)YmJn4&m}gD}jMqNt>}7)8Z^w$PeI+OlA9 zZjdQH)Fkj9(lenoKOF7)l`d>sE(`*WaYDa#-Rc(<@EM6Hpj4d$AHwQDPzb}Q7LjL3 zg2>{dvw(<)?T7VHW=q4kqEOkya9-kN6&Z{jO{UD~undJEU}zV@jBHT-o{2)XsY>Jl zw$^b(K$FnQTP=J}Ve1h!ey4lO8BQl~-a ztkz&3<)%2&pRc<*_|se4<>KVMAzjF9~n0wraFQagxS0c02+5 zP;F^!?-MQM+gJ|6z&gsY;&)I(#Fp93$pa&>!@_ZeE!VHC(#`h`@@;#1hlSRV zwl$>f8sa+fd&7LkaJ(Yo(_T(-@eF~{0V{`^&ErT+y*evVnMGnSI}v0i2{|T-kQKE~ z@ZlqG8Sk9gH?ey%Im(^;*ykjP$KtCOxZPIpAItYB%`E#a8V|CWm?ICf>=RbK_pfMn!qxPvZWwk*Da8a zUf8#US>~W^&3z6$uyyU&gH5KkOqdKJTbYJ>sWKghxyp1&*lJZ!pfO@g7!q{BaX!q& z-E1B#*a;S47aW1bYLU{4FuVMyG7Z_NpdeO2A^J$gg*eX?hp!iPl-FX@R2^6XlLoX( zO)>D*0mfbkmrNGNv>G1bRJ_v4Ves&a43fqyHBc*;KI3sKSJo=W`qx775!kYZ-b2q# z(F(SF8lobHyr#%FsAjK<#?4uF(DV*EI?y1SrUQa5QiVqpHeax6(`FzYlOjEdqEV~BrFCQ&c4~y z1ocdWjqDMcMNrQ;U1Z{}Qy;jDxYH`wX39A2ld*NQTxlIM1v?s`{x~s40XwbQW-hb2 zo2)^g#z~?i^*9_6FUrRG_HvDwwpBE$(t1%N&@UovD*NFkELsE4)Ga~Qv6Gla8g@1%CWI&XPY6vpwk7ovJ__*)gx}Y?7+T6P$yXy-V)UDq1b&=jR zW$bdF)pv{U#VI*#c8_JFFOrF=sne*21=D)~I@67LQkJzN@#1JRKzAB%)-LnCTZV={ z!>_x)f0+Bg94N@@WD{E$8Co+mI@B1xd-YmR24DXJydma^Wa@A-kudV^bp^?RM-zh& z9pIk0*L)fK@uj&p79=Y-4kRPP!y|(PqlvCz?wguScIe{xP$^y~m2~opqgJ>aZu^=M&=1 zc<_;jXC@BvUf;QUo$gKfuY}Od^2TCWFye4>W9-e#1yGmy6-M4QWLgn7LKRIdN z2-DMlukeyFhjvqj`eG}l7}B+{`%a_b=6elXc$@kA3j3W?S>@c%sqAVJyKpghgz$^F zNj!w3#CF^m9wB}J*M;qd_{;3yKG6P_m6vZEa&Df+Ur6bQq;~c5f9@sYLsc$in{b+t z3?p55W8l$?y@q{G{W&B-CXD`JFBXE7%&cD^TPQe45 zmSf;uSKIx#7tFa}@O=Jxj2tv@VA!l>2`5> ze+D{Rp&^GjzMh9W%0c?5*6RD^IIS!KOK_>&$hUSATtURK5u7btY82Q;%4xiGmqso& zJD}-Y&W89daQr{fTTS^bY3t<-^)P%$=%?<*>bsRQgmMgLS~3 zZvZMM9JyI1xb*1hE}qFb%ejc_F6NE4Z+Nc1BhcAFz3vN|2gz-OrfwBJmQqvAYSB)E ziKFU=JCM`Jxx2EcO0Yh)U@V+e%k^K*PwFX)CO=)7lWVT1$%#oWGIHGRVmrq)aZAov za>5+49!o}dnEY&~j9My}HjREqW|cFCI^Z`ZN2@%n5U7fudnhBvrmi&3Z?osEGnrqA z``?m(J-HvVvK@Cexk9^}L^oRA7}yJX9O!YN$AKOPdK~C+pvQq82YMX1894BskM+zk uRA<9|GxWLF#~ufI9O!YN$AKOPdK~C+pvQq82YMXnaiGV69tUnR4*UnB-c@}7 literal 0 HcmV?d00001 diff --git a/src/Libraries/ICSharpCode.Decompiler/Tests/packages.config b/src/Libraries/ICSharpCode.Decompiler/Tests/packages.config new file mode 100644 index 0000000000..4d992b4245 --- /dev/null +++ b/src/Libraries/ICSharpCode.Decompiler/Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/.gitignore b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs index 1660e99b14..bfaaf11f52 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs @@ -143,7 +143,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis Dictionary labels; List gotoStatements; - public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken)) + public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context) + { + return BuildControlFlowGraph(statement, context, CancellationToken.None); + } + + public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken) { return BuildControlFlowGraph(statement, new ResolveVisitor( new CSharpResolver(context, cancellationToken), diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs index d4cc6e1c53..edef14f633 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs @@ -79,12 +79,22 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis Queue nodesWithModifiedInput = new Queue(); - public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken = default(CancellationToken)) + public DefiniteAssignmentAnalysis(Statement rootStatement) + : this(rootStatement, null, CancellationToken.None) + { + } + + public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken) : this(rootStatement, null, cancellationToken) { } - public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken)) + public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context) + : this(rootStatement, context, CancellationToken.None) + { + } + + public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken) : this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken), null, ConstantModeResolveVisitorNavigator.Skip)) { @@ -167,12 +177,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis /// This method can be used to restrict the analysis to only a part of the method. /// Only the control flow paths that are fully contained within the selected part will be analyzed. /// - /// Both 'start' and 'end' are inclusive. - public void SetAnalyzedRange(Statement start, Statement end) + /// By default, both 'start' and 'end' are inclusive. + public void SetAnalyzedRange(Statement start, Statement end, bool startInclusive = true, bool endInclusive = true) { - Debug.Assert(beginNodeDict.ContainsKey(start) && endNodeDict.ContainsKey(end)); - int startIndex = beginNodeDict[start].Index; - int endIndex = endNodeDict[end].Index; + var dictForStart = startInclusive ? beginNodeDict : endNodeDict; + var dictForEnd = endInclusive ? endNodeDict : beginNodeDict; + Debug.Assert(dictForStart.ContainsKey(start) && dictForEnd.ContainsKey(end)); + int startIndex = dictForStart[start].Index; + int endIndex = dictForEnd[end].Index; if (startIndex > endIndex) throw new ArgumentException("The start statement must be lexically preceding the end statement"); this.analyzedRangeStart = startIndex; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs index d9909d0d4d..64fc134935 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -14,7 +14,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis /// /// Resolve context represents the minimal mscorlib required for evaluating constants. /// - sealed class MinimalResolveContext : IProjectContent, ISynchronizedTypeResolveContext + sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext { static readonly Lazy instance = new Lazy(() => new MinimalResolveContext()); @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis }; } - public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { foreach (ITypeDefinition type in types) { if (nameComparer.Equals(type.Name, name) && nameComparer.Equals(type.Namespace, nameSpace) && type.TypeParameterCount == typeParameterCount) @@ -67,12 +67,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis return null; } - public IEnumerable GetClasses() + public IEnumerable GetTypes() { return types; } - public IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { return types.Where(t => nameComparer.Equals(t.Namespace, nameSpace)); } @@ -112,5 +112,16 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis { // exit from Synchronize() block } + + IParsedFile IProjectContent.GetFile(string fileName) + { + return null; + } + + IEnumerable IProjectContent.Files { + get { + return EmptyList.Instance; + } + } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs index 07927d1cd8..a535257ef1 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs @@ -23,7 +23,6 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; using System.Collections; using System.Collections.Generic; @@ -33,7 +32,7 @@ using System.Threading; namespace ICSharpCode.NRefactory.CSharp { - public abstract class AstNode : PatternMatching.INode + public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode { #region Null public static readonly AstNode Null = new NullAstNode (); @@ -57,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp return default (S); } - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } @@ -65,16 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region PatternPlaceholder - public static implicit operator AstNode(PatternMatching.Pattern pattern) + public static implicit operator AstNode (PatternMatching.Pattern pattern) { - return pattern != null ? new PatternPlaceholder(pattern) : null; + return pattern != null ? new PatternPlaceholder (pattern) : null; } sealed class PatternPlaceholder : AstNode, PatternMatching.INode { readonly PatternMatching.Pattern child; - public PatternPlaceholder(PatternMatching.Pattern child) + public PatternPlaceholder (PatternMatching.Pattern child) { this.child = child; } @@ -83,19 +82,19 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data) { - return visitor.VisitPatternPlaceholder(this, child, data); + return visitor.VisitPatternPlaceholder (this, child, data); } - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) { - return child.DoMatch(other, match); + return child.DoMatch (other, match); } - bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { - return child.DoMatchCollection(role, pos, match, backtrackingInfo); + return child.DoMatchCollection (role, pos, match, backtrackingInfo); } } #endregion @@ -163,7 +162,7 @@ namespace ICSharpCode.NRefactory.CSharp get { AstNode next; for (AstNode cur = firstChild; cur != null; cur = next) { - Debug.Assert(cur.parent == this); + Debug.Assert (cur.parent == this); // Remember next before yielding cur. // This allows removing/replacing nodes while iterating through the list. next = cur.nextSibling; @@ -188,7 +187,7 @@ namespace ICSharpCode.NRefactory.CSharp /// public IEnumerable Descendants { get { - return Utils.TreeTraversal.PreOrder(this.Children, n => n.Children); + return Utils.TreeTraversal.PreOrder (this.Children, n => n.Children); } } @@ -197,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp ///
public IEnumerable DescendantsAndSelf { get { - return Utils.TreeTraversal.PreOrder(this, n => n.Children); + return Utils.TreeTraversal.PreOrder (this, n => n.Children); } } @@ -205,10 +204,10 @@ namespace ICSharpCode.NRefactory.CSharp /// Gets the first child with the specified role. /// Returns the role's null object if the child is not found. ///
- public T GetChildByRole(Role role) where T : AstNode + public T GetChildByRole (Role role) where T : AstNode { if (role == null) - throw new ArgumentNullException("role"); + throw new ArgumentNullException ("role"); for (var cur = firstChild; cur != null; cur = cur.nextSibling) { if (cur.role == role) return (T)cur; @@ -216,37 +215,37 @@ namespace ICSharpCode.NRefactory.CSharp return role.NullObject; } - public AstNodeCollection GetChildrenByRole(Role role) where T : AstNode + public AstNodeCollection GetChildrenByRole (Role role) where T : AstNode { - return new AstNodeCollection(this, role); + return new AstNodeCollection (this, role); } - protected void SetChildByRole(Role role, T newChild) where T : AstNode + protected void SetChildByRole (Role role, T newChild) where T : AstNode { - AstNode oldChild = GetChildByRole(role); + AstNode oldChild = GetChildByRole (role); if (oldChild.IsNull) - AddChild(newChild, role); + AddChild (newChild, role); else - oldChild.ReplaceWith(newChild); + oldChild.ReplaceWith (newChild); } - public void AddChild(T child, Role role) where T : AstNode + public void AddChild (T child, Role role) where T : AstNode { if (role == null) - throw new ArgumentNullException("role"); + throw new ArgumentNullException ("role"); if (child == null || child.IsNull) return; if (this.IsNull) - throw new InvalidOperationException("Cannot add children to null nodes"); + throw new InvalidOperationException ("Cannot add children to null nodes"); if (child.parent != null) throw new ArgumentException ("Node is already used in another tree.", "child"); - AddChildUnsafe(child, role); + AddChildUnsafe (child, role); } /// /// Adds a child without performing any safety checks. /// - void AddChildUnsafe(AstNode child, Role role) + void AddChildUnsafe (AstNode child, Role role) { child.parent = this; child.role = role; @@ -259,12 +258,12 @@ namespace ICSharpCode.NRefactory.CSharp } } - public void InsertChildBefore(AstNode nextSibling, T child, Role role) where T : AstNode + public void InsertChildBefore (AstNode nextSibling, T child, Role role) where T : AstNode { if (role == null) - throw new ArgumentNullException("role"); + throw new ArgumentNullException ("role"); if (nextSibling == null || nextSibling.IsNull) { - AddChild(child, role); + AddChild (child, role); return; } @@ -276,11 +275,10 @@ namespace ICSharpCode.NRefactory.CSharp throw new ArgumentException ("NextSibling is not a child of this node.", "nextSibling"); // No need to test for "Cannot add children to null nodes", // as there isn't any valid nextSibling in null nodes. - InsertChildBeforeUnsafe(nextSibling, child, role); + InsertChildBeforeUnsafe (nextSibling, child, role); } - - void InsertChildBeforeUnsafe(AstNode nextSibling, AstNode child, Role role) + void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role) { child.parent = this; child.role = role; @@ -288,38 +286,38 @@ namespace ICSharpCode.NRefactory.CSharp child.prevSibling = nextSibling.prevSibling; if (nextSibling.prevSibling != null) { - Debug.Assert(nextSibling.prevSibling.nextSibling == nextSibling); + Debug.Assert (nextSibling.prevSibling.nextSibling == nextSibling); nextSibling.prevSibling.nextSibling = child; } else { - Debug.Assert(firstChild == nextSibling); + Debug.Assert (firstChild == nextSibling); firstChild = child; } nextSibling.prevSibling = child; } - public void InsertChildAfter(AstNode prevSibling, T child, Role role) where T : AstNode + public void InsertChildAfter (AstNode prevSibling, T child, Role role) where T : AstNode { - InsertChildBefore((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role); + InsertChildBefore ((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role); } /// /// Removes this node from its parent. /// - public void Remove() + public void Remove () { if (parent != null) { if (prevSibling != null) { - Debug.Assert(prevSibling.nextSibling == this); + Debug.Assert (prevSibling.nextSibling == this); prevSibling.nextSibling = nextSibling; } else { - Debug.Assert(parent.firstChild == this); + Debug.Assert (parent.firstChild == this); parent.firstChild = nextSibling; } if (nextSibling != null) { - Debug.Assert(nextSibling.prevSibling == this); + Debug.Assert (nextSibling.prevSibling == this); nextSibling.prevSibling = prevSibling; } else { - Debug.Assert(parent.lastChild == this); + Debug.Assert (parent.lastChild == this); parent.lastChild = prevSibling; } parent = null; @@ -332,28 +330,28 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Replaces this node with the new node. /// - public void ReplaceWith(AstNode newNode) + public void ReplaceWith (AstNode newNode) { if (newNode == null || newNode.IsNull) { - Remove(); + Remove (); return; } if (newNode == this) return; // nothing to do... if (parent == null) { - throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); } // Because this method doesn't statically check the new node's type with the role, // we perform a runtime test: - if (!role.IsValid(newNode)) { - throw new ArgumentException (string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), "newNode"); + if (!role.IsValid (newNode)) { + throw new ArgumentException (string.Format ("The new node '{0}' is not valid in the role {1}", newNode.GetType ().Name, role.ToString ()), "newNode"); } if (newNode.parent != null) { // newNode is used within this tree? - if (newNode.Ancestors.Contains(this)) { + if (newNode.Ancestors.Contains (this)) { // e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);" // enable automatic removal - newNode.Remove(); + newNode.Remove (); } else { throw new ArgumentException ("Node is already used in another tree.", "newNode"); } @@ -365,17 +363,17 @@ namespace ICSharpCode.NRefactory.CSharp newNode.nextSibling = nextSibling; if (parent != null) { if (prevSibling != null) { - Debug.Assert(prevSibling.nextSibling == this); + Debug.Assert (prevSibling.nextSibling == this); prevSibling.nextSibling = newNode; } else { - Debug.Assert(parent.firstChild == this); + Debug.Assert (parent.firstChild == this); parent.firstChild = newNode; } if (nextSibling != null) { - Debug.Assert(nextSibling.prevSibling == this); + Debug.Assert (nextSibling.prevSibling == this); nextSibling.prevSibling = newNode; } else { - Debug.Assert(parent.lastChild == this); + Debug.Assert (parent.lastChild == this); parent.lastChild = newNode; } parent = null; @@ -385,31 +383,31 @@ namespace ICSharpCode.NRefactory.CSharp } } - public AstNode ReplaceWith(Func replaceFunction) + public AstNode ReplaceWith (Func replaceFunction) { if (replaceFunction == null) - throw new ArgumentNullException("replaceFunction"); + throw new ArgumentNullException ("replaceFunction"); if (parent == null) { - throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); } AstNode oldParent = parent; AstNode oldSuccessor = nextSibling; Role oldRole = role; - Remove(); - AstNode replacement = replaceFunction(this); + Remove (); + AstNode replacement = replaceFunction (this); if (oldSuccessor != null && oldSuccessor.parent != oldParent) - throw new InvalidOperationException("replace function changed nextSibling of node being replaced?"); + throw new InvalidOperationException ("replace function changed nextSibling of node being replaced?"); if (!(replacement == null || replacement.IsNull)) { if (replacement.parent != null) - throw new InvalidOperationException("replace function must return the root of a tree"); - if (!oldRole.IsValid(replacement)) { - throw new InvalidOperationException (string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString())); + throw new InvalidOperationException ("replace function must return the root of a tree"); + if (!oldRole.IsValid (replacement)) { + throw new InvalidOperationException (string.Format ("The new node '{0}' is not valid in the role {1}", replacement.GetType ().Name, oldRole.ToString ())); } if (oldSuccessor != null) - oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldRole); + oldParent.InsertChildBeforeUnsafe (oldSuccessor, replacement, oldRole); else - oldParent.AddChildUnsafe(replacement, oldRole); + oldParent.AddChildUnsafe (replacement, oldRole); } return replacement; } @@ -418,9 +416,9 @@ namespace ICSharpCode.NRefactory.CSharp /// Clones the whole subtree starting at this AST node. /// /// Annotations are copied over to the new nodes; and any annotations implementing ICloneable will be cloned. - public AstNode Clone() + public AstNode Clone () { - AstNode copy = (AstNode)MemberwiseClone(); + AstNode copy = (AstNode)MemberwiseClone (); // First, reset the shallow pointer copies copy.parent = null; copy.role = Roles.Root; @@ -431,7 +429,7 @@ namespace ICSharpCode.NRefactory.CSharp // Then perform a deep copy: for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) { - copy.AddChildUnsafe(cur.Clone(), cur.role); + copy.AddChildUnsafe (cur.Clone (), cur.role); } // Finally, clone the annotation, if necessary @@ -442,175 +440,24 @@ namespace ICSharpCode.NRefactory.CSharp return copy; } - #region Annotation support - // Annotations: points either null (no annotations), to the single annotation, - // or to an AnnotationList. - // Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list) - object annotations; - - sealed class AnnotationList : List, ICloneable - { - // There are two uses for this custom list type: - // 1) it's private, and thus (unlike List) cannot be confused with real annotations - // 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation. - public AnnotationList(int initialCapacity) : base(initialCapacity) - { - } - - public object Clone() - { - lock (this) { - AnnotationList copy = new AnnotationList(this.Count); - for (int i = 0; i < this.Count; i++) { - object obj = this[i]; - ICloneable c = obj as ICloneable; - copy.Add(c != null ? c.Clone() : obj); - } - return copy; - } - } - } - - public void AddAnnotation(object annotation) - { - if (annotation == null) - throw new ArgumentNullException("annotation"); - if (this.IsNull) - throw new InvalidOperationException("Cannot add annotations to the null node"); - retry: // Retry until successful - object oldAnnotation = Interlocked.CompareExchange(ref this.annotations, annotation, null); - if (oldAnnotation == null) { - return; // we successfully added a single annotation - } - AnnotationList list = oldAnnotation as AnnotationList; - if (list == null) { - // we need to transform the old annotation into a list - list = new AnnotationList(4); - list.Add(oldAnnotation); - list.Add(annotation); - if (Interlocked.CompareExchange(ref this.annotations, list, oldAnnotation) != oldAnnotation) { - // the transformation failed (some other thread wrote to this.annotations first) - goto retry; - } - } else { - // once there's a list, use simple locking - lock (list) { - list.Add(annotation); - } - } - } - - public void RemoveAnnotations() where T : class - { - retry: // Retry until successful - object oldAnnotations = this.annotations; - AnnotationList list = oldAnnotations as AnnotationList; - if (list != null) { - lock (list) - list.RemoveAll(obj => obj is T); - } else if (oldAnnotations is T) { - if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) { - // Operation failed (some other thread wrote to this.annotations first) - goto retry; - } - } - } - - public void RemoveAnnotations(Type type) - { - if (type == null) - throw new ArgumentNullException("type"); - retry: // Retry until successful - object oldAnnotations = this.annotations; - AnnotationList list = oldAnnotations as AnnotationList; - if (list != null) { - lock (list) - list.RemoveAll(obj => type.IsInstanceOfType(obj)); - } else if (type.IsInstanceOfType(oldAnnotations)) { - if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) { - // Operation failed (some other thread wrote to this.annotations first) - goto retry; - } - } - } - - public T Annotation() where T: class - { - object annotations = this.annotations; - AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { - foreach (object obj in list) { - T t = obj as T; - if (t != null) - return t; - } - return null; - } - } else { - return annotations as T; - } - } - - public object Annotation(Type type) - { - if (type == null) - throw new ArgumentNullException("type"); - object annotations = this.annotations; - AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { - foreach (object obj in list) { - if (type.IsInstanceOfType(obj)) - return obj; - } - } - } else { - if (type.IsInstanceOfType(annotations)) - return annotations; - } - return null; - } - - /// - /// Gets all annotations stored on this AstNode. - /// - public IEnumerable Annotations { - get { - object annotations = this.annotations; - AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { - return list.ToArray(); - } - } else { - if (annotations != null) - return new object[] { annotations }; - else - return Enumerable.Empty(); - } - } - } - #endregion - public abstract S AcceptVisitor (IAstVisitor visitor, T data); #region Pattern Matching - protected static bool MatchString(string name1, string name2) + protected static bool MatchString (string name1, string name2) { - return string.IsNullOrEmpty(name1) || name1 == name2; + return string.IsNullOrEmpty (name1) || name1 == name2; } - protected internal abstract bool DoMatch(AstNode other, PatternMatching.Match match); + protected internal abstract bool DoMatch (AstNode other, PatternMatching.Match match); - bool PatternMatching.INode.DoMatch(PatternMatching.INode other, PatternMatching.Match match) + bool PatternMatching.INode.DoMatch (PatternMatching.INode other, PatternMatching.Match match) { AstNode o = other as AstNode; // try matching if other is null, or if other is an AstNode - return (other == null || o != null) && DoMatch(o, match); + return (other == null || o != null) && DoMatch (o, match); } - bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { AstNode o = pos as AstNode; return (pos == null || o != null) && DoMatch (o, match); @@ -623,6 +470,7 @@ namespace ICSharpCode.NRefactory.CSharp PatternMatching.INode PatternMatching.INode.FirstChild { get { return firstChild; } } + #endregion public AstNode GetNextNode () @@ -655,8 +503,168 @@ namespace ICSharpCode.NRefactory.CSharp return null; } + public AstNode GetNodeAt (int line, int column) + { + return GetNodeAt (new AstLocation (line, column)); + } + + public AstNode GetNodeAt (AstLocation location, Predicate pred = null) + { + AstNode result = null; + AstNode node = this; + while (node.FirstChild != null) { + var child = node.FirstChild; + while (child != null) { + if (child.StartLocation <= location && location < child.EndLocation) { + if (pred == null || pred (child)) + result = child; + node = child; + break; + } + child = child.NextSibling; + } + // found no better child node - therefore the parent is the right one. + if (child == null) + break; + } + return result; + } + + public T GetNodeAt (int line, int column) where T : AstNode + { + return GetNodeAt (new AstLocation (line, column)); + } + + /// + /// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching + /// the current method declaration. + /// + public T GetNodeAt (AstLocation location) where T : AstNode + { + T result = null; + AstNode node = this; + while (node.FirstChild != null) { + var child = node.FirstChild; + while (child != null) { + if (child.StartLocation <= location && location < child.EndLocation) { + if (child is T) + result = (T)child; + node = child; + break; + } + child = child.NextSibling; + } + // found no better child node - therefore the parent is the right one. + if (child == null) + break; + } + return result; + } + + public AstNode GetResolveableNodeAt (int line, int column) + { + return GetResolveableNodeAt (new AstLocation (line, column)); + } + + /// + /// Gets a node that can be resolved at location. + /// + public AstNode GetResolveableNodeAt (AstLocation location) + { + return GetNodeAt (location, delegate (AstNode n) { + + if (n is TypeDeclaration) { + var decl = (TypeDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is DelegateDeclaration) { + var decl = (DelegateDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is MemberDeclaration) { + var decl = (MemberDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is ConstructorDeclaration) { + var decl = (ConstructorDeclaration)n; + return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; + } + + if (n is DestructorDeclaration) { + var decl = (DestructorDeclaration)n; + return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; + } + + if (n is VariableInitializer) { + var decl = (VariableInitializer)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is ParameterDeclaration) { + var decl = (ParameterDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is MemberReferenceExpression) { + var decl = (MemberReferenceExpression)n; + return decl.MemberNameToken.StartLocation <= location && location <= decl.MemberNameToken.EndLocation; + } + + return n is IdentifierExpression || n is AstType; + }); + } + + public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) + { + return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); + } + + public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + { + AstNode node = this; + while (node != null) { + AstNode next; + if (start <= node.StartLocation && node.EndLocation <= end) { + // Remember next before yielding node. + // This allows iteration to continue when the caller removes/replaces the node. + next = node.NextSibling; + yield return node; + } else { + if (node.EndLocation <= start) { + next = node.NextSibling; + } else { + next = node.FirstChild; + } + } + + if (next != null && next.StartLocation > end) + yield break; + node = next; + } + } + + public bool Contains (int line, int column) + { + return Contains (new AstLocation (line, column)); + } + + public bool Contains (AstLocation location) + { + return this.StartLocation <= location && location < this.EndLocation; + } + + public override void AddAnnotation (object annotation) + { + if (this.IsNull) + throw new InvalidOperationException ("Cannot add annotations to the null node"); + base.AddAnnotation (annotation); + } + // the Root role must be available when creating the null nodes, so we can't put it in the Roles class - static readonly Role RootRole = new Role("Root"); + static readonly Role RootRole = new Role ("Root"); public static class Roles { @@ -666,41 +674,38 @@ namespace ICSharpCode.NRefactory.CSharp public static readonly Role Root = RootRole; // some pre defined constants for common roles - public static readonly Role Identifier = new Role("Identifier", CSharp.Identifier.Null); - - public static readonly Role Body = new Role("Body", CSharp.BlockStatement.Null); - public static readonly Role Parameter = new Role("Parameter"); - public static readonly Role Argument = new Role("Argument", CSharp.Expression.Null); - public static readonly Role Type = new Role("Type", CSharp.AstType.Null); - public static readonly Role Expression = new Role("Expression", CSharp.Expression.Null); - public static readonly Role TargetExpression = new Role("Target", CSharp.Expression.Null); - public readonly static Role Condition = new Role("Condition", CSharp.Expression.Null); - - public static readonly Role TypeParameter = new Role("TypeParameter"); - public static readonly Role TypeArgument = new Role("TypeArgument", CSharp.AstType.Null); - public readonly static Role Constraint = new Role("Constraint"); - public static readonly Role Variable = new Role("Variable"); - public static readonly Role EmbeddedStatement = new Role("EmbeddedStatement", CSharp.Statement.Null); - - public static readonly Role Keyword = new Role("Keyword", CSharpTokenNode.Null); - public static readonly Role InKeyword = new Role("InKeyword", CSharpTokenNode.Null); + public static readonly Role Identifier = new Role ("Identifier", CSharp.Identifier.Null); + public static readonly Role Body = new Role ("Body", CSharp.BlockStatement.Null); + public static readonly Role Parameter = new Role ("Parameter"); + public static readonly Role Argument = new Role ("Argument", CSharp.Expression.Null); + public static readonly Role Type = new Role ("Type", CSharp.AstType.Null); + public static readonly Role Expression = new Role ("Expression", CSharp.Expression.Null); + public static readonly Role TargetExpression = new Role ("Target", CSharp.Expression.Null); + public readonly static Role Condition = new Role ("Condition", CSharp.Expression.Null); + public static readonly Role TypeParameter = new Role ("TypeParameter"); + public static readonly Role TypeArgument = new Role ("TypeArgument", CSharp.AstType.Null); + public readonly static Role Constraint = new Role ("Constraint"); + public static readonly Role Variable = new Role ("Variable"); + public static readonly Role EmbeddedStatement = new Role ("EmbeddedStatement", CSharp.Statement.Null); + public static readonly Role Keyword = new Role ("Keyword", CSharpTokenNode.Null); + public static readonly Role InKeyword = new Role ("InKeyword", CSharpTokenNode.Null); // some pre defined constants for most used punctuation - public static readonly Role LPar = new Role("LPar", CSharpTokenNode.Null); - public static readonly Role RPar = new Role("RPar", CSharpTokenNode.Null); - public static readonly Role LBracket = new Role("LBracket", CSharpTokenNode.Null); - public static readonly Role RBracket = new Role("RBracket", CSharpTokenNode.Null); - public static readonly Role LBrace = new Role("LBrace", CSharpTokenNode.Null); - public static readonly Role RBrace = new Role("RBrace", CSharpTokenNode.Null); - public static readonly Role LChevron = new Role("LChevron", CSharpTokenNode.Null); - public static readonly Role RChevron = new Role("RChevron", CSharpTokenNode.Null); - public static readonly Role Comma = new Role("Comma", CSharpTokenNode.Null); - public static readonly Role Dot = new Role("Dot", CSharpTokenNode.Null); - public static readonly Role Semicolon = new Role("Semicolon", CSharpTokenNode.Null); - public static readonly Role Assign = new Role("Assign", CSharpTokenNode.Null); - public static readonly Role Colon = new Role("Colon", CSharpTokenNode.Null); - - public static readonly Role Comment = new Role("Comment"); + public static readonly Role LPar = new Role ("LPar", CSharpTokenNode.Null); + public static readonly Role RPar = new Role ("RPar", CSharpTokenNode.Null); + public static readonly Role LBracket = new Role ("LBracket", CSharpTokenNode.Null); + public static readonly Role RBracket = new Role ("RBracket", CSharpTokenNode.Null); + public static readonly Role LBrace = new Role ("LBrace", CSharpTokenNode.Null); + public static readonly Role RBrace = new Role ("RBrace", CSharpTokenNode.Null); + public static readonly Role LChevron = new Role ("LChevron", CSharpTokenNode.Null); + public static readonly Role RChevron = new Role ("RChevron", CSharpTokenNode.Null); + public static readonly Role Comma = new Role ("Comma", CSharpTokenNode.Null); + public static readonly Role Dot = new Role ("Dot", CSharpTokenNode.Null); + public static readonly Role Semicolon = new Role ("Semicolon", CSharpTokenNode.Null); + public static readonly Role Assign = new Role ("Assign", CSharpTokenNode.Null); + public static readonly Role Colon = new Role ("Colon", CSharpTokenNode.Null); + public static readonly Role Comment = new Role ("Comment"); + public static readonly Role Error = new Role ("Error"); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs index a776f259f5..b125413d0f 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs @@ -1,4 +1,4 @@ -// +// // TokenNode.cs // // Author: @@ -27,7 +27,7 @@ using System; namespace ICSharpCode.NRefactory.CSharp { - public class CSharpTokenNode : AstNode + public class CSharpTokenNode : AstNode, IRelocatable { public static new readonly CSharpTokenNode Null = new NullCSharpTokenNode (); class NullCSharpTokenNode : CSharpTokenNode @@ -80,6 +80,13 @@ namespace ICSharpCode.NRefactory.CSharp this.tokenLength = tokenLength; } + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; + } + #endregion + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitCSharpTokenNode (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs new file mode 100644 index 0000000000..46f528d46b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs @@ -0,0 +1,95 @@ +// +// CSharpUtil.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.CSharp +{ + public static class CSharpUtil + { + public static Expression InvertCondition (Expression condition) + { + return InvertConditionInternal (condition.Clone ()); + } + + static Expression InvertConditionInternal (Expression condition) + { + if (condition is ParenthesizedExpression) { + ((ParenthesizedExpression)condition).Expression = InvertCondition (((ParenthesizedExpression)condition).Expression); + return condition; + } + + if (condition is UnaryOperatorExpression) { + var uOp = (UnaryOperatorExpression)condition; + if (uOp.Operator == UnaryOperatorType.Not) + return uOp.Expression; + return new UnaryOperatorExpression (UnaryOperatorType.Not, uOp); + } + + if (condition is BinaryOperatorExpression) { + var bOp = (BinaryOperatorExpression)condition; + switch (bOp.Operator) { + case BinaryOperatorType.GreaterThan: + bOp.Operator = BinaryOperatorType.LessThanOrEqual; + return bOp; + case BinaryOperatorType.GreaterThanOrEqual: + bOp.Operator = BinaryOperatorType.LessThan; + return bOp; + case BinaryOperatorType.Equality: + bOp.Operator = BinaryOperatorType.InEquality; + return bOp; + case BinaryOperatorType.InEquality: + bOp.Operator = BinaryOperatorType.Equality; + return bOp; + case BinaryOperatorType.LessThan: + bOp.Operator = BinaryOperatorType.GreaterThanOrEqual; + return bOp; + case BinaryOperatorType.LessThanOrEqual: + bOp.Operator = BinaryOperatorType.GreaterThan; + return bOp; + default: + return new UnaryOperatorExpression (UnaryOperatorType.Not, new ParenthesizedExpression (condition)); + } + } + + if (condition is ConditionalExpression) { + var cEx = condition as ConditionalExpression; + cEx.Condition = InvertCondition (cEx.Condition); + return cEx; + } + if (condition is PrimitiveExpression) { + var pex = condition as PrimitiveExpression; + if (pex.Value is bool) { + pex.Value = !((bool)pex.Value); + return pex; + } + } + + return new UnaryOperatorExpression (UnaryOperatorType.Not, condition); + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs index 9a50477191..889e8d048b 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp { @@ -38,67 +39,48 @@ namespace ICSharpCode.NRefactory.CSharp } } - public CompilationUnit () - { + List errors = new List (); + + public List Errors { + get { return errors; } } - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) - { - CompilationUnit o = other as CompilationUnit; - return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match); + /// + /// Gets the expression that was on top of the parse stack. + /// This is the only way to get an expression that isn't part of a statment. + /// (eg. when an error follows an expression). + /// + /// This is used for code completion to 'get the expression before a token - like ., <, ('. + /// + public AstNode TopExpression { + get; + internal set; } - public AstNode GetNodeAt (int line, int column) + public CompilationUnit () { - return GetNodeAt (new AstLocation (line, column)); } - public AstNode GetNodeAt (AstLocation location) + public IEnumerable GetTypes (bool includeInnerTypes = false) { - AstNode node = this; - while (node.FirstChild != null) { - var child = node.FirstChild; - while (child != null) { - if (child.StartLocation <= location && location < child.EndLocation) { - node = child; - break; - } - child = child.NextSibling; + Stack nodeStack = new Stack (); + nodeStack.Push (this); + while (nodeStack.Count > 0) { + var curNode = nodeStack.Pop (); + if (curNode is TypeDeclaration) + yield return (TypeDeclaration)curNode; + foreach (var child in curNode.Children) { + if (!(child is Statement || child is Expression) && + (child.Role != TypeDeclaration.MemberRole || (child is TypeDeclaration && includeInnerTypes))) + nodeStack.Push (child); } - // found no better child node - therefore the parent is the right one. - if (child == null) - break; } - return node; } - public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) - { - return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); - } - - public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { - AstNode node = this; - while (node != null) { - AstNode next; - if (start <= node.StartLocation && node.EndLocation <= end) { - // Remember next before yielding node. - // This allows iteration to continue when the caller removes/replaces the node. - next = node.NextSibling; - yield return node; - } else { - if (node.EndLocation < start) { - next = node.NextSibling; - } else { - next = node.FirstChild; - } - } - - if (next != null && next.StartLocation > end) - yield break; - node = next; - } + CompilationUnit o = other as CompilationUnit; + return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match); } public override S AcceptVisitor (IAstVisitor visitor, T data) diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs index b888cdea23..813f472137 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp public int PointerRank { get { - return GetChildrenByRole(PointerRole).Count(); + return GetChildrenByRole(PointerRole).Count; } set { if (value < 0) @@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp } public int Dimensions { - get { return 1 + GetChildrenByRole(Roles.Comma).Count(); } + get { return 1 + GetChildrenByRole(Roles.Comma).Count; } set { int d = this.Dimensions; while (d > value) { diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs new file mode 100644 index 0000000000..af2fed7506 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs @@ -0,0 +1,79 @@ +// +// ErrorNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin (http://www.xamarin.com); +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a parsing error in the ast. At the moment it only represents missing closing bracket. + /// This closing bracket is replaced by a node at the highest possible position. + /// (To make GetAstNodeAt (line, col) working). + /// + public class ErrorNode : AstNode + { + static AstLocation maxLoc = new AstLocation (int.MaxValue, int.MaxValue); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public override AstLocation StartLocation { + get { + return maxLoc; + } + } + + public override AstLocation EndLocation { + get { + return maxLoc; + } + } + + public ErrorNode () + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + // nothing + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as ErrorNode; + return o != null; + } + + public override string ToString () + { + return "[ErrorNode]"; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs index b057acbdf6..3c23f54f88 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Type<[EMPTY]> /// - public class EmptyExpression : Expression + public class EmptyExpression : Expression, IRelocatable { AstLocation location; @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp return location; } } - + public override AstLocation EndLocation { get { return location; @@ -54,7 +54,14 @@ namespace ICSharpCode.NRefactory.CSharp { this.location = location; } - + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.location = startLocation; + } + #endregion + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitEmptyExpression (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs index bbc6898c1d..e982f13201 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp public IdentifierExpression(string identifier, AstLocation location) { - SetChildByRole(Roles.Identifier, new Identifier(identifier, location)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (identifier, location)); } // public Identifier IdentifierToken { @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs index 60d7a17edc..4a7decbe0e 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs @@ -1,4 +1,4 @@ -// +// // MemberReferenceExpression.cs // // Author: @@ -43,7 +43,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier MemberNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs index df51dcf937..73bcb2e274 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs @@ -15,7 +15,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs index 3ac10d3874..21e805b671 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs @@ -1,4 +1,4 @@ -// +// // PointerReferenceExpression.cs // // Author: @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs index cc4fbe1c04..22e16e29ba 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Represents a literal value. /// - public class PrimitiveExpression : Expression + public class PrimitiveExpression : Expression, IRelocatable { public static readonly object AnyValue = new object(); @@ -40,16 +40,22 @@ namespace ICSharpCode.NRefactory.CSharp } } - int length; + string literalValue; public override AstLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + length); + return new AstLocation (StartLocation.Line, StartLocation.Column + literalValue.Length); } } public object Value { get; - private set; + set; + } + + public string LiteralValue { + get { + return literalValue; + } } public PrimitiveExpression (object value) @@ -57,12 +63,25 @@ namespace ICSharpCode.NRefactory.CSharp this.Value = value; } - public PrimitiveExpression (object value, AstLocation startLocation, int length) + public PrimitiveExpression (object value, string literalValue) + { + this.Value = value; + this.literalValue = literalValue ?? ""; + } + + public PrimitiveExpression (object value, AstLocation startLocation, string literalValue) { this.Value = value; this.startLocation = startLocation; - this.length = length; + this.literalValue = literalValue ?? ""; + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; } + #endregion public override S AcceptVisitor (IAstVisitor visitor, T data) { diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs index 9841a74685..5cf8877030 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs @@ -89,7 +89,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); } } @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); } } @@ -153,7 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); } } @@ -237,7 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole(JoinIdentifierRole).Name; } set { - SetChildByRole(JoinIdentifierRole, new Identifier(value, AstLocation.Empty)); + SetChildByRole(JoinIdentifierRole, Identifier.Create (value, AstLocation.Empty)); } } @@ -277,7 +277,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (IntoIdentifierRole).Name; } set { - SetChildByRole(IntoIdentifierRole, new Identifier(value, AstLocation.Empty)); + SetChildByRole(IntoIdentifierRole, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs index 877771736a..95235527f3 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs @@ -47,16 +47,31 @@ namespace ICSharpCode.NRefactory.CSharp public AstNodeCollection Arguments { get { return base.GetChildrenByRole (Roles.Argument); } } - + + // HasArgumentList == false: [Empty] + public bool HasArgumentList { + get; + set; + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitAttribute (this, data); } - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) { Attribute o = other as Attribute; - return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match); + return o != null && this.Type.DoMatch (o.Type, match) && this.Arguments.DoMatch (o.Arguments, match); + } + + public override string ToString () + { + if (IsNull) + return "Null"; + var w = new System.IO.StringWriter (); + AcceptVisitor (new OutputVisitor (w, new CSharpFormattingOptions ()), null); + return w.ToString (); } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs index 4f757b2640..61b424f491 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs @@ -1,4 +1,4 @@ -// +// // Comment.cs // // Author: @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp Documentation } - public class Comment : AstNode + public class Comment : AstNode, IRelocatable { public override NodeType NodeType { get { @@ -81,6 +81,15 @@ namespace ICSharpCode.NRefactory.CSharp this.startLocation = startLocation; this.endLocation = endLocation; } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + int lineDelta = startLocation.Line - this.startLocation.Line; + endLocation = new AstLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column); + this.startLocation = startLocation; + } + #endregion public override S AcceptVisitor (IAstVisitor visitor, T data) { diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs index 8bac245c76..48c4e0ecb4 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs @@ -1,4 +1,4 @@ -// +// // Constraint.cs // // Author: @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs index e014a4b3f8..c33c0bf246 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs @@ -1,4 +1,4 @@ -// +// // DelegateDeclaration.cs // // Author: @@ -50,7 +50,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs index bdd8c0f043..7d9a33df4f 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs index 07dee45b76..c580f3790c 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs @@ -1,4 +1,4 @@ -// +// // NamespaceDeclaration.cs // // Author: @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp return builder.ToString (); } set { - GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier(ident, AstLocation.Empty))); + GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident, AstLocation.Empty))); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs index df7ac21388..945c936cd6 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs @@ -1,4 +1,4 @@ -// +// // TypeDeclaration.cs // // Author: @@ -55,7 +55,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs index 84c9b2f507..ee2d58eb37 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs @@ -35,7 +35,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs index a157ce62fc..7fd3dfa096 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs @@ -1,4 +1,4 @@ -// +// // UsingAliasDeclaration.cs // // Author: @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (AliasRole).Name; } set { - SetChildByRole(AliasRole, new Identifier(value, AstLocation.Empty)); + SetChildByRole(AliasRole, Identifier.Create (value, AstLocation.Empty)); } } @@ -72,13 +72,13 @@ namespace ICSharpCode.NRefactory.CSharp public UsingAliasDeclaration (string alias, string nameSpace) { - AddChild (new Identifier (alias, AstLocation.Empty), AliasRole); + AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); AddChild (new SimpleType (nameSpace), ImportRole); } public UsingAliasDeclaration (string alias, AstType import) { - AddChild (new Identifier (alias, AstLocation.Empty), AliasRole); + AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); AddChild (import, ImportRole); } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs new file mode 100644 index 0000000000..48205191fc --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs @@ -0,0 +1,35 @@ +// +// IRelocationable.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + public interface IRelocatable + { + void SetStartLocation (AstLocation startLocation); + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs index 09639ab0b7..12bd644752 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs @@ -1,4 +1,4 @@ -// +// // Identifier.cs // // Author: @@ -28,9 +28,9 @@ using System; namespace ICSharpCode.NRefactory.CSharp { - public class Identifier : AstNode + public class Identifier : AstNode, IRelocatable { - public static readonly new Identifier Null = new NullIdentifier (); + public static readonly Identifier Null = new NullIdentifier (); class NullIdentifier : Identifier { public override bool IsNull { @@ -66,37 +66,69 @@ namespace ICSharpCode.NRefactory.CSharp } } - public bool IsQuoted { - get; - set; - } - AstLocation startLocation; public override AstLocation StartLocation { get { return startLocation; } + + } + + public virtual bool IsVerbatim { + get { + return false; + } + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; } + #endregion public override AstLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + (IsQuoted ? 1 : 0)); + return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length); } } - private Identifier () + Identifier () { this.name = string.Empty; } - public Identifier (string name, AstLocation location) + protected Identifier (string name, AstLocation location) { if (name == null) throw new ArgumentNullException("name"); - IsQuoted = name.StartsWith ("@"); - this.Name = IsQuoted ? name.Substring (1) : name; + this.Name = name; this.startLocation = location; } + + public static Identifier Create (string name) + { + return Create (name, AstLocation.Empty); + } + + public static Identifier Create (string name, AstLocation location) + { + if (name == null) + throw new ArgumentNullException("name"); + if (name.Length > 0 && name[0] == '@') + return new VerbatimIdentifier(name.Substring (1), location); + return new Identifier (name, location); + } + + public static Identifier Create (string name, AstLocation location, bool isVerbatim) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (isVerbatim) + return new VerbatimIdentifier(name, location); + return new Identifier (name, location); + } public override S AcceptVisitor (IAstVisitor visitor, T data) { @@ -108,5 +140,24 @@ namespace ICSharpCode.NRefactory.CSharp Identifier o = other as Identifier; return o != null && !o.IsNull && MatchString(this.Name, o.Name); } + + class VerbatimIdentifier : Identifier + { + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..." + } + } + + public override bool IsVerbatim { + get { + return true; + } + } + + public VerbatimIdentifier(string name, AstLocation location) : base (name, location) + { + } + } } -} +} \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs index b91048a5c9..771623eac5 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs @@ -1,4 +1,4 @@ -// +// // FullTypeName.cs // // Author: @@ -47,7 +47,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier MemberNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } @@ -55,6 +64,29 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.TypeArgument); } } + public MemberType () + { + } + + public MemberType (AstType target, string memberName) + { + this.Target = target; + this.MemberName = memberName; + } + + public MemberType (AstType target, string memberName, IEnumerable typeArguments) + { + this.Target = target; + this.MemberName = memberName; + foreach (var arg in typeArguments) { + AddChild (arg, Roles.TypeArgument); + } + } + + public MemberType (AstType target, string memberName, params AstType[] typeArguments) : this (target, memberName, (IEnumerable)typeArguments) + { + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitMemberType (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/NotImplementedAstVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/NotImplementedAstVisitor.cs new file mode 100644 index 0000000000..cb8115be8e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/NotImplementedAstVisitor.cs @@ -0,0 +1,560 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class NotImplementedAstVisitor : IAstVisitor + { + public virtual S VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitAsExpression(AsExpression asExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitAssignmentExpression(AssignmentExpression assignmentExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCastExpression(CastExpression castExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCheckedExpression(CheckedExpression checkedExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitConditionalExpression(ConditionalExpression conditionalExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitDirectionExpression(DirectionExpression directionExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIndexerExpression(IndexerExpression indexerExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitInvocationExpression(InvocationExpression invocationExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIsExpression(IsExpression isExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitLambdaExpression(LambdaExpression lambdaExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitSizeOfExpression(SizeOfExpression sizeOfExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitStackAllocExpression(StackAllocExpression stackAllocExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitTypeOfExpression(TypeOfExpression typeOfExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUncheckedExpression(UncheckedExpression uncheckedExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryFromClause(QueryFromClause queryFromClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryLetClause(QueryLetClause queryLetClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryOrdering(QueryOrdering queryOrdering, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitAttribute(Attribute attribute, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitAttributeSection(AttributeSection attributeSection, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitTypeDeclaration(TypeDeclaration typeDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUsingDeclaration(UsingDeclaration usingDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitBlockStatement(BlockStatement blockStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitBreakStatement(BreakStatement breakStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCheckedStatement(CheckedStatement checkedStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitContinueStatement(ContinueStatement continueStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitDoWhileStatement(DoWhileStatement doWhileStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitEmptyStatement(EmptyStatement emptyStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitExpressionStatement(ExpressionStatement expressionStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitFixedStatement(FixedStatement fixedStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitForeachStatement(ForeachStatement foreachStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitForStatement(ForStatement forStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitGotoStatement(GotoStatement gotoStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIfElseStatement(IfElseStatement ifElseStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitLabelStatement(LabelStatement labelStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitLockStatement(LockStatement lockStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitReturnStatement(ReturnStatement returnStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitSwitchStatement(SwitchStatement switchStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitSwitchSection(SwitchSection switchSection, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCaseLabel(CaseLabel caseLabel, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitThrowStatement(ThrowStatement throwStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitTryCatchStatement(TryCatchStatement tryCatchStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCatchClause(CatchClause catchClause, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUncheckedStatement(UncheckedStatement uncheckedStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUnsafeStatement(UnsafeStatement unsafeStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitUsingStatement(UsingStatement usingStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitWhileStatement(WhileStatement whileStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitYieldStatement(YieldStatement yieldStatement, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitAccessor(Accessor accessor, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitConstructorInitializer(ConstructorInitializer constructorInitializer, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitEventDeclaration(EventDeclaration eventDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitFieldDeclaration(FieldDeclaration fieldDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitMethodDeclaration(MethodDeclaration methodDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitVariableInitializer(VariableInitializer variableInitializer, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCompilationUnit(CompilationUnit compilationUnit, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitSimpleType(SimpleType simpleType, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitMemberType(MemberType memberType, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitComposedType(ComposedType composedType, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitPrimitiveType(PrimitiveType primitiveType, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitComment(Comment comment, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitConstraint(Constraint constraint, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitIdentifier(Identifier identifier, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitEmptyExpression(EmptyExpression emptyExpression, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, T data) + { + throw new NotImplementedException(); + } + + public virtual S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, T data) + { + throw new NotImplementedException(); + } + + public S VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, T data) + { + throw new NotImplementedException(); + } + + public S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data) + { + throw new NotImplementedException(); + } + + public S VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern, T data) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs new file mode 100644 index 0000000000..253f6ef3c3 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs @@ -0,0 +1,1141 @@ +// +// ObservableAstVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class ObservableAstVisitor: IAstVisitor + { + S VisitChildren (AstNode node, T data) + { + AstNode next; + for (var child = node.FirstChild; child != null; child = next) { + // Store next to allow the loop to continue + // if the visitor removes/replaces child. + next = child.NextSibling; + child.AcceptVisitor (this, data); + } + return default (S); + } + + public event Action CompilationUnitVisited; + + S IAstVisitor.VisitCompilationUnit (CompilationUnit unit, T data) + { + var handler = CompilationUnitVisited; + if (handler != null) + handler (unit, data); + return VisitChildren (unit, data); + } + + public event Action CommentVisited; + + S IAstVisitor.VisitComment (Comment comment, T data) + { + var handler = CommentVisited; + if (handler != null) + handler (comment, data); + return VisitChildren (comment, data); + } + + public event Action IdentifierVisited; + + S IAstVisitor.VisitIdentifier (Identifier identifier, T data) + { + var handler = IdentifierVisited; + if (handler != null) + handler (identifier, data); + return VisitChildren (identifier, data); + } + + public event Action CSharpTokenNodeVisited; + + S IAstVisitor.VisitCSharpTokenNode (CSharpTokenNode token, T data) + { + var handler = CSharpTokenNodeVisited; + if (handler != null) + handler (token, data); + return VisitChildren (token, data); + } + + public event Action PrimitiveTypeVisited; + + S IAstVisitor.VisitPrimitiveType (PrimitiveType primitiveType, T data) + { + var handler = PrimitiveTypeVisited; + if (handler != null) + handler (primitiveType, data); + return VisitChildren (primitiveType, data); + } + + public event Action ComposedTypeVisited; + + S IAstVisitor.VisitComposedType (ComposedType composedType, T data) + { + var handler = ComposedTypeVisited; + if (handler != null) + handler (composedType, data); + return VisitChildren (composedType, data); + } + + public event Action SimpleTypeVisited; + + S IAstVisitor.VisitSimpleType (SimpleType simpleType, T data) + { + var handler = SimpleTypeVisited; + if (handler != null) + handler (simpleType, data); + return VisitChildren (simpleType, data); + } + + public event Action MemberTypeVisited; + + S IAstVisitor.VisitMemberType (MemberType memberType, T data) + { + var handler = MemberTypeVisited; + if (handler != null) + handler (memberType, data); + return VisitChildren (memberType, data); + } + + public event Action AttributeVisited; + + S IAstVisitor.VisitAttribute (Attribute attribute, T data) + { + var handler = AttributeVisited; + if (handler != null) + handler (attribute, data); + return VisitChildren (attribute, data); + } + + public event Action AttributeSectionVisited; + + S IAstVisitor.VisitAttributeSection (AttributeSection attributeSection, T data) + { + var handler = AttributeSectionVisited; + if (handler != null) + handler (attributeSection, data); + return VisitChildren (attributeSection, data); + } + + public event Action DelegateDeclarationVisited; + + S IAstVisitor.VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, T data) + { + var handler = DelegateDeclarationVisited; + if (handler != null) + handler (delegateDeclaration, data); + return VisitChildren (delegateDeclaration, data); + } + + public event Action NamespaceDeclarationVisited; + + S IAstVisitor.VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, T data) + { + var handler = NamespaceDeclarationVisited; + if (handler != null) + handler (namespaceDeclaration, data); + return VisitChildren (namespaceDeclaration, data); + } + + public event Action TypeDeclarationVisited; + + S IAstVisitor.VisitTypeDeclaration (TypeDeclaration typeDeclaration, T data) + { + var handler = TypeDeclarationVisited; + if (handler != null) + handler (typeDeclaration, data); + return VisitChildren (typeDeclaration, data); + } + + public event Action TypeParameterDeclarationVisited; + + S IAstVisitor.VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, T data) + { + var handler = TypeParameterDeclarationVisited; + if (handler != null) + handler (typeParameterDeclaration, data); + return VisitChildren (typeParameterDeclaration, data); + } + + public event Action EnumMemberDeclarationVisited; + + S IAstVisitor.VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, T data) + { + var handler = EnumMemberDeclarationVisited; + if (handler != null) + handler (enumMemberDeclaration, data); + return VisitChildren (enumMemberDeclaration, data); + } + + public event Action UsingDeclarationVisited; + + S IAstVisitor.VisitUsingDeclaration (UsingDeclaration usingDeclaration, T data) + { + var handler = UsingDeclarationVisited; + if (handler != null) + handler (usingDeclaration, data); + return VisitChildren (usingDeclaration, data); + } + + public event Action UsingAliasDeclarationVisited; + + S IAstVisitor.VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, T data) + { + var handler = UsingAliasDeclarationVisited; + if (handler != null) + handler (usingDeclaration, data); + return VisitChildren (usingDeclaration, data); + } + + public event Action ExternAliasDeclarationVisited; + + S IAstVisitor.VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration, T data) + { + var handler = ExternAliasDeclarationVisited; + if (handler != null) + handler (externAliasDeclaration, data); + return VisitChildren (externAliasDeclaration, data); + } + + public event Action ConstructorDeclarationVisited; + + S IAstVisitor.VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, T data) + { + var handler = ConstructorDeclarationVisited; + if (handler != null) + handler (constructorDeclaration, data); + return VisitChildren (constructorDeclaration, data); + } + + public event Action ConstructorInitializerVisited; + + S IAstVisitor.VisitConstructorInitializer (ConstructorInitializer constructorInitializer, T data) + { + var handler = ConstructorInitializerVisited; + if (handler != null) + handler (constructorInitializer, data); + return VisitChildren (constructorInitializer, data); + } + + public event Action DestructorDeclarationVisited; + + S IAstVisitor.VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, T data) + { + var handler = DestructorDeclarationVisited; + if (handler != null) + handler (destructorDeclaration, data); + return VisitChildren (destructorDeclaration, data); + } + + public event Action EventDeclarationVisited; + + S IAstVisitor.VisitEventDeclaration (EventDeclaration eventDeclaration, T data) + { + var handler = EventDeclarationVisited; + if (handler != null) + handler (eventDeclaration, data); + return VisitChildren (eventDeclaration, data); + } + + public event Action CustomEventDeclarationVisited; + + S IAstVisitor.VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, T data) + { + var handler = CustomEventDeclarationVisited; + if (handler != null) + handler (eventDeclaration, data); + return VisitChildren (eventDeclaration, data); + } + + public event Action FieldDeclarationVisited; + + S IAstVisitor.VisitFieldDeclaration (FieldDeclaration fieldDeclaration, T data) + { + var handler = FieldDeclarationVisited; + if (handler != null) + handler (fieldDeclaration, data); + return VisitChildren (fieldDeclaration, data); + } + + public event Action FixedFieldDeclarationVisited; + + S IAstVisitor.VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, T data) + { + var handler = FixedFieldDeclarationVisited; + if (handler != null) + handler (fixedFieldDeclaration, data); + return VisitChildren (fixedFieldDeclaration, data); + } + + public event Action FixedVariableInitializerVisited; + + S IAstVisitor.VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, T data) + { + var handler = FixedVariableInitializerVisited; + if (handler != null) + handler (fixedVariableInitializer, data); + return VisitChildren (fixedVariableInitializer, data); + } + + public event Action IndexerDeclarationVisited; + + S IAstVisitor.VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, T data) + { + var handler = IndexerDeclarationVisited; + if (handler != null) + handler (indexerDeclaration, data); + return VisitChildren (indexerDeclaration, data); + } + + public event Action MethodDeclarationVisited; + + S IAstVisitor.VisitMethodDeclaration (MethodDeclaration methodDeclaration, T data) + { + var handler = MethodDeclarationVisited; + if (handler != null) + handler (methodDeclaration, data); + return VisitChildren (methodDeclaration, data); + } + + public event Action OperatorDeclarationVisited; + + S IAstVisitor.VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, T data) + { + var handler = OperatorDeclarationVisited; + if (handler != null) + handler (operatorDeclaration, data); + return VisitChildren (operatorDeclaration, data); + } + + public event Action PropertyDeclarationVisited; + + S IAstVisitor.VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, T data) + { + var handler = PropertyDeclarationVisited; + if (handler != null) + handler (propertyDeclaration, data); + return VisitChildren (propertyDeclaration, data); + } + + public event Action AccessorVisited; + + S IAstVisitor.VisitAccessor (Accessor accessor, T data) + { + var handler = AccessorVisited; + if (handler != null) + handler (accessor, data); + return VisitChildren (accessor, data); + } + + public event Action VariableInitializerVisited; + + S IAstVisitor.VisitVariableInitializer (VariableInitializer variableInitializer, T data) + { + var handler = VariableInitializerVisited; + if (handler != null) + handler (variableInitializer, data); + return VisitChildren (variableInitializer, data); + } + + public event Action ParameterDeclarationVisited; + + S IAstVisitor.VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, T data) + { + var handler = ParameterDeclarationVisited; + if (handler != null) + handler (parameterDeclaration, data); + return VisitChildren (parameterDeclaration, data); + } + + public event Action ConstraintVisited; + + S IAstVisitor.VisitConstraint (Constraint constraint, T data) + { + var handler = ConstraintVisited; + if (handler != null) + handler (constraint, data); + return VisitChildren (constraint, data); + } + + public event Action BlockStatementVisited; + + S IAstVisitor.VisitBlockStatement (BlockStatement blockStatement, T data) + { + var handler = BlockStatementVisited; + if (handler != null) + handler (blockStatement, data); + return VisitChildren (blockStatement, data); + } + + public event Action ExpressionStatementVisited; + + S IAstVisitor.VisitExpressionStatement (ExpressionStatement expressionStatement, T data) + { + var handler = ExpressionStatementVisited; + if (handler != null) + handler (expressionStatement, data); + return VisitChildren (expressionStatement, data); + } + + public event Action BreakStatementVisited; + + S IAstVisitor.VisitBreakStatement (BreakStatement breakStatement, T data) + { + var handler = BreakStatementVisited; + if (handler != null) + handler (breakStatement, data); + return VisitChildren (breakStatement, data); + } + + public event Action CheckedStatementVisited; + + S IAstVisitor.VisitCheckedStatement (CheckedStatement checkedStatement, T data) + { + var handler = CheckedStatementVisited; + if (handler != null) + handler (checkedStatement, data); + return VisitChildren (checkedStatement, data); + } + + public event Action ContinueStatementVisited; + + S IAstVisitor.VisitContinueStatement (ContinueStatement continueStatement, T data) + { + var handler = ContinueStatementVisited; + if (handler != null) + handler (continueStatement, data); + return VisitChildren (continueStatement, data); + } + + public event Action DoWhileStatementVisited; + + S IAstVisitor.VisitDoWhileStatement (DoWhileStatement doWhileStatement, T data) + { + var handler = DoWhileStatementVisited; + if (handler != null) + handler (doWhileStatement, data); + return VisitChildren (doWhileStatement, data); + } + + public event Action EmptyStatementVisited; + + S IAstVisitor.VisitEmptyStatement (EmptyStatement emptyStatement, T data) + { + var handler = EmptyStatementVisited; + if (handler != null) + handler (emptyStatement, data); + return VisitChildren (emptyStatement, data); + } + + public event Action FixedStatementVisited; + + S IAstVisitor.VisitFixedStatement (FixedStatement fixedStatement, T data) + { + var handler = FixedStatementVisited; + if (handler != null) + handler (fixedStatement, data); + return VisitChildren (fixedStatement, data); + } + + public event Action ForeachStatementVisited; + + S IAstVisitor.VisitForeachStatement (ForeachStatement foreachStatement, T data) + { + var handler = ForeachStatementVisited; + if (handler != null) + handler (foreachStatement, data); + return VisitChildren (foreachStatement, data); + } + + public event Action ForStatementVisited; + + S IAstVisitor.VisitForStatement (ForStatement forStatement, T data) + { + var handler = ForStatementVisited; + if (handler != null) + handler (forStatement, data); + return VisitChildren (forStatement, data); + } + + public event Action GotoCaseStatementVisited; + + S IAstVisitor.VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, T data) + { + var handler = GotoCaseStatementVisited; + if (handler != null) + handler (gotoCaseStatement, data); + return VisitChildren (gotoCaseStatement, data); + } + + public event Action GotoDefaultStatementVisited; + + S IAstVisitor.VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, T data) + { + var handler = GotoDefaultStatementVisited; + if (handler != null) + handler (gotoDefaultStatement, data); + return VisitChildren (gotoDefaultStatement, data); + } + + public event Action GotoStatementVisited; + + S IAstVisitor.VisitGotoStatement (GotoStatement gotoStatement, T data) + { + var handler = GotoStatementVisited; + if (handler != null) + handler (gotoStatement, data); + return VisitChildren (gotoStatement, data); + } + + public event Action IfElseStatementVisited; + + S IAstVisitor.VisitIfElseStatement (IfElseStatement ifElseStatement, T data) + { + var handler = IfElseStatementVisited; + if (handler != null) + handler (ifElseStatement, data); + return VisitChildren (ifElseStatement, data); + } + + public event Action LabelStatementVisited; + + S IAstVisitor.VisitLabelStatement (LabelStatement labelStatement, T data) + { + var handler = LabelStatementVisited; + if (handler != null) + handler (labelStatement, data); + return VisitChildren (labelStatement, data); + } + + public event Action LockStatementVisited; + + S IAstVisitor.VisitLockStatement (LockStatement lockStatement, T data) + { + var handler = LockStatementVisited; + if (handler != null) + handler (lockStatement, data); + return VisitChildren (lockStatement, data); + } + + public event Action ReturnStatementVisited; + + S IAstVisitor.VisitReturnStatement (ReturnStatement returnStatement, T data) + { + var handler = ReturnStatementVisited; + if (handler != null) + handler (returnStatement, data); + return VisitChildren (returnStatement, data); + } + + public event Action SwitchStatementVisited; + + S IAstVisitor.VisitSwitchStatement (SwitchStatement switchStatement, T data) + { + var handler = SwitchStatementVisited; + if (handler != null) + handler (switchStatement, data); + return VisitChildren (switchStatement, data); + } + + public event Action SwitchSectionVisited; + + S IAstVisitor.VisitSwitchSection (SwitchSection switchSection, T data) + { + var handler = SwitchSectionVisited; + if (handler != null) + handler (switchSection, data); + return VisitChildren (switchSection, data); + } + + public event Action CaseLabelVisited; + + S IAstVisitor.VisitCaseLabel (CaseLabel caseLabel, T data) + { + var handler = CaseLabelVisited; + if (handler != null) + handler (caseLabel, data); + return VisitChildren (caseLabel, data); + } + + public event Action ThrowStatementVisited; + + S IAstVisitor.VisitThrowStatement (ThrowStatement throwStatement, T data) + { + var handler = ThrowStatementVisited; + if (handler != null) + handler (throwStatement, data); + return VisitChildren (throwStatement, data); + } + + public event Action TryCatchStatementVisited; + + S IAstVisitor.VisitTryCatchStatement (TryCatchStatement tryCatchStatement, T data) + { + var handler = TryCatchStatementVisited; + if (handler != null) + handler (tryCatchStatement, data); + return VisitChildren (tryCatchStatement, data); + } + + public event Action CatchClauseVisited; + + S IAstVisitor.VisitCatchClause (CatchClause catchClause, T data) + { + var handler = CatchClauseVisited; + if (handler != null) + handler (catchClause, data); + return VisitChildren (catchClause, data); + } + + public event Action UncheckedStatementVisited; + + S IAstVisitor.VisitUncheckedStatement (UncheckedStatement uncheckedStatement, T data) + { + var handler = UncheckedStatementVisited; + if (handler != null) + handler (uncheckedStatement, data); + return VisitChildren (uncheckedStatement, data); + } + + public event Action UnsafeStatementVisited; + + S IAstVisitor.VisitUnsafeStatement (UnsafeStatement unsafeStatement, T data) + { + var handler = UnsafeStatementVisited; + if (handler != null) + handler (unsafeStatement, data); + return VisitChildren (unsafeStatement, data); + } + + public event Action UsingStatementVisited; + + S IAstVisitor.VisitUsingStatement (UsingStatement usingStatement, T data) + { + var handler = UsingStatementVisited; + if (handler != null) + handler (usingStatement, data); + return VisitChildren (usingStatement, data); + } + + public event Action VariableDeclarationStatementVisited; + + S IAstVisitor.VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, T data) + { + var handler = VariableDeclarationStatementVisited; + if (handler != null) + handler (variableDeclarationStatement, data); + return VisitChildren (variableDeclarationStatement, data); + } + + public event Action WhileStatementVisited; + + S IAstVisitor.VisitWhileStatement (WhileStatement whileStatement, T data) + { + var handler = WhileStatementVisited; + if (handler != null) + handler (whileStatement, data); + return VisitChildren (whileStatement, data); + } + + public event Action YieldBreakStatementVisited; + + S IAstVisitor.VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, T data) + { + var handler = YieldBreakStatementVisited; + if (handler != null) + handler (yieldBreakStatement, data); + return VisitChildren (yieldBreakStatement, data); + } + + public event Action YieldStatementVisited; + + S IAstVisitor.VisitYieldStatement (YieldStatement yieldStatement, T data) + { + var handler = YieldStatementVisited; + if (handler != null) + handler (yieldStatement, data); + return VisitChildren (yieldStatement, data); + } + + public event Action AnonymousMethodExpressionVisited; + + S IAstVisitor.VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, T data) + { + var handler = AnonymousMethodExpressionVisited; + if (handler != null) + handler (anonymousMethodExpression, data); + return VisitChildren (anonymousMethodExpression, data); + } + + public event Action LambdaExpressionVisited; + + S IAstVisitor.VisitLambdaExpression (LambdaExpression lambdaExpression, T data) + { + var handler = LambdaExpressionVisited; + if (handler != null) + handler (lambdaExpression, data); + return VisitChildren (lambdaExpression, data); + } + + public event Action AssignmentExpressionVisited; + + S IAstVisitor.VisitAssignmentExpression (AssignmentExpression assignmentExpression, T data) + { + var handler = AssignmentExpressionVisited; + if (handler != null) + handler (assignmentExpression, data); + return VisitChildren (assignmentExpression, data); + } + + public event Action BaseReferenceExpressionVisited; + + S IAstVisitor.VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, T data) + { + var handler = BaseReferenceExpressionVisited; + if (handler != null) + handler (baseReferenceExpression, data); + return VisitChildren (baseReferenceExpression, data); + } + + public event Action BinaryOperatorExpressionVisited; + + S IAstVisitor.VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, T data) + { + var handler = BinaryOperatorExpressionVisited; + if (handler != null) + handler (binaryOperatorExpression, data); + return VisitChildren (binaryOperatorExpression, data); + } + + public event Action CastExpressionVisited; + + S IAstVisitor.VisitCastExpression (CastExpression castExpression, T data) + { + var handler = CastExpressionVisited; + if (handler != null) + handler (castExpression, data); + return VisitChildren (castExpression, data); + } + + public event Action CheckedExpressionVisited; + + S IAstVisitor.VisitCheckedExpression (CheckedExpression checkedExpression, T data) + { + var handler = CheckedExpressionVisited; + if (handler != null) + handler (checkedExpression, data); + return VisitChildren (checkedExpression, data); + } + + public event Action ConditionalExpressionVisited; + + S IAstVisitor.VisitConditionalExpression (ConditionalExpression conditionalExpression, T data) + { + var handler = ConditionalExpressionVisited; + if (handler != null) + handler (conditionalExpression, data); + return VisitChildren (conditionalExpression, data); + } + + public event Action IdentifierExpressionVisited; + + S IAstVisitor.VisitIdentifierExpression (IdentifierExpression identifierExpression, T data) + { + var handler = IdentifierExpressionVisited; + if (handler != null) + handler (identifierExpression, data); + return VisitChildren (identifierExpression, data); + } + + public event Action IndexerExpressionVisited; + + S IAstVisitor.VisitIndexerExpression (IndexerExpression indexerExpression, T data) + { + var handler = IndexerExpressionVisited; + if (handler != null) + handler (indexerExpression, data); + return VisitChildren (indexerExpression, data); + } + + public event Action InvocationExpressionVisited; + + S IAstVisitor.VisitInvocationExpression (InvocationExpression invocationExpression, T data) + { + var handler = InvocationExpressionVisited; + if (handler != null) + handler (invocationExpression, data); + return VisitChildren (invocationExpression, data); + } + + public event Action DirectionExpressionVisited; + + S IAstVisitor.VisitDirectionExpression (DirectionExpression directionExpression, T data) + { + var handler = DirectionExpressionVisited; + if (handler != null) + handler (directionExpression, data); + return VisitChildren (directionExpression, data); + } + + public event Action MemberReferenceExpressionVisited; + + S IAstVisitor.VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, T data) + { + var handler = MemberReferenceExpressionVisited; + if (handler != null) + handler (memberReferenceExpression, data); + return VisitChildren (memberReferenceExpression, data); + } + + public event Action NullReferenceExpressionVisited; + + S IAstVisitor.VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, T data) + { + var handler = NullReferenceExpressionVisited; + if (handler != null) + handler (nullReferenceExpression, data); + return VisitChildren (nullReferenceExpression, data); + } + + public event Action ObjectCreateExpressionVisited; + + S IAstVisitor.VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, T data) + { + var handler = ObjectCreateExpressionVisited; + if (handler != null) + handler (objectCreateExpression, data); + return VisitChildren (objectCreateExpression, data); + } + + public event Action AnonymousTypeCreateExpressionVisited; + + S IAstVisitor.VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data) + { + var handler = AnonymousTypeCreateExpressionVisited; + if (handler != null) + handler (anonymousTypeCreateExpression, data); + return VisitChildren (anonymousTypeCreateExpression, data); + } + + public event Action ArrayCreateExpressionVisited; + + S IAstVisitor.VisitArrayCreateExpression (ArrayCreateExpression arraySCreateExpression, T data) + { + var handler = ArrayCreateExpressionVisited; + if (handler != null) + handler (arraySCreateExpression, data); + return VisitChildren (arraySCreateExpression, data); + } + + public event Action ParenthesizedExpressionVisited; + + S IAstVisitor.VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data) + { + var handler = ParenthesizedExpressionVisited; + if (handler != null) + handler (parenthesizedExpression, data); + return VisitChildren (parenthesizedExpression, data); + } + + public event Action PointerReferenceExpressionVisited; + + S IAstVisitor.VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, T data) + { + var handler = PointerReferenceExpressionVisited; + if (handler != null) + handler (pointerReferenceExpression, data); + return VisitChildren (pointerReferenceExpression, data); + } + + public event Action PrimitiveExpressionVisited; + + S IAstVisitor.VisitPrimitiveExpression (PrimitiveExpression primitiveExpression, T data) + { + var handler = PrimitiveExpressionVisited; + if (handler != null) + handler (primitiveExpression, data); + return VisitChildren (primitiveExpression, data); + } + + public event Action SizeOfExpressionVisited; + + S IAstVisitor.VisitSizeOfExpression (SizeOfExpression sizeOfExpression, T data) + { + var handler = SizeOfExpressionVisited; + if (handler != null) + handler (sizeOfExpression, data); + return VisitChildren (sizeOfExpression, data); + } + + public event Action StackAllocExpressionVisited; + + S IAstVisitor.VisitStackAllocExpression (StackAllocExpression stackAllocExpression, T data) + { + var handler = StackAllocExpressionVisited; + if (handler != null) + handler (stackAllocExpression, data); + return VisitChildren (stackAllocExpression, data); + } + + public event Action ThisReferenceExpressionVisited; + + S IAstVisitor.VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression, T data) + { + var handler = ThisReferenceExpressionVisited; + if (handler != null) + handler (thisReferenceExpression, data); + return VisitChildren (thisReferenceExpression, data); + } + + public event Action TypeOfExpressionVisited; + + S IAstVisitor.VisitTypeOfExpression (TypeOfExpression typeOfExpression, T data) + { + var handler = TypeOfExpressionVisited; + if (handler != null) + handler (typeOfExpression, data); + return VisitChildren (typeOfExpression, data); + } + + public event Action TypeReferenceExpressionVisited; + + S IAstVisitor.VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression, T data) + { + var handler = TypeReferenceExpressionVisited; + if (handler != null) + handler (typeReferenceExpression, data); + return VisitChildren (typeReferenceExpression, data); + } + + public event Action UnaryOperatorExpressionVisited; + + S IAstVisitor.VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, T data) + { + var handler = UnaryOperatorExpressionVisited; + if (handler != null) + handler (unaryOperatorExpression, data); + return VisitChildren (unaryOperatorExpression, data); + } + + public event Action UncheckedExpressionVisited; + + S IAstVisitor.VisitUncheckedExpression (UncheckedExpression uncheckedExpression, T data) + { + var handler = UncheckedExpressionVisited; + if (handler != null) + handler (uncheckedExpression, data); + return VisitChildren (uncheckedExpression, data); + } + + public event Action QueryExpressionVisited; + + S IAstVisitor.VisitQueryExpression (QueryExpression queryExpression, T data) + { + var handler = QueryExpressionVisited; + if (handler != null) + handler (queryExpression, data); + return VisitChildren (queryExpression, data); + } + + public event Action QueryContinuationClauseVisited; + + S IAstVisitor.VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause, T data) + { + var handler = QueryContinuationClauseVisited; + if (handler != null) + handler (queryContinuationClause, data); + return VisitChildren (queryContinuationClause, data); + } + + public event Action QueryFromClauseVisited; + + S IAstVisitor.VisitQueryFromClause (QueryFromClause queryFromClause, T data) + { + var handler = QueryFromClauseVisited; + if (handler != null) + handler (queryFromClause, data); + return VisitChildren (queryFromClause, data); + } + + public event Action QueryLetClauseVisited; + + S IAstVisitor.VisitQueryLetClause (QueryLetClause queryLetClause, T data) + { + var handler = QueryLetClauseVisited; + if (handler != null) + handler (queryLetClause, data); + return VisitChildren (queryLetClause, data); + } + + public event Action QueryWhereClauseVisited; + + S IAstVisitor.VisitQueryWhereClause (QueryWhereClause queryWhereClause, T data) + { + var handler = QueryWhereClauseVisited; + if (handler != null) + handler (queryWhereClause, data); + return VisitChildren (queryWhereClause, data); + } + + public event Action QueryJoinClauseVisited; + + S IAstVisitor.VisitQueryJoinClause (QueryJoinClause queryJoinClause, T data) + { + var handler = QueryJoinClauseVisited; + if (handler != null) + handler (queryJoinClause, data); + return VisitChildren (queryJoinClause, data); + } + + public event Action QueryOrderClauseVisited; + + S IAstVisitor.VisitQueryOrderClause (QueryOrderClause queryOrderClause, T data) + { + var handler = QueryOrderClauseVisited; + if (handler != null) + handler (queryOrderClause, data); + return VisitChildren (queryOrderClause, data); + } + + public event Action QueryOrderingVisited; + + S IAstVisitor.VisitQueryOrdering (QueryOrdering queryOrdering, T data) + { + var handler = QueryOrderingVisited; + if (handler != null) + handler (queryOrdering, data); + return VisitChildren (queryOrdering, data); + } + + public event Action QuerySelectClauseVisited; + + S IAstVisitor.VisitQuerySelectClause (QuerySelectClause querySelectClause, T data) + { + var handler = QuerySelectClauseVisited; + if (handler != null) + handler (querySelectClause, data); + return VisitChildren (querySelectClause, data); + } + + public event Action QueryGroupClauseVisited; + + S IAstVisitor.VisitQueryGroupClause (QueryGroupClause queryGroupClause, T data) + { + var handler = QueryGroupClauseVisited; + if (handler != null) + handler (queryGroupClause, data); + return VisitChildren (queryGroupClause, data); + } + + public event Action AsExpressionVisited; + + S IAstVisitor.VisitAsExpression (AsExpression asExpression, T data) + { + var handler = AsExpressionVisited; + if (handler != null) + handler (asExpression, data); + return VisitChildren (asExpression, data); + } + + public event Action IsExpressionVisited; + + S IAstVisitor.VisitIsExpression (IsExpression isExpression, T data) + { + var handler = IsExpressionVisited; + if (handler != null) + handler (isExpression, data); + return VisitChildren (isExpression, data); + } + + public event Action DefaultValueExpressionVisited; + + S IAstVisitor.VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, T data) + { + var handler = DefaultValueExpressionVisited; + if (handler != null) + handler (defaultValueExpression, data); + return VisitChildren (defaultValueExpression, data); + } + + public event Action UndocumentedExpressionVisited; + + S IAstVisitor.VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, T data) + { + var handler = UndocumentedExpressionVisited; + if (handler != null) + handler (undocumentedExpression, data); + return VisitChildren (undocumentedExpression, data); + } + + public event Action ArrayInitializerExpressionVisited; + + S IAstVisitor.VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, T data) + { + var handler = ArrayInitializerExpressionVisited; + if (handler != null) + handler (arrayInitializerExpression, data); + return VisitChildren (arrayInitializerExpression, data); + } + + public event Action ArraySpecifierVisited; + + S IAstVisitor.VisitArraySpecifier (ArraySpecifier arraySpecifier, T data) + { + var handler = ArraySpecifierVisited; + if (handler != null) + handler (arraySpecifier, data); + return VisitChildren (arraySpecifier, data); + } + + public event Action NamedArgumentExpressionVisited; + + S IAstVisitor.VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, T data) + { + var handler = NamedArgumentExpressionVisited; + if (handler != null) + handler (namedArgumentExpression, data); + return VisitChildren (namedArgumentExpression, data); + } + + public event Action EmptyExpressionVisited; + + S IAstVisitor.VisitEmptyExpression (EmptyExpression emptyExpression, T data) + { + var handler = EmptyExpressionVisited; + if (handler != null) + handler (emptyExpression, data); + return VisitChildren (emptyExpression, data); + } + + S IAstVisitor.VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, T data) + { + return VisitChildren (placeholder, data); + } + } +} + + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs index 2a2b41dff5..26c93b21a7 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs @@ -29,7 +29,7 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { - public class PrimitiveType : AstType + public class PrimitiveType : AstType, IRelocatable { public string Keyword { get; set; } public AstLocation Location { get; set; } @@ -60,6 +60,14 @@ namespace ICSharpCode.NRefactory.CSharp } } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.Location = startLocation; + } + #endregion + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitPrimitiveType (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs index 2d807a50ab..675b344a7f 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs @@ -3,7 +3,7 @@ using System; -namespace ICSharpCode.NRefactory.CSharp +namespace ICSharpCode.NRefactory { /// /// Represents the role a node plays within its parent. @@ -15,14 +15,14 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Gets whether the specified node is valid in this role. /// - public abstract bool IsValid(AstNode node); + public abstract bool IsValid(object node); } /// /// Represents the role a node plays within its parent. /// All nodes with this role have type T. /// - public sealed class Role : Role where T : AstNode + public sealed class Role : Role where T : class { readonly string name; // helps with debugging the AST readonly T nullObject; @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return nullObject; } } - public override bool IsValid(AstNode node) + public override bool IsValid(object node) { return node is T; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs index 237b3b55ba..2609473e71 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs @@ -1,4 +1,4 @@ -// +// // FullTypeName.cs // // Author: @@ -44,7 +44,19 @@ namespace ICSharpCode.NRefactory.CSharp public SimpleType(string identifier, AstLocation location) { - SetChildByRole (Roles.Identifier, new Identifier(identifier, location)); + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (identifier, location)); + } + + public SimpleType (string identifier, IEnumerable typeArguments) + { + this.Identifier = identifier; + foreach (var arg in typeArguments) { + AddChild (arg, Roles.TypeArgument); + } + } + + public SimpleType (string identifier, params AstType[] typeArguments) : this (identifier, (IEnumerable)typeArguments) + { } public string Identifier { @@ -52,7 +64,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs index 3ee53863e5..c75adbec68 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs @@ -1,4 +1,4 @@ -// +// // EmptyStatement.cs // // Author: @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// ; /// - public class EmptyStatement : Statement + public class EmptyStatement : Statement, IRelocatable { public AstLocation Location { get; @@ -48,6 +48,13 @@ namespace ICSharpCode.NRefactory.CSharp } } + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.Location = startLocation; + } + #endregion + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitEmptyStatement (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs index 6caf3883e7..52be5da59a 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs @@ -1,4 +1,4 @@ -// +// // ForeachStatement.cs // // Author: @@ -49,7 +49,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier VariableNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs index 2eeeb0bc39..0bcc5e2388 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs @@ -1,4 +1,4 @@ -// +// // GotoStatement.cs // // Author: @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp if (string.IsNullOrEmpty(value)) SetChildByRole(Roles.Identifier, null); else - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs index 3ebdc3302c..b23c80a4c2 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs @@ -1,4 +1,4 @@ -// +// // LabelStatement.cs // // Author: @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs index f7404229a4..c3fd4dd3fb 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs @@ -156,6 +156,15 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Expression, value); } } + public CaseLabel () + { + } + + public CaseLabel (Expression expression) + { + this.Expression = expression; + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitCaseLabel (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs index ccd1fb7b6e..77ef45e6b2 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs @@ -1,4 +1,4 @@ -// +// // TryCatchStatement.cs // // Author: @@ -140,7 +140,16 @@ namespace ICSharpCode.NRefactory.CSharp if (string.IsNullOrEmpty(value)) SetChildByRole (Roles.Identifier, null); else - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier VariableNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs index e5066c1c31..54f473684e 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs @@ -61,6 +61,11 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } + public VariableInitializer GetVariable (string name) + { + return Variables.FirstOrDefault (vi => vi.Name == name); + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitVariableDeclarationStatement (this, data); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs index af5e584dc4..019c55444a 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs @@ -58,9 +58,14 @@ namespace ICSharpCode.NRefactory.CSharp } } - protected bool MatchAttributesAndModifiers(AttributedNode o, PatternMatching.Match match) + protected bool MatchAttributesAndModifiers (AttributedNode o, PatternMatching.Match match) { - return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match); + return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch (o.Attributes, match); + } + + public bool HasModifier (Modifiers mod) + { + return (Modifiers & mod) == mod; } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs index a86214b977..afcc2d47d6 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs @@ -40,6 +40,11 @@ namespace ICSharpCode.NRefactory.CSharp /// public string Name { get; set; } + public Identifier IdentifierToken { + get { return GetChildByRole (Roles.Identifier); } + set { SetChildByRole (Roles.Identifier, value); } + } + public CSharpTokenNode LParToken { get { return GetChildByRole (Roles.LPar); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs index 8a892b275c..829682e73f 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs @@ -41,6 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp /// public string Name { get; set; } + public Identifier IdentifierToken { + get { return GetChildByRole (Roles.Identifier); } + set { SetChildByRole (Roles.Identifier, value); } + } + public CSharpTokenNode LParToken { get { return GetChildByRole (Roles.LPar); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs index e2784f565a..8c31562983 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs @@ -1,4 +1,4 @@ -// +// // EnumMemberDeclaration.cs // // Author: @@ -36,7 +36,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs index 930d31a0e5..1d5d9da935 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs @@ -1,4 +1,4 @@ -// +// // FixedFieldDeclaration.cs // // Author: @@ -54,10 +54,19 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); } } - + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + public CSharpTokenNode LBracketToken { get { return GetChildByRole (Roles.LBracket); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs index a7e1b74e46..f2fd816830 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs @@ -1,4 +1,4 @@ -// +// // AbstractMember.cs // // Author: @@ -48,7 +48,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs index c7e68ab029..31d1232323 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs @@ -23,7 +23,6 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System.Collections.Generic; using System.Linq; @@ -72,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp public class OperatorDeclaration : AttributedNode { - public static readonly Role OperatorTypeRole = new Role("OperatorType", CSharpTokenNode.Null); + public static readonly Role OperatorTypeRole = new Role ("OperatorType", CSharpTokenNode.Null); public static readonly Role OperatorKeywordRole = Roles.Keyword; public OperatorType OperatorType { @@ -82,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp public AstType ReturnType { get { return GetChildByRole (Roles.Type); } - set { SetChildByRole(Roles.Type, value); } + set { SetChildByRole (Roles.Type, value); } } public CSharpTokenNode LParToken { @@ -113,17 +112,17 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Gets the method name for the operator type. ("op_Addition", "op_Implicit", etc.) /// - public static string GetName(OperatorType type) + public static string GetName (OperatorType type) { - return Mono.CSharp.Operator.GetMetadataName((Mono.CSharp.Operator.OpType)type); + return Mono.CSharp.Operator.GetMetadataName ((Mono.CSharp.Operator.OpType)type); } /// /// Gets the token for the operator type ("+", "implicit", etc.) /// - public static string GetToken(OperatorType type) + public static string GetToken (OperatorType type) { - return Mono.CSharp.Operator.GetName((Mono.CSharp.Operator.OpType)type); + return Mono.CSharp.Operator.GetName ((Mono.CSharp.Operator.OpType)type); } public override NodeType NodeType { @@ -136,15 +135,15 @@ namespace ICSharpCode.NRefactory.CSharp } public string Name { - get { return GetName(this.OperatorType); } + get { return GetName (this.OperatorType); } } - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) { OperatorDeclaration o = other as OperatorDeclaration; - return o != null && this.MatchAttributesAndModifiers(o, match) && this.OperatorType == o.OperatorType - && this.ReturnType.DoMatch(o.ReturnType, match) - && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + return o != null && this.MatchAttributesAndModifiers (o, match) && this.OperatorType == o.OperatorType + && this.ReturnType.DoMatch (o.ReturnType, match) + && this.Parameters.DoMatch (o.Parameters, match) && this.Body.DoMatch (o.Body, match); } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs index 5544c5aa77..287611ef69 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs @@ -1,4 +1,4 @@ -// +// // ParameterDeclarationExpression.cs // // Author: @@ -68,7 +68,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs index c90d172c15..6e1d572727 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs @@ -1,4 +1,4 @@ -// +// // VariableInitializer.cs // // Author: @@ -85,7 +85,16 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier(value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs new file mode 100644 index 0000000000..2b08ae116d --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs @@ -0,0 +1,1608 @@ +// +// AstFormattingVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.CSharp.Refactoring; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class AstFormattingVisitor : DepthFirstAstVisitor + { + CSharpFormattingOptions policy; + ITextEditorAdapter data; + IActionFactory factory; + List changes = new List (); + Indent curIndent = new Indent (); + + public int IndentLevel { + get { + return curIndent.Level; + } + set { + curIndent.Level = value; + } + } + + public int CurrentSpaceIndents { + get; + set; + } + + public List Changes { + get { return this.changes; } + } + + public bool CorrectBlankLines { + get; + set; + } + + public bool HadErrors { + get; + set; + } + + public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data, IActionFactory factory) + { + if (factory == null) + throw new ArgumentNullException ("factory"); + this.policy = policy; + this.data = data; + this.curIndent.TabsToSpaces = this.data.TabsToSpaces; + this.curIndent.TabSize = this.data.TabSize; + this.factory = factory; + CorrectBlankLines = true; + } + + public override object VisitCompilationUnit (CompilationUnit unit, object data) + { + base.VisitCompilationUnit (unit, data); + return null; + } + + public void EnsureBlankLinesAfter (AstNode node, int blankLines) + { + if (!CorrectBlankLines) + return; + var loc = node.EndLocation; + int line = loc.Line; + do { + line++; + } while (line < data.LineCount && data.GetEditableLength (line) == data.GetIndentation (line).Length); + var start = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + + int foundBlankLines = line - loc.Line - 1; + + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < blankLines - foundBlankLines; i++) + sb.Append (data.EolMarker); + + int ws = start; + while (ws < data.Length && IsSpacing (data.GetCharAt (ws))) + ws++; + int removedChars = ws - start; + if (foundBlankLines > blankLines) + removedChars += data.GetLineEndOffset (loc.Line + foundBlankLines - blankLines) - data.GetLineEndOffset (loc.Line); + AddChange (start, removedChars, sb.ToString ()); + } + + public void EnsureBlankLinesBefore (AstNode node, int blankLines) + { + if (!CorrectBlankLines) + return; + var loc = node.StartLocation; + int line = loc.Line; + do { + line--; + } while (line > 0 && data.GetEditableLength (line) == data.GetIndentation (line).Length); + int end = data.GetLineOffset (loc.Line); + int start = line >= 1 ? data.GetLineEndOffset (line) : 0; + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < blankLines; i++) + sb.Append (data.EolMarker); + AddChange (start, end - start, sb.ToString ()); + } + + public override object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) + { + if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) + EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); + if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) + EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); + + return null; + } + + public override object VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, object data) + { + if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) + EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); + if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) + EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); + return null; + } + + public override object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) + { + var firstNsMember = namespaceDeclaration.Members.FirstOrDefault (); + if (firstNsMember != null) + EnsureBlankLinesBefore (firstNsMember, policy.BlankLinesBeforeFirstDeclaration); + FixIndentationForceNewLine (namespaceDeclaration.StartLocation); + EnforceBraceStyle (policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken, namespaceDeclaration.RBraceToken); + if (policy.IndentNamespaceBody) + IndentLevel++; + object result = base.VisitNamespaceDeclaration (namespaceDeclaration, data); + if (policy.IndentNamespaceBody) + IndentLevel--; + FixIndentation (namespaceDeclaration.RBraceToken.StartLocation); + return result; + } + + public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) + { + FixIndentationForceNewLine (typeDeclaration.StartLocation); + BraceStyle braceStyle; + bool indentBody = false; + switch (typeDeclaration.ClassType) { + case ClassType.Class: + braceStyle = policy.ClassBraceStyle; + indentBody = policy.IndentClassBody; + break; + case ClassType.Struct: + braceStyle = policy.StructBraceStyle; + indentBody = policy.IndentStructBody; + break; + case ClassType.Interface: + braceStyle = policy.InterfaceBraceStyle; + indentBody = policy.IndentInterfaceBody; + break; + case ClassType.Enum: + braceStyle = policy.EnumBraceStyle; + indentBody = policy.IndentEnumBody; + break; + default: + throw new InvalidOperationException ("unsupported class type : " + typeDeclaration.ClassType); + } + EnforceBraceStyle (braceStyle, typeDeclaration.LBraceToken, typeDeclaration.RBraceToken); + + if (indentBody) + IndentLevel++; + object result = base.VisitTypeDeclaration (typeDeclaration, data); + if (indentBody) + IndentLevel--; + + if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration) + EnsureBlankLinesAfter (typeDeclaration, policy.BlankLinesBetweenTypes); + return result; + } + + bool IsSimpleAccessor (Accessor accessor) + { + if (accessor.IsNull || accessor.Body.IsNull || accessor.Body.FirstChild == null) + return true; + if (accessor.Body.Statements.Count () != 1) + return false; + return !(accessor.Body.Statements.FirstOrDefault () is BlockStatement); + + } + + bool IsSpacing (char ch) + { + return ch == ' ' || ch == '\t'; + } + + int SearchLastNonWsChar (int startOffset, int endOffset) + { + startOffset = System.Math.Max (0, startOffset); + endOffset = System.Math.Max (startOffset, endOffset); + if (startOffset >= endOffset) + return startOffset; + int result = -1; + bool inComment = false; + + for (int i = startOffset; i < endOffset && i < data.Length; i++) { + char ch = data.GetCharAt (i); + if (IsSpacing (ch)) + continue; + if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') + return result; + if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '*') { + inComment = true; + i++; + continue; + } + if (inComment && ch == '*' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') { + inComment = false; + i++; + continue; + } + if (!inComment) + result = i; + } + return result; + } + + void ForceSpace (int startOffset, int endOffset, bool forceSpace) + { + int lastNonWs = SearchLastNonWsChar (startOffset, endOffset); + AddChange (lastNonWs + 1, System.Math.Max (0, endOffset - lastNonWs - 1), forceSpace ? " " : ""); + } +// void ForceSpacesAfter (AstNode n, bool forceSpaces) +// { +// if (n == null) +// return; +// AstLocation location = n.EndLocation; +// int offset = data.LocationToOffset (location.Line, location.Column); +// int i = offset; +// while (i < data.Length && IsSpacing (data.GetCharAt (i))) { +// i++; +// } +// ForceSpace (offset - 1, i, forceSpaces); +// } + + void ForceSpacesAfter (AstNode n, bool forceSpaces) + { + if (n == null) + return; + AstLocation location = n.EndLocation; + int offset = data.LocationToOffset (location.Line, location.Column); + if (location.Column > data.GetEditableLength (location.Line)) + return; + int i = offset; + while (i < data.Length && IsSpacing (data.GetCharAt (i))) { + i++; + } + ForceSpace (offset - 1, i, forceSpaces); + } + +// int ForceSpacesBefore (AstNode n, bool forceSpaces) +// { +// if (n == null || n.IsNull) +// return 0; +// AstLocation location = n.StartLocation; +// +// int offset = data.LocationToOffset (location.Line, location.Column); +// int i = offset - 1; +// +// while (i >= 0 && IsSpacing (data.GetCharAt (i))) { +// i--; +// } +// ForceSpace (i, offset, forceSpaces); +// return i; +// } + + int ForceSpacesBefore (AstNode n, bool forceSpaces) + { + if (n == null || n.IsNull) + return 0; + AstLocation location = n.StartLocation; + // respect manual line breaks. + if (location.Column <= 1 || data.GetIndentation (location.Line).Length == location.Column - 1) + return 0; + + int offset = data.LocationToOffset (location.Line, location.Column); + int i = offset - 1; + while (i >= 0 && IsSpacing (data.GetCharAt (i))) { + i--; + } + ForceSpace (i, offset, forceSpaces); + return i; + } + + public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) + { + FixIndentationForceNewLine (propertyDeclaration.StartLocation); + bool oneLine = false; + switch (policy.PropertyFormatting) { + case PropertyFormatting.AllowOneLine: + bool isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); + if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != propertyDeclaration.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + } else { + ForceSpacesBefore (propertyDeclaration.Getter, true); + ForceSpacesBefore (propertyDeclaration.Setter, true); + ForceSpacesBefore (propertyDeclaration.RBraceToken, true); + oneLine = true; + } + break; + case PropertyFormatting.ForceNewLine: + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + break; + case PropertyFormatting.ForceOneLine: + isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); + if (isSimple) { + int offset = this.data.LocationToOffset (propertyDeclaration.LBraceToken.StartLocation.Line, propertyDeclaration.LBraceToken.StartLocation.Column); + + int start = SearchWhitespaceStart (offset); + int end = SearchWhitespaceEnd (offset); + AddChange (start, offset - start, " "); + AddChange (offset + 1, end - offset - 2, " "); + + offset = this.data.LocationToOffset (propertyDeclaration.RBraceToken.StartLocation.Line, propertyDeclaration.RBraceToken.StartLocation.Column); + start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + oneLine = true; + + } else { + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + } + break; + } + if (policy.IndentPropertyBody) + IndentLevel++; + ///System.Console.WriteLine ("one line: " + oneLine); + if (!propertyDeclaration.Getter.IsNull) { + if (!oneLine) { + if (!IsLineIsEmptyUpToEol (propertyDeclaration.Getter.StartLocation)) { + int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + string indentString = this.curIndent.IndentString; + AddChange (start, offset - start, this.data.EolMarker + indentString); + } else { + FixIndentation (propertyDeclaration.Getter.StartLocation); + } + } else { + int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + + ForceSpacesBefore (propertyDeclaration.Getter.Body.LBraceToken, true); + ForceSpacesBefore (propertyDeclaration.Getter.Body.RBraceToken, true); + } + if (!propertyDeclaration.Getter.Body.IsNull) { + if (!policy.AllowPropertyGetBlockInline || propertyDeclaration.Getter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyGetBraceStyle, propertyDeclaration.Getter.Body.LBraceToken, propertyDeclaration.Getter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (propertyDeclaration.Getter.Body, policy.IndentBlocks, data); + } + } + + if (!propertyDeclaration.Setter.IsNull) { + if (!oneLine) { + if (!IsLineIsEmptyUpToEol (propertyDeclaration.Setter.StartLocation)) { + int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + string indentString = this.curIndent.IndentString; + AddChange (start, offset - start, this.data.EolMarker + indentString); + } else { + FixIndentation (propertyDeclaration.Setter.StartLocation); + } + } else { + int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + + ForceSpacesBefore (propertyDeclaration.Setter.Body.LBraceToken, true); + ForceSpacesBefore (propertyDeclaration.Setter.Body.RBraceToken, true); + } + if (!propertyDeclaration.Setter.Body.IsNull) { + if (!policy.AllowPropertySetBlockInline || propertyDeclaration.Setter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertySetBraceStyle, propertyDeclaration.Setter.Body.LBraceToken, propertyDeclaration.Setter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (propertyDeclaration.Setter.Body, policy.IndentBlocks, data); + } + } + + if (policy.IndentPropertyBody) + IndentLevel--; + if (IsMember (propertyDeclaration.NextSibling)) + EnsureBlankLinesAfter (propertyDeclaration, policy.BlankLinesBetweenMembers); + return null; + } + + public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) + { + ForceSpacesBefore (indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket); + ForceSpacesAfter (indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket); + ForceSpacesBefore (indexerDeclaration.RBracketToken, policy.SpaceWithinIndexerDeclarationBracket); + + FormatCommas (indexerDeclaration, policy.SpaceBeforeIndexerDeclarationParameterComma, policy.SpaceAfterIndexerDeclarationParameterComma); + + + FixIndentationForceNewLine (indexerDeclaration.StartLocation); + EnforceBraceStyle (policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken); + if (policy.IndentPropertyBody) + IndentLevel++; + + if (!indexerDeclaration.Getter.IsNull) { + FixIndentation (indexerDeclaration.Getter.StartLocation); + if (!indexerDeclaration.Getter.Body.IsNull) { + if (!policy.AllowPropertyGetBlockInline || indexerDeclaration.Getter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyGetBraceStyle, indexerDeclaration.Getter.Body.LBraceToken, indexerDeclaration.Getter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (indexerDeclaration.Getter.Body, policy.IndentBlocks, data); + } + } + + if (!indexerDeclaration.Setter.IsNull) { + FixIndentation (indexerDeclaration.Setter.StartLocation); + if (!indexerDeclaration.Setter.Body.IsNull) { + if (!policy.AllowPropertySetBlockInline || indexerDeclaration.Setter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertySetBraceStyle, indexerDeclaration.Setter.Body.LBraceToken, indexerDeclaration.Setter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (indexerDeclaration.Setter.Body, policy.IndentBlocks, data); + } + } + if (policy.IndentPropertyBody) + IndentLevel--; + if (IsMember (indexerDeclaration.NextSibling)) + EnsureBlankLinesAfter (indexerDeclaration, policy.BlankLinesBetweenMembers); + return null; + } + + static bool IsSimpleEvent (AstNode node) + { + return node is EventDeclaration; + } + + public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data) + { + FixIndentationForceNewLine (eventDeclaration.StartLocation); + EnforceBraceStyle (policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken); + if (policy.IndentEventBody) + IndentLevel++; + + if (!eventDeclaration.AddAccessor.IsNull) { + FixIndentation (eventDeclaration.AddAccessor.StartLocation); + if (!eventDeclaration.AddAccessor.Body.IsNull) { + if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBraceToken, eventDeclaration.AddAccessor.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + + VisitBlockWithoutFixIndentation (eventDeclaration.AddAccessor.Body, policy.IndentBlocks, data); + } + } + + if (!eventDeclaration.RemoveAccessor.IsNull) { + FixIndentation (eventDeclaration.RemoveAccessor.StartLocation); + if (!eventDeclaration.RemoveAccessor.Body.IsNull) { + if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBraceToken, eventDeclaration.RemoveAccessor.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks, data); + } + } + + if (policy.IndentEventBody) + IndentLevel--; + + if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); + } else if (IsMember (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers); + } + return null; + } + + public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) + { + FixIndentationForceNewLine (eventDeclaration.StartLocation); + if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); + } else if (IsMember (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers); + } + return null; + } + + public override object VisitAccessor (Accessor accessor, object data) + { + FixIndentationForceNewLine (accessor.StartLocation); + object result = base.VisitAccessor (accessor, data); + return result; + } + + public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) + { + FixIndentationForceNewLine (fieldDeclaration.StartLocation); + FormatCommas (fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); + if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) { + EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenFields); + } else if (IsMember (fieldDeclaration.NextSibling)) { + EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenMembers); + } + return base.VisitFieldDeclaration (fieldDeclaration, data); + } + + public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) + { + FixIndentationForceNewLine (fixedFieldDeclaration.StartLocation); + FormatCommas (fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); + if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) { + EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenFields); + } else if (IsMember (fixedFieldDeclaration.NextSibling)) { + EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenMembers); + } + return base.VisitFixedFieldDeclaration (fixedFieldDeclaration, data); + } + + public override object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) + { + FixIndentationForceNewLine (enumMemberDeclaration.StartLocation); + return base.VisitEnumMemberDeclaration (enumMemberDeclaration, data); + } + + public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) + { + FixIndentation (delegateDeclaration.StartLocation); + + ForceSpacesBefore (delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses); + if (delegateDeclaration.Parameters.Any ()) { + ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses); + ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses); + } else { + ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); + ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); + } + FormatCommas (delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma); + + if (delegateDeclaration.NextSibling is TypeDeclaration || delegateDeclaration.NextSibling is DelegateDeclaration) { + EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenTypes); + } else if (IsMember (delegateDeclaration.NextSibling)) { + EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenMembers); + } + + return base.VisitDelegateDeclaration (delegateDeclaration, data); + } + + static bool IsMember (AstNode nextSibling) + { + return nextSibling != null && nextSibling.NodeType == NodeType.Member; + } + + public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) + { + FixIndentationForceNewLine (methodDeclaration.StartLocation); + + ForceSpacesBefore (methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); + if (methodDeclaration.Parameters.Any ()) { + ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); + ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); + } else { + ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + } + FormatCommas (methodDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); + + if (!methodDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + base.VisitBlockStatement (methodDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (methodDeclaration.NextSibling)) + EnsureBlankLinesAfter (methodDeclaration, policy.BlankLinesBetweenMembers); + + return null; + } + + public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) + { + FixIndentationForceNewLine (operatorDeclaration.StartLocation); + + ForceSpacesBefore (operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); + if (operatorDeclaration.Parameters.Any ()) { + ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); + ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); + } else { + ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + } + FormatCommas (operatorDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); + + if (!operatorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + base.VisitBlockStatement (operatorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (operatorDeclaration.NextSibling)) + EnsureBlankLinesAfter (operatorDeclaration, policy.BlankLinesBetweenMembers); + + return null; + } + + public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) + { + FixIndentationForceNewLine (constructorDeclaration.StartLocation); + + ForceSpacesBefore (constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses); + if (constructorDeclaration.Parameters.Any ()) { + ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses); + ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceWithinConstructorDeclarationParentheses); + } else { + ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); + ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); + } + FormatCommas (constructorDeclaration, policy.SpaceBeforeConstructorDeclarationParameterComma, policy.SpaceAfterConstructorDeclarationParameterComma); + + object result = null; + if (!constructorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + result = base.VisitBlockStatement (constructorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (constructorDeclaration.NextSibling)) + EnsureBlankLinesAfter (constructorDeclaration, policy.BlankLinesBetweenMembers); + return result; + } + + public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) + { + FixIndentationForceNewLine (destructorDeclaration.StartLocation); + + CSharpTokenNode lParen = destructorDeclaration.LParToken; + int offset = this.data.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column); + ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses); + + object result = null; + if (!destructorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + result = base.VisitBlockStatement (destructorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (destructorDeclaration.NextSibling)) + EnsureBlankLinesAfter (destructorDeclaration, policy.BlankLinesBetweenMembers); + return result; + } + + #region Statements + public override object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) + { + FixStatementIndentation (expressionStatement.StartLocation); + FixSemicolon (expressionStatement.SemicolonToken); + return base.VisitExpressionStatement (expressionStatement, data); + } + + object VisitBlockWithoutFixIndentation (BlockStatement blockStatement, bool indent, object data) + { + if (indent) + IndentLevel++; + object result = base.VisitBlockStatement (blockStatement, data); + if (indent) + IndentLevel--; + return result; + } + + public override object VisitBlockStatement (BlockStatement blockStatement, object data) + { + FixIndentation (blockStatement.StartLocation); + object result = VisitBlockWithoutFixIndentation (blockStatement, policy.IndentBlocks, data); + FixIndentation (blockStatement.EndLocation, -1); + return result; + } + + public override object VisitComment (Comment comment, object data) + { + if (comment.StartsLine && !HadErrors && comment.StartLocation.Column > 1) + FixIndentation (comment.StartLocation); + return null; + } + + public override object VisitBreakStatement (BreakStatement breakStatement, object data) + { + FixStatementIndentation (breakStatement.StartLocation); + return null; + } + + public override object VisitCheckedStatement (CheckedStatement checkedStatement, object data) + { + FixStatementIndentation (checkedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body); + } + + public override object VisitContinueStatement (ContinueStatement continueStatement, object data) + { + FixStatementIndentation (continueStatement.StartLocation); + return null; + } + + public override object VisitEmptyStatement (EmptyStatement emptyStatement, object data) + { + FixStatementIndentation (emptyStatement.StartLocation); + return null; + } + + public override object VisitFixedStatement (FixedStatement fixedStatement, object data) + { + FixStatementIndentation (fixedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement); + } + + public override object VisitForeachStatement (ForeachStatement foreachStatement, object data) + { + FixStatementIndentation (foreachStatement.StartLocation); + ForceSpacesBefore (foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses); + + ForceSpacesAfter (foreachStatement.LParToken, policy.SpacesWithinForeachParentheses); + ForceSpacesBefore (foreachStatement.RParToken, policy.SpacesWithinForeachParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement); + } + + object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, AstNode node) + { + return FixEmbeddedStatment (braceStyle, braceForcement, null, false, node); + } + + object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node) + { + if (node == null) + return null; + int originalLevel = curIndent.Level; + bool isBlock = node is BlockStatement; + switch (braceForcement) { + case BraceForcement.DoNotChange: + //nothing + break; + case BraceForcement.AddBraces: + if (!isBlock) { + AstNode n = node.Parent.GetCSharpNodeBefore (node); + int start = data.LocationToOffset (n.EndLocation.Line, n.EndLocation.Column); + var next = n.GetNextNode (); + int offset = data.LocationToOffset (next.StartLocation.Line, next.StartLocation.Column); + string startBrace = ""; + switch (braceStyle) { + case BraceStyle.EndOfLineWithoutSpace: + startBrace = "{"; + break; + case BraceStyle.EndOfLine: + startBrace = " {"; + break; + case BraceStyle.NextLine: + startBrace = data.EolMarker + curIndent.IndentString + "{"; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; + break; + } + if (IsLineIsEmptyUpToEol (data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column))) + startBrace += data.EolMarker + data.GetIndentation (node.StartLocation.Line); + AddChange (start, offset - start, startBrace); + } + break; + case BraceForcement.RemoveBraces: + if (isBlock) { + BlockStatement block = node as BlockStatement; + if (block.Statements.Count () == 1) { + int offset1 = data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column); + int start = SearchWhitespaceStart (offset1); + + int offset2 = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + int end = SearchWhitespaceStart (offset2 - 1); + + AddChange (start, offset1 - start + 1, null); + AddChange (end + 1, offset2 - end, null); + node = block.FirstChild; + isBlock = false; + } + } + break; + } + if (isBlock) { + BlockStatement block = node as BlockStatement; + if (allowInLine && block.StartLocation.Line == block.EndLocation.Line && block.Statements.Count () <= 1) { + if (block.Statements.Count () == 1) + nextStatementIndent = " "; + } else { + EnforceBraceStyle (braceStyle, block.LBraceToken, block.RBraceToken); + } + if (braceStyle == BraceStyle.NextLineShifted2) + curIndent.Level++; + } else { + if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) { + nextStatementIndent = " "; + } + } + if (!(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || + policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) + curIndent.Level++; + object result = isBlock ? base.VisitBlockStatement ((BlockStatement)node, null) : node.AcceptVisitor (this, null); + curIndent.Level = originalLevel; + switch (braceForcement) { + case BraceForcement.DoNotChange: + break; + case BraceForcement.AddBraces: + if (!isBlock) { + int offset = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + if (!char.IsWhiteSpace (data.GetCharAt (offset))) + offset++; + string startBrace = ""; + switch (braceStyle) { + case BraceStyle.DoNotChange: + startBrace = null; + break; + case BraceStyle.EndOfLineWithoutSpace: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.EndOfLine: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.NextLine: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; + break; + } + if (startBrace != null) + AddChange (offset, 0, startBrace); + } + break; + } + return result; + } + + void EnforceBraceStyle (BraceStyle braceStyle, AstNode lbrace, AstNode rbrace) + { + if (lbrace.IsNull || rbrace.IsNull) + return; + +// LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line); + int lbraceOffset = data.LocationToOffset (lbrace.StartLocation.Line, lbrace.StartLocation.Column); + +// LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line); + int rbraceOffset = data.LocationToOffset (rbrace.StartLocation.Line, rbrace.StartLocation.Column); + int whitespaceStart = SearchWhitespaceStart (lbraceOffset); + int whitespaceEnd = SearchWhitespaceLineStart (rbraceOffset); + string startIndent = ""; + string endIndent = ""; + switch (braceStyle) { + case BraceStyle.DoNotChange: + startIndent = endIndent = null; + break; + case BraceStyle.EndOfLineWithoutSpace: + startIndent = ""; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.EndOfLine: + var prevNode = lbrace.GetPrevNode (); + if (prevNode is Comment) { + // delete old bracket + AddChange (whitespaceStart, lbraceOffset - whitespaceStart + 1, ""); + + while (prevNode is Comment) { + prevNode = prevNode.GetPrevNode (); + } + whitespaceStart = data.LocationToOffset (prevNode.EndLocation.Line, prevNode.EndLocation.Column); + lbraceOffset = whitespaceStart; + startIndent = " {"; + } else { + startIndent = " "; + } + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.NextLine: + startIndent = data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startIndent = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + break; + } + + if (lbraceOffset > 0 && startIndent != null) + AddChange (whitespaceStart, lbraceOffset - whitespaceStart, startIndent); + if (rbraceOffset > 0 && endIndent != null) + AddChange (whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent); + } + + void AddChange (int offset, int removedChars, string insertedText) + { + if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars + && c.InsertedText == insertedText)) + return; + string currentText = data.GetTextAt (offset, removedChars); + if (currentText == insertedText) + return; + if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}'))) + throw new InvalidOperationException ("Tried to remove non ws chars: '" + currentText + "'"); + foreach (var change in changes) { + if (change.Offset == offset) { + if (removedChars > 0 && insertedText == change.InsertedText) { + change.RemovedChars = removedChars; +// change.InsertedText = insertedText; + return; + } + if (!string.IsNullOrEmpty (change.InsertedText)) { + change.InsertedText += insertedText; + } else { + change.InsertedText = insertedText; + } + change.RemovedChars = System.Math.Max (removedChars, change.RemovedChars); + return; + } + } + //Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "" : insertedText.Replace ("\n", "\\n").Replace ("\t", "\\t").Replace (" ", ".")); + //Console.WriteLine (Environment.StackTrace); + + changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText)); + } + + public bool IsLineIsEmptyUpToEol (AstLocation startLocation) + { + return IsLineIsEmptyUpToEol (data.LocationToOffset (startLocation.Line, startLocation.Column) - 1); + } + + bool IsLineIsEmptyUpToEol (int startOffset) + { + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (ch != ' ' && ch != '\t') + return ch == '\n' || ch == '\r'; + } + return true; + } + + int SearchWhitespaceStart (int startOffset) + { + if (startOffset < 0) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (!Char.IsWhiteSpace (ch)) { + return offset + 1; + } + } + return 0; + } + + int SearchWhitespaceEnd (int startOffset) + { + if (startOffset > data.Length) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset + 1; offset < data.Length; offset++) { + char ch = data.GetCharAt (offset); + if (!Char.IsWhiteSpace (ch)) { + return offset + 1; + } + } + return data.Length - 1; + } + + int SearchWhitespaceLineStart (int startOffset) + { + if (startOffset < 0) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (ch != ' ' && ch != '\t') { + return offset + 1; + } + } + return 0; + } + + public override object VisitForStatement (ForStatement forStatement, object data) + { + FixStatementIndentation (forStatement.StartLocation); + foreach (AstNode node in forStatement.Children) { + if (node.Role == ForStatement.Roles.Semicolon) { + if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement) + continue; + ForceSpacesBefore (node, policy.SpaceBeforeForSemicolon); + ForceSpacesAfter (node, policy.SpaceAfterForSemicolon); + } + } + + ForceSpacesBefore (forStatement.LParToken, policy.SpaceBeforeForParentheses); + + ForceSpacesAfter (forStatement.LParToken, policy.SpacesWithinForParentheses); + ForceSpacesBefore (forStatement.RParToken, policy.SpacesWithinForParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement); + } + + public override object VisitGotoStatement (GotoStatement gotoStatement, object data) + { + FixStatementIndentation (gotoStatement.StartLocation); + return VisitChildren (gotoStatement, data); + } + + public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + { + ForceSpacesBefore (ifElseStatement.LParToken, policy.SpaceBeforeIfParentheses); + + ForceSpacesAfter (ifElseStatement.LParToken, policy.SpacesWithinIfParentheses); + ForceSpacesBefore (ifElseStatement.RParToken, policy.SpacesWithinIfParentheses); + + if (!(ifElseStatement.Parent is IfElseStatement && ((IfElseStatement)ifElseStatement.Parent).FalseStatement == ifElseStatement)) + FixStatementIndentation (ifElseStatement.StartLocation); + + if (!ifElseStatement.Condition.IsNull) + ifElseStatement.Condition.AcceptVisitor (this, data); + + if (!ifElseStatement.TrueStatement.IsNull) + FixEmbeddedStatment (policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement); + + if (!ifElseStatement.FalseStatement.IsNull) { + PlaceOnNewLine (policy.PlaceElseOnNewLine || !(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces, ifElseStatement.ElseToken); + var forcement = policy.IfElseBraceForcement; + if (ifElseStatement.FalseStatement is IfElseStatement) { + forcement = BraceForcement.DoNotChange; + PlaceOnNewLine (policy.PlaceElseIfOnNewLine, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken); + } + FixEmbeddedStatment (policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement); + } + + return null; + } + + public override object VisitLabelStatement (LabelStatement labelStatement, object data) + { + // TODO + return VisitChildren (labelStatement, data); + } + + public override object VisitLockStatement (LockStatement lockStatement, object data) + { + FixStatementIndentation (lockStatement.StartLocation); + ForceSpacesBefore (lockStatement.LParToken, policy.SpaceBeforeLockParentheses); + + ForceSpacesAfter (lockStatement.LParToken, policy.SpacesWithinLockParentheses); + ForceSpacesBefore (lockStatement.RParToken, policy.SpacesWithinLockParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement); + } + + public override object VisitReturnStatement (ReturnStatement returnStatement, object data) + { + FixStatementIndentation (returnStatement.StartLocation); + return VisitChildren (returnStatement, data); + } + + public override object VisitSwitchStatement (SwitchStatement switchStatement, object data) + { + FixStatementIndentation (switchStatement.StartLocation); + ForceSpacesBefore (switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses); + + ForceSpacesAfter (switchStatement.LParToken, policy.SpacesWithinSwitchParentheses); + ForceSpacesBefore (switchStatement.RParToken, policy.SpacesWithinSwitchParentheses); + + EnforceBraceStyle (policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken); + object result = VisitChildren (switchStatement, data); + return result; + } + + public override object VisitSwitchSection (SwitchSection switchSection, object data) + { + if (policy.IndentSwitchBody) + curIndent.Level++; + + foreach (CaseLabel label in switchSection.CaseLabels) { + FixStatementIndentation (label.StartLocation); + } + if (policy.IndentCaseBody) + curIndent.Level++; + + foreach (var stmt in switchSection.Statements) { + stmt.AcceptVisitor (this, null); + } + if (policy.IndentCaseBody) + curIndent.Level--; + + if (policy.IndentSwitchBody) + curIndent.Level--; + return null; + } + + public override object VisitCaseLabel (CaseLabel caseLabel, object data) + { + // handled in switchsection + return null; + } + + public override object VisitThrowStatement (ThrowStatement throwStatement, object data) + { + FixStatementIndentation (throwStatement.StartLocation); + return VisitChildren (throwStatement, data); + } + + public override object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) + { + FixStatementIndentation (tryCatchStatement.StartLocation); + + if (!tryCatchStatement.TryBlock.IsNull) + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock); + + foreach (CatchClause clause in tryCatchStatement.CatchClauses) { + PlaceOnNewLine (policy.PlaceCatchOnNewLine, clause.CatchToken); + if (!clause.LParToken.IsNull) { + ForceSpacesBefore (clause.LParToken, policy.SpaceBeforeCatchParentheses); + + ForceSpacesAfter (clause.LParToken, policy.SpacesWithinCatchParentheses); + ForceSpacesBefore (clause.RParToken, policy.SpacesWithinCatchParentheses); + } + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, clause.Body); + } + + if (!tryCatchStatement.FinallyBlock.IsNull) { + PlaceOnNewLine (policy.PlaceFinallyOnNewLine, tryCatchStatement.FinallyToken); + + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock); + } + + return VisitChildren (tryCatchStatement, data); + } + + public override object VisitCatchClause (CatchClause catchClause, object data) + { + // Handled in TryCatchStatement + return null; + } + + public override object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) + { + FixStatementIndentation (uncheckedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body); + } + + public override object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) + { + FixStatementIndentation (unsafeStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body); + } + + public override object VisitUsingStatement (UsingStatement usingStatement, object data) + { + FixStatementIndentation (usingStatement.StartLocation); + ForceSpacesBefore (usingStatement.LParToken, policy.SpaceBeforeUsingParentheses); + + ForceSpacesAfter (usingStatement.LParToken, policy.SpacesWithinUsingParentheses); + ForceSpacesBefore (usingStatement.RParToken, policy.SpacesWithinUsingParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement); + } + + public override object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) + { + if (!variableDeclarationStatement.SemicolonToken.IsNull) + FixStatementIndentation (variableDeclarationStatement.StartLocation); + + if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) { + ForceSpacesAround (variableDeclarationStatement.Type, true); + } else { + ForceSpacesAfter (variableDeclarationStatement.Type, true); + } + foreach (var initializer in variableDeclarationStatement.Variables) { + initializer.AcceptVisitor (this, data); + } + FormatCommas (variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma); + FixSemicolon (variableDeclarationStatement.SemicolonToken); + return null; + } + + public override object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) + { + FixStatementIndentation (doWhileStatement.StartLocation); + PlaceOnNewLine (policy.PlaceWhileOnNewLine, doWhileStatement.WhileToken); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, doWhileStatement.EmbeddedStatement); + } + + public override object VisitWhileStatement (WhileStatement whileStatement, object data) + { + FixStatementIndentation (whileStatement.StartLocation); + ForceSpacesBefore (whileStatement.LParToken, policy.SpaceBeforeWhileParentheses); + + ForceSpacesAfter (whileStatement.LParToken, policy.SpacesWithinWhileParentheses); + ForceSpacesBefore (whileStatement.RParToken, policy.SpacesWithinWhileParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, whileStatement.EmbeddedStatement); + } + + public override object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) + { + FixStatementIndentation (yieldBreakStatement.StartLocation); + return null; + } + + public override object VisitYieldStatement (YieldStatement yieldStatement, object data) + { + FixStatementIndentation (yieldStatement.StartLocation); + return null; + } + + public override object VisitVariableInitializer (VariableInitializer variableInitializer, object data) + { + if (!variableInitializer.AssignToken.IsNull) + ForceSpacesAround (variableInitializer.AssignToken, policy.SpaceAroundAssignment); + if (!variableInitializer.Initializer.IsNull) + variableInitializer.Initializer.AcceptVisitor (this, data); + return data; + } + + #endregion + + #region Expressions + public override object VisitComposedType (ComposedType composedType, object data) + { + var spec = composedType.ArraySpecifiers.FirstOrDefault (); + if (spec != null) + ForceSpacesBefore (spec.LBracketToken, policy.SpaceBeforeArrayDeclarationBrackets); + + return base.VisitComposedType (composedType, data); + } + + public override object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) + { + ForceSpacesAround (assignmentExpression.OperatorToken, policy.SpaceAroundAssignment); + return base.VisitAssignmentExpression (assignmentExpression, data); + } + + public override object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) + { + bool forceSpaces = false; + switch (binaryOperatorExpression.Operator) { + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + forceSpaces = policy.SpaceAroundEqualityOperator; + break; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThan: + case BinaryOperatorType.LessThanOrEqual: + forceSpaces = policy.SpaceAroundRelationalOperator; + break; + case BinaryOperatorType.ConditionalAnd: + case BinaryOperatorType.ConditionalOr: + forceSpaces = policy.SpaceAroundLogicalOperator; + break; + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + forceSpaces = policy.SpaceAroundBitwiseOperator; + break; + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + forceSpaces = policy.SpaceAroundAdditiveOperator; + break; + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + forceSpaces = policy.SpaceAroundMultiplicativeOperator; + break; + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + forceSpaces = policy.SpaceAroundShiftOperator; + break; + case BinaryOperatorType.NullCoalescing: + forceSpaces = policy.SpaceAroundNullCoalescingOperator; + break; + } + ForceSpacesAround (binaryOperatorExpression.OperatorToken, forceSpaces); + + return base.VisitBinaryOperatorExpression (binaryOperatorExpression, data); + } + + public override object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) + { + ForceSpacesBefore (conditionalExpression.QuestionMarkToken, policy.SpaceBeforeConditionalOperatorCondition); + ForceSpacesAfter (conditionalExpression.QuestionMarkToken, policy.SpaceAfterConditionalOperatorCondition); + ForceSpacesBefore (conditionalExpression.ColonToken, policy.SpaceBeforeConditionalOperatorSeparator); + ForceSpacesAfter (conditionalExpression.ColonToken, policy.SpaceAfterConditionalOperatorSeparator); + return base.VisitConditionalExpression (conditionalExpression, data); + } + + public override object VisitCastExpression (CastExpression castExpression, object data) + { + if (castExpression.RParToken != null) { + ForceSpacesAfter (castExpression.LParToken, policy.SpacesWithinCastParentheses); + ForceSpacesBefore (castExpression.RParToken, policy.SpacesWithinCastParentheses); + + ForceSpacesAfter (castExpression.RParToken, policy.SpaceAfterTypecast); + } + return base.VisitCastExpression (castExpression, data); + } + + void ForceSpacesAround (AstNode node, bool forceSpaces) + { + if (node.IsNull) + return; + ForceSpacesBefore (node, forceSpaces); + ForceSpacesAfter (node, forceSpaces); + } + + void FormatCommas (AstNode parent, bool before, bool after) + { + if (parent.IsNull) + return; + foreach (CSharpTokenNode comma in parent.Children.Where (node => node.Role == FieldDeclaration.Roles.Comma)) { + ForceSpacesAfter (comma, after); + ForceSpacesBefore (comma, before); + } + } + + public override object VisitInvocationExpression (InvocationExpression invocationExpression, object data) + { + ForceSpacesBefore (invocationExpression.LParToken, policy.SpaceBeforeMethodCallParentheses); + if (invocationExpression.Arguments.Any ()) { + ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceWithinMethodCallParentheses); + ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceWithinMethodCallParentheses); + } else { + ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses); + ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses); + } + FormatCommas (invocationExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); + + return base.VisitInvocationExpression (invocationExpression, data); + } + + public override object VisitIndexerExpression (IndexerExpression indexerExpression, object data) + { + ForceSpacesBefore (indexerExpression.LBracketToken, policy.SpacesBeforeBrackets); + ForceSpacesAfter (indexerExpression.LBracketToken, policy.SpacesWithinBrackets); + ForceSpacesBefore (indexerExpression.RBracketToken, policy.SpacesWithinBrackets); + FormatCommas (indexerExpression, policy.SpaceBeforeBracketComma, policy.SpaceAfterBracketComma); + + return base.VisitIndexerExpression (indexerExpression, data); + } + + public override object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) + { + ForceSpacesAfter (parenthesizedExpression.LParToken, policy.SpacesWithinParentheses); + ForceSpacesBefore (parenthesizedExpression.RParToken, policy.SpacesWithinParentheses); + return base.VisitParenthesizedExpression (parenthesizedExpression, data); + } + + public override object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) + { + ForceSpacesBefore (sizeOfExpression.LParToken, policy.SpaceBeforeSizeOfParentheses); + ForceSpacesAfter (sizeOfExpression.LParToken, policy.SpacesWithinSizeOfParentheses); + ForceSpacesBefore (sizeOfExpression.RParToken, policy.SpacesWithinSizeOfParentheses); + return base.VisitSizeOfExpression (sizeOfExpression, data); + } + + public override object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) + { + ForceSpacesBefore (typeOfExpression.LParToken, policy.SpaceBeforeTypeOfParentheses); + ForceSpacesAfter (typeOfExpression.LParToken, policy.SpacesWithinTypeOfParentheses); + ForceSpacesBefore (typeOfExpression.RParToken, policy.SpacesWithinTypeOfParentheses); + return base.VisitTypeOfExpression (typeOfExpression, data); + } + + public override object VisitCheckedExpression (CheckedExpression checkedExpression, object data) + { + ForceSpacesAfter (checkedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); + ForceSpacesBefore (checkedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); + return base.VisitCheckedExpression (checkedExpression, data); + } + + public override object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) + { + ForceSpacesAfter (uncheckedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); + ForceSpacesBefore (uncheckedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); + return base.VisitUncheckedExpression (uncheckedExpression, data); + } + + public override object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) + { + ForceSpacesBefore (objectCreateExpression.LParToken, policy.SpaceBeforeNewParentheses); + + if (objectCreateExpression.Arguments.Any ()) { + if (!objectCreateExpression.LParToken.IsNull) + ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesWithinNewParentheses); + if (!objectCreateExpression.RParToken.IsNull) + ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesWithinNewParentheses); + } else { + if (!objectCreateExpression.LParToken.IsNull) + ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesBetweenEmptyNewParentheses); + if (!objectCreateExpression.RParToken.IsNull) + ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesBetweenEmptyNewParentheses); + } + FormatCommas (objectCreateExpression, policy.SpaceBeforeNewParameterComma, policy.SpaceAfterNewParameterComma); + + return base.VisitObjectCreateExpression (objectCreateExpression, data); + } + + public override object VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, object data) + { + FormatCommas (arrayObjectCreateExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); + return base.VisitArrayCreateExpression (arrayObjectCreateExpression, data); + } + + public override object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) + { + ForceSpacesAfter (lambdaExpression.ArrowToken, true); + ForceSpacesBefore (lambdaExpression.ArrowToken, true); + + return base.VisitLambdaExpression (lambdaExpression, data); + } + + #endregion + + void ForceSpaceBefore (int offset, bool forceSpace) + { + bool insertedSpace = false; + do { + char ch = data.GetCharAt (offset); + //Console.WriteLine (ch); + if (!IsSpacing (ch) && (insertedSpace || !forceSpace)) + break; + if (ch == ' ' && forceSpace) { + if (insertedSpace) { + AddChange (offset, 1, null); + } else { + insertedSpace = true; + } + } else if (forceSpace) { + if (!insertedSpace) { + AddChange (offset, IsSpacing (ch) ? 1 : 0, " "); + insertedSpace = true; + } else if (IsSpacing (ch)) { + AddChange (offset, 1, null); + } + } + + offset--; + } while (offset >= 0); + } + + + + /* + int GetLastNonWsChar (LineSegment line, int lastColumn) + { + int result = -1; + bool inComment = false; + for (int i = 0; i < lastColumn; i++) { + char ch = data.GetCharAt (line.Offset + i); + if (Char.IsWhiteSpace (ch)) + continue; + if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') + return result; + if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '*') { + inComment = true; + i++; + continue; + } + if (inComment && ch == '*' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') { + inComment = false; + i++; + continue; + } + if (!inComment) + result = i; + } + return result; + } + */ + + + public void FixSemicolon (CSharpTokenNode semicolon) + { + if (semicolon.IsNull) + return; + int endOffset = data.LocationToOffset (semicolon.StartLocation.Line, semicolon.StartLocation.Column); + int offset = endOffset; + while (offset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (offset - 1))) { + offset--; + } + if (offset < endOffset) { + AddChange (offset, endOffset - offset, null); + } + } + + void PlaceOnNewLine (bool newLine, AstNode keywordNode) + { + if (keywordNode == null) + return; + int offset = data.LocationToOffset (keywordNode.StartLocation.Line, keywordNode.StartLocation.Column); + + int whitespaceStart = SearchWhitespaceStart (offset); + string indentString = newLine ? data.EolMarker + this.curIndent.IndentString : " "; + AddChange (whitespaceStart, offset - whitespaceStart, indentString); + } + + string nextStatementIndent = null; + + void FixStatementIndentation (AstLocation location) + { + int offset = data.LocationToOffset (location.Line, location.Column); + if (offset <= 0) { + Console.WriteLine ("possible wrong offset"); + Console.WriteLine (Environment.StackTrace); + return; + } + bool isEmpty = IsLineIsEmptyUpToEol (offset); + int lineStart = SearchWhitespaceLineStart (offset); + string indentString = nextStatementIndent == null ? (isEmpty ? "" : data.EolMarker) + this.curIndent.IndentString : nextStatementIndent; + nextStatementIndent = null; + AddChange (lineStart, offset - lineStart, indentString); + } + + void FixIndentation (AstLocation location) + { + FixIndentation (location, 0); + } + + void FixIndentation (AstLocation location, int relOffset) + { + if (location.Line < 1 || location.Line > data.LineCount) { + Console.WriteLine ("Invalid location " + location); + Console.WriteLine (Environment.StackTrace); + return; + } + + string lineIndent = data.GetIndentation (location.Line); + string indentString = this.curIndent.IndentString; + if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) { + AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + } + } + + void FixIndentationForceNewLine (AstLocation location) + { + string lineIndent = data.GetIndentation (location.Line); + string indentString = this.curIndent.IndentString; + if (location.Column - 1 == lineIndent.Length) { + AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + } else { + int offset = data.LocationToOffset (location.Line, location.Column); + int start = SearchWhitespaceLineStart (offset); + if (start > 0) { + char ch = data.GetCharAt (start - 1); + if (ch == '\n') { + start--; + if (start > 1 && data.GetCharAt (start - 1) == '\r') + start--; + } else if (ch == '\r') { + start--; + } + AddChange (start, offset - start, data.EolMarker + indentString); + } + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Change.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Change.cs new file mode 100644 index 0000000000..f2a241c1dd --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Change.cs @@ -0,0 +1,72 @@ +// +// Change.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory +{ + public class Change + { + public int Offset { + get; + set; + } + + int removedChars; + public int RemovedChars { + get { + return removedChars; + } + set { + if (value < 0) + throw new ArgumentOutOfRangeException ("RemovedChars", "needs to be >= 0"); + removedChars = value; + } + } + + public string InsertedText { + get; + set; + } + + public Change (int offset, int removedChars, string insertedText) + { + if (removedChars < 0) + throw new ArgumentOutOfRangeException ("removedChars", "removedChars needs to be >= 0"); + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "offset needs to be >= 0"); + this.removedChars = removedChars; + this.Offset = offset; + this.InsertedText = insertedText; + } + + public override string ToString () + { + return string.Format ("[Change: Offset={0}, RemovedChars={1}, InsertedText={2}]", Offset, RemovedChars, InsertedText); + } + } + +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs new file mode 100644 index 0000000000..4568f8736e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs @@ -0,0 +1,83 @@ +// +// ITextEditorAdapter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory +{ + public interface ITextEditorAdapter + { + bool TabsToSpaces { get; } + + int TabSize { get; } + + string EolMarker { get; } + + string Text { get; } + + int Length { get; } + + int LocationToOffset (int line, int col); + char GetCharAt (int offset); + string GetTextAt (int offset, int length); + + int LineCount { get; } + + int GetEditableLength (int lineNumber); + string GetIndentation (int lineNumber); + int GetLineOffset (int lineNumber); + int GetLineLength (int lineNumber); + int GetLineEndOffset (int lineNumber); + + void Replace (int offset, int count, string text); + } + + /* + public static class ITextEditorAdapterHelperMethods + { + public static void AcceptChanges (this ITextEditorAdapter adapter, List changes) + { + for (int i = 0; i < changes.Count; i++) { + changes [i].PerformChange (adapter); + var replaceChange = changes [i]; + for (int j = i + 1; j < changes.Count; j++) { + var change = changes [j]; + if (replaceChange.Offset >= 0 && change.Offset >= 0) { + if (replaceChange.Offset < change.Offset) { + change.Offset -= replaceChange.RemovedChars; + if (!string.IsNullOrEmpty (replaceChange.InsertedText)) + change.Offset += replaceChange.InsertedText.Length; + } else if (replaceChange.Offset < change.Offset + change.RemovedChars) { + change.RemovedChars -= replaceChange.RemovedChars; + change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0); + } + } + } + } + } + }*/ +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs new file mode 100644 index 0000000000..017d8c9b49 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs @@ -0,0 +1,89 @@ +// +// Indent.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class Indent + { + public int Level { + get; + set; + } + + public int ExtraSpaces { + get; + set; + } + + public bool TabsToSpaces { + get; + set; + } + + public int TabSize { + get; + set; + } + + public Indent () + { + } + + public Indent (int level, int extraSpaces) + { + this.Level = level; + this.ExtraSpaces = extraSpaces; + } + + public static Indent operator+ (Indent left, Indent right) + { + return new Indent (left.Level + right.Level, left.ExtraSpaces + right.ExtraSpaces); + } + + public static Indent operator- (Indent left, Indent right) + { + return new Indent (left.Level - right.Level, left.ExtraSpaces - right.ExtraSpaces); + } + + public string IndentString { + get { + return (TabsToSpaces ? new string (' ', Level * TabSize) : new string ('\t', Level)) + new string (' ', ExtraSpaces); + } + } + + public string SingleIndent { + get { + return TabsToSpaces ? new string (' ', TabSize) : "\t"; + } + } + + public override string ToString () + { + return string.Format ("[Indent: Level={0}, ExtraSpaces={1}]", Level, ExtraSpaces); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 7a7d56f6b7..34589023dd 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -1,6 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) - using System; using System.Collections.Generic; using System.Diagnostics; @@ -21,9 +20,8 @@ namespace ICSharpCode.NRefactory.CSharp { readonly IOutputFormatter formatter; readonly CSharpFormattingOptions policy; - - readonly Stack containerStack = new Stack(); - readonly Stack positionStack = new Stack(); + readonly Stack containerStack = new Stack (); + readonly Stack positionStack = new Stack (); /// /// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written. @@ -42,47 +40,81 @@ namespace ICSharpCode.NRefactory.CSharp Division } - public OutputVisitor(TextWriter textWriter, CSharpFormattingOptions formattingPolicy) + public OutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy) { if (textWriter == null) - throw new ArgumentNullException("textWriter"); + throw new ArgumentNullException ("textWriter"); if (formattingPolicy == null) - throw new ArgumentNullException("formattingPolicy"); - this.formatter = new TextWriterOutputFormatter(textWriter); + throw new ArgumentNullException ("formattingPolicy"); + this.formatter = new TextWriterOutputFormatter (textWriter); this.policy = formattingPolicy; } - public OutputVisitor(IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) + public OutputVisitor (IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) { if (formatter == null) - throw new ArgumentNullException("formatter"); + throw new ArgumentNullException ("formatter"); if (formattingPolicy == null) - throw new ArgumentNullException("formattingPolicy"); + throw new ArgumentNullException ("formattingPolicy"); this.formatter = formatter; this.policy = formattingPolicy; } #region StartNode/EndNode - void StartNode(AstNode node) + public event EventHandler OutputStarted; + + protected virtual void OnOutputStarted (AstNodeEventArgs e) { - // Ensure that nodes are visited in the proper nested order. - // Jumps to different subtrees are allowed only for the child of a placeholder node. - Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek() || containerStack.Peek().NodeType == NodeType.Pattern); - if (positionStack.Count > 0) - WriteSpecialsUpToNode(node); - containerStack.Push(node); - positionStack.Push(node.FirstChild); - formatter.StartNode(node); + EventHandler handler = this.OutputStarted; + if (handler != null) + handler (this, e); + } + + public event EventHandler OutputFinished; + + protected virtual void OnOutputFinished (AstNodeEventArgs e) + { + EventHandler handler = this.OutputFinished; + if (handler != null) + handler (this, e); + } + + [Serializable] + public sealed class AstNodeEventArgs : EventArgs + { + public AstNode AstNode { + get; + private set; + } + + public AstNodeEventArgs (AstNode node) + { + this.AstNode = node; + } } - object EndNode(AstNode node) + void StartNode (AstNode node) { - Debug.Assert(node == containerStack.Peek()); - AstNode pos = positionStack.Pop(); - Debug.Assert(pos == null || pos.Parent == node); - WriteSpecials(pos, null); - containerStack.Pop(); - formatter.EndNode(node); + // Ensure that nodes are visited in the proper nested order. + // Jumps to different subtrees are allowed only for the child of a placeholder node. + Debug.Assert (containerStack.Count == 0 || node.Parent == containerStack.Peek () || containerStack.Peek ().NodeType == NodeType.Pattern); + if (positionStack.Count > 0) + WriteSpecialsUpToNode (node); + containerStack.Push (node); + positionStack.Push (node.FirstChild); + OnOutputStarted (new AstNodeEventArgs (node)); + formatter.StartNode (node); + } + + object EndNode (AstNode node) + { + Debug.Assert (node == containerStack.Peek ()); + AstNode pos = positionStack.Pop (); + Debug.Assert (pos == null || pos.Parent == node); + WriteSpecials (pos, null); + containerStack.Pop (); + OnOutputFinished (new AstNodeEventArgs (node)); + formatter.EndNode (node); return null; } #endregion @@ -91,11 +123,11 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Writes all specials from start to end (exclusive). Does not touch the positionStack. /// - void WriteSpecials(AstNode start, AstNode end) + void WriteSpecials (AstNode start, AstNode end) { for (AstNode pos = start; pos != end; pos = pos.NextSibling) { if (pos.Role == AstNode.Roles.Comment) { - pos.AcceptVisitor(this, null); + pos.AcceptVisitor (this, null); } } } @@ -104,12 +136,12 @@ namespace ICSharpCode.NRefactory.CSharp /// Writes all specials between the current position (in the positionStack) and the next /// node with the specified role. Advances the current position. /// - void WriteSpecialsUpToRole(Role role) + void WriteSpecialsUpToRole (Role role) { for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { if (pos.Role == role) { - WriteSpecials(positionStack.Pop(), pos); - positionStack.Push(pos); + WriteSpecials (positionStack.Pop (), pos); + positionStack.Push (pos); break; } } @@ -119,24 +151,24 @@ namespace ICSharpCode.NRefactory.CSharp /// Writes all specials between the current position (in the positionStack) and the specified node. /// Advances the current position. /// - void WriteSpecialsUpToNode(AstNode node) + void WriteSpecialsUpToNode (AstNode node) { for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { if (pos == node) { - WriteSpecials(positionStack.Pop(), pos); - positionStack.Push(pos); + WriteSpecials (positionStack.Pop (), pos); + positionStack.Push (pos); break; } } } - void WriteSpecialsUpToRole(Role role, AstNode nextNode) + void WriteSpecialsUpToRole (Role role, AstNode nextNode) { // Look for the role between the current position and the nextNode. for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) { if (pos.Role == AstNode.Roles.Comma) { - WriteSpecials(positionStack.Pop(), pos); - positionStack.Push(pos); + WriteSpecials (positionStack.Pop (), pos); + positionStack.Push (pos); break; } } @@ -149,37 +181,37 @@ namespace ICSharpCode.NRefactory.CSharp /// /// The next node after the comma. /// When set prevents printing a space after comma. - void Comma(AstNode nextNode, bool noSpaceAfterComma = false) + void Comma (AstNode nextNode, bool noSpaceAfterComma = false) { - WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); - Space(policy.SpaceBeforeBracketComma); // TODO: Comma policy has changed. - formatter.WriteToken(","); + WriteSpecialsUpToRole (AstNode.Roles.Comma, nextNode); + Space (policy.SpaceBeforeBracketComma); // TODO: Comma policy has changed. + formatter.WriteToken (","); lastWritten = LastWritten.Other; - Space(!noSpaceAfterComma && policy.SpaceAfterBracketComma); // TODO: Comma policy has changed. + Space (!noSpaceAfterComma && policy.SpaceAfterBracketComma); // TODO: Comma policy has changed. } - void WriteCommaSeparatedList(IEnumerable list) + void WriteCommaSeparatedList (IEnumerable list) { bool isFirst = true; foreach (AstNode node in list) { if (isFirst) { isFirst = false; } else { - Comma(node); + Comma (node); } - node.AcceptVisitor(this, null); + node.AcceptVisitor (this, null); } } - void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + void WriteCommaSeparatedListInParenthesis (IEnumerable list, bool spaceWithin) { - LPar(); - if (list.Any()) { - Space(spaceWithin); - WriteCommaSeparatedList(list); - Space(spaceWithin); + LPar (); + if (list.Any ()) { + Space (spaceWithin); + WriteCommaSeparatedList (list); + Space (spaceWithin); } - RPar(); + RPar (); } #if DOTNET35 @@ -205,18 +237,18 @@ namespace ICSharpCode.NRefactory.CSharp #endif - void WriteCommaSeparatedListInBrackets(IEnumerable list, bool spaceWithin) + void WriteCommaSeparatedListInBrackets (IEnumerable list, bool spaceWithin) { - WriteToken("[", AstNode.Roles.LBracket); - if (list.Any()) { - Space(spaceWithin); - WriteCommaSeparatedList(list.SafeCast()); - Space(spaceWithin); + WriteToken ("[", AstNode.Roles.LBracket); + if (list.Any ()) { + Space (spaceWithin); + WriteCommaSeparatedList (list.SafeCast ()); + Space (spaceWithin); } - WriteToken("]", AstNode.Roles.RBracket); + WriteToken ("]", AstNode.Roles.RBracket); } - void WriteCommaSeparatedListInBrackets(IEnumerable list) + void WriteCommaSeparatedListInBrackets (IEnumerable list) { WriteToken ("[", AstNode.Roles.LBracket); if (list.Any ()) { @@ -232,47 +264,46 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Writes a keyword, and all specials up to /// - void WriteKeyword(string keyword, Role tokenRole = null) + void WriteKeyword (string keyword, Role tokenRole = null) { - WriteSpecialsUpToRole(tokenRole ?? AstNode.Roles.Keyword); + WriteSpecialsUpToRole (tokenRole ?? AstNode.Roles.Keyword); if (lastWritten == LastWritten.KeywordOrIdentifier) - formatter.Space(); - formatter.WriteKeyword(keyword); + formatter.Space (); + formatter.WriteKeyword (keyword); lastWritten = LastWritten.KeywordOrIdentifier; } - void WriteIdentifier(string identifier, Role identifierRole = null) + void WriteIdentifier (string identifier, Role identifierRole = null) { - WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier); - if (IsKeyword(identifier, containerStack.Peek())) { + WriteSpecialsUpToRole (identifierRole ?? AstNode.Roles.Identifier); + if (IsKeyword (identifier, containerStack.Peek ())) { if (lastWritten == LastWritten.KeywordOrIdentifier) - Space(); // this space is not strictly required, so we call Space() - formatter.WriteToken("@"); + Space (); // this space is not strictly required, so we call Space() + formatter.WriteToken ("@"); } else if (lastWritten == LastWritten.KeywordOrIdentifier) { - formatter.Space(); // this space is strictly required, so we directly call the formatter + formatter.Space (); // this space is strictly required, so we directly call the formatter } - formatter.WriteIdentifier(identifier); + formatter.WriteIdentifier (identifier); lastWritten = LastWritten.KeywordOrIdentifier; } - void WriteToken(string token, Role tokenRole) + void WriteToken (string token, Role tokenRole) { - WriteSpecialsUpToRole(tokenRole); + WriteSpecialsUpToRole (tokenRole); // Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token. // Note that we don't need to handle tokens like = because there's no valid // C# program that contains the single token twice in a row. // (for +, - and &, this can happen with unary operators; // for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0"; // and for /, this can happen with "1/ *ptr" or "1/ //comment".) - if (lastWritten == LastWritten.Plus && token[0] == '+' - || lastWritten == LastWritten.Minus && token[0] == '-' - || lastWritten == LastWritten.Ampersand && token[0] == '&' - || lastWritten == LastWritten.QuestionMark && token[0] == '?' - || lastWritten == LastWritten.Division && token[0] == '*') - { - formatter.Space(); - } - formatter.WriteToken(token); + if (lastWritten == LastWritten.Plus && token [0] == '+' + || lastWritten == LastWritten.Minus && token [0] == '-' + || lastWritten == LastWritten.Ampersand && token [0] == '&' + || lastWritten == LastWritten.QuestionMark && token [0] == '?' + || lastWritten == LastWritten.Division && token [0] == '*') { + formatter.Space (); + } + formatter.WriteToken (token); if (token == "+") lastWritten = LastWritten.Plus; else if (token == "-") @@ -287,58 +318,59 @@ namespace ICSharpCode.NRefactory.CSharp lastWritten = LastWritten.Other; } - void LPar() + void LPar () { - WriteToken("(", AstNode.Roles.LPar); + WriteToken ("(", AstNode.Roles.LPar); } - void RPar() + void RPar () { - WriteToken(")", AstNode.Roles.LPar); + WriteToken (")", AstNode.Roles.LPar); } /// /// Marks the end of a statement /// - void Semicolon() + void Semicolon () { - Role role = containerStack.Peek().Role; // get the role of the current node + Role role = containerStack.Peek ().Role; // get the role of the current node if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) { - WriteToken(";", AstNode.Roles.Semicolon); - NewLine(); + WriteToken (";", AstNode.Roles.Semicolon); + NewLine (); } } /// /// Writes a space depending on policy. /// - void Space(bool addSpace = true) + void Space (bool addSpace = true) { if (addSpace) { - formatter.Space(); + formatter.Space (); lastWritten = LastWritten.Whitespace; } } - void NewLine() + void NewLine () { - formatter.NewLine(); + formatter.NewLine (); lastWritten = LastWritten.Whitespace; } - void OpenBrace(BraceStyle style) + void OpenBrace (BraceStyle style) { - WriteSpecialsUpToRole(AstNode.Roles.LBrace); - formatter.OpenBrace(style); + WriteSpecialsUpToRole (AstNode.Roles.LBrace); + formatter.OpenBrace (style); lastWritten = LastWritten.Other; } - void CloseBrace(BraceStyle style) + void CloseBrace (BraceStyle style) { - WriteSpecialsUpToRole(AstNode.Roles.RBrace); - formatter.CloseBrace(style); + WriteSpecialsUpToRole (AstNode.Roles.RBrace); + formatter.CloseBrace (style); lastWritten = LastWritten.Other; } + #endregion #region IsKeyword Test @@ -354,7 +386,6 @@ namespace ICSharpCode.NRefactory.CSharp "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while" }; - static readonly HashSet queryKeywords = new HashSet { "from", "where", "join", "on", "equals", "into", "let", "orderby", "ascending", "descending", "select", "group", "by" @@ -363,467 +394,473 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Determines whether the specified identifier is a keyword in the given context. /// - public static bool IsKeyword(string identifier, AstNode context) + public static bool IsKeyword (string identifier, AstNode context) { - if (unconditionalKeywords.Contains(identifier)) + if (unconditionalKeywords.Contains (identifier)) return true; - if (context.Ancestors.Any(a => a is QueryExpression)) { - if (queryKeywords.Contains(identifier)) + if (context.Ancestors.Any (a => a is QueryExpression)) { + if (queryKeywords.Contains (identifier)) return true; } return false; } + #endregion #region Write constructs - void WriteTypeArguments(IEnumerable typeArguments) + void WriteTypeArguments (IEnumerable typeArguments) { - if (typeArguments.Any()) { - WriteToken("<", AstNode.Roles.LChevron); - WriteCommaSeparatedList(typeArguments); - WriteToken(">", AstNode.Roles.RChevron); + if (typeArguments.Any ()) { + WriteToken ("<", AstNode.Roles.LChevron); + WriteCommaSeparatedList (typeArguments); + WriteToken (">", AstNode.Roles.RChevron); } } - void WriteTypeParameters(IEnumerable typeParameters) + void WriteTypeParameters (IEnumerable typeParameters) { - if (typeParameters.Any()) { - WriteToken("<", AstNode.Roles.LChevron); - WriteCommaSeparatedList(typeParameters.SafeCast()); - WriteToken(">", AstNode.Roles.RChevron); + if (typeParameters.Any ()) { + WriteToken ("<", AstNode.Roles.LChevron); + WriteCommaSeparatedList (typeParameters.SafeCast ()); + WriteToken (">", AstNode.Roles.RChevron); } } - void WriteModifiers(IEnumerable modifierTokens) + void WriteModifiers (IEnumerable modifierTokens) { foreach (CSharpModifierToken modifier in modifierTokens) { - modifier.AcceptVisitor(this, null); + modifier.AcceptVisitor (this, null); } } - void WriteQualifiedIdentifier(IEnumerable identifiers) + void WriteQualifiedIdentifier (IEnumerable identifiers) { bool first = true; foreach (Identifier ident in identifiers) { if (first) { first = false; if (lastWritten == LastWritten.KeywordOrIdentifier) - formatter.Space(); + formatter.Space (); } else { - WriteSpecialsUpToRole(AstNode.Roles.Dot, ident); - formatter.WriteToken("."); + WriteSpecialsUpToRole (AstNode.Roles.Dot, ident); + formatter.WriteToken ("."); lastWritten = LastWritten.Other; } - WriteSpecialsUpToNode(ident); - formatter.WriteIdentifier(ident.Name); + WriteSpecialsUpToNode (ident); + formatter.WriteIdentifier (ident.Name); lastWritten = LastWritten.KeywordOrIdentifier; } } - void WriteEmbeddedStatement(Statement embeddedStatement) + void WriteEmbeddedStatement (Statement embeddedStatement) { if (embeddedStatement.IsNull) return; BlockStatement block = embeddedStatement as BlockStatement; if (block != null) - VisitBlockStatement(block, null); - else - embeddedStatement.AcceptVisitor(this, null); + VisitBlockStatement (block, null); + else { + NewLine (); + formatter.Indent (); + embeddedStatement.AcceptVisitor (this, null); + formatter.Unindent (); + } } - void WriteMethodBody(BlockStatement body) + void WriteMethodBody (BlockStatement body) { if (body.IsNull) - Semicolon(); + Semicolon (); else - VisitBlockStatement(body, null); + VisitBlockStatement (body, null); } - void WriteAttributes(IEnumerable attributes) + void WriteAttributes (IEnumerable attributes) { foreach (AttributeSection attr in attributes) { - attr.AcceptVisitor(this, null); + attr.AcceptVisitor (this, null); } } - void WritePrivateImplementationType(AstType privateImplementationType) + void WritePrivateImplementationType (AstType privateImplementationType) { if (!privateImplementationType.IsNull) { - privateImplementationType.AcceptVisitor(this, null); - WriteToken(".", AstNode.Roles.Dot); + privateImplementationType.AcceptVisitor (this, null); + WriteToken (".", AstNode.Roles.Dot); } } + #endregion #region Expressions - public object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) + public object VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, object data) { - StartNode(anonymousMethodExpression); - WriteKeyword("delegate"); + StartNode (anonymousMethodExpression); + WriteKeyword ("delegate"); if (anonymousMethodExpression.HasParameterList) { - Space(policy.SpaceBeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); } - anonymousMethodExpression.Body.AcceptVisitor(this, data); - return EndNode(anonymousMethodExpression); + anonymousMethodExpression.Body.AcceptVisitor (this, data); + return EndNode (anonymousMethodExpression); } - public object VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + public object VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, object data) { - StartNode(undocumentedExpression); + StartNode (undocumentedExpression); switch (undocumentedExpression.UndocumentedExpressionType) { case UndocumentedExpressionType.ArgList: case UndocumentedExpressionType.ArgListAccess: - WriteKeyword("__arglist"); + WriteKeyword ("__arglist"); break; case UndocumentedExpressionType.MakeRef: - WriteKeyword("__makeref"); + WriteKeyword ("__makeref"); break; case UndocumentedExpressionType.RefType: - WriteKeyword("__reftype"); + WriteKeyword ("__reftype"); break; case UndocumentedExpressionType.RefValue: - WriteKeyword("__refvalue"); + WriteKeyword ("__refvalue"); break; } if (undocumentedExpression.Arguments.Count > 0) { - Space(policy.SpaceBeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses); } - return EndNode(undocumentedExpression); + return EndNode (undocumentedExpression); } - public object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) + public object VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, object data) { - StartNode(arrayCreateExpression); - WriteKeyword("new"); - arrayCreateExpression.Type.AcceptVisitor(this, data); - WriteCommaSeparatedListInBrackets(arrayCreateExpression.Arguments); + StartNode (arrayCreateExpression); + WriteKeyword ("new"); + arrayCreateExpression.Type.AcceptVisitor (this, data); + WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments); foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) - specifier.AcceptVisitor(this, data); - arrayCreateExpression.Initializer.AcceptVisitor(this, data); - return EndNode(arrayCreateExpression); + specifier.AcceptVisitor (this, data); + arrayCreateExpression.Initializer.AcceptVisitor (this, data); + return EndNode (arrayCreateExpression); } - public object VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) + public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data) { - StartNode(arrayInitializerExpression); + StartNode (arrayInitializerExpression); BraceStyle style; if (policy.PlaceArrayInitializersOnNewLine == ArrayInitializerPlacement.AlwaysNewLine) style = BraceStyle.NextLine; else style = BraceStyle.EndOfLine; - OpenBrace(style); + OpenBrace (style); bool isFirst = true; foreach (AstNode node in arrayInitializerExpression.Elements) { if (isFirst) { isFirst = false; } else { - Comma(node); - NewLine(); + Comma (node); + NewLine (); } - node.AcceptVisitor(this, null); + node.AcceptVisitor (this, null); } - NewLine(); - CloseBrace(style); - return EndNode(arrayInitializerExpression); + NewLine (); + CloseBrace (style); + return EndNode (arrayInitializerExpression); } - public object VisitAsExpression(AsExpression asExpression, object data) + public object VisitAsExpression (AsExpression asExpression, object data) { - StartNode(asExpression); - asExpression.Expression.AcceptVisitor(this, data); - Space(); - WriteKeyword("as"); - Space(); - asExpression.Type.AcceptVisitor(this, data); - return EndNode(asExpression); + StartNode (asExpression); + asExpression.Expression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("as"); + Space (); + asExpression.Type.AcceptVisitor (this, data); + return EndNode (asExpression); } - public object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + public object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) { - StartNode(assignmentExpression); - assignmentExpression.Left.AcceptVisitor(this, data); - Space(policy.SpaceAroundAssignment); - WriteToken(AssignmentExpression.GetOperatorSymbol(assignmentExpression.Operator), AssignmentExpression.OperatorRole); - Space(policy.SpaceAroundAssignment); - assignmentExpression.Right.AcceptVisitor(this, data); - return EndNode(assignmentExpression); + StartNode (assignmentExpression); + assignmentExpression.Left.AcceptVisitor (this, data); + Space (policy.SpaceAroundAssignment); + WriteToken (AssignmentExpression.GetOperatorSymbol (assignmentExpression.Operator), AssignmentExpression.OperatorRole); + Space (policy.SpaceAroundAssignment); + assignmentExpression.Right.AcceptVisitor (this, data); + return EndNode (assignmentExpression); } - public object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) + public object VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, object data) { - StartNode(baseReferenceExpression); - WriteKeyword("base"); - return EndNode(baseReferenceExpression); + StartNode (baseReferenceExpression); + WriteKeyword ("base"); + return EndNode (baseReferenceExpression); } - public object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + public object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) { - StartNode(binaryOperatorExpression); - binaryOperatorExpression.Left.AcceptVisitor(this, data); + StartNode (binaryOperatorExpression); + binaryOperatorExpression.Left.AcceptVisitor (this, data); bool spacePolicy; switch (binaryOperatorExpression.Operator) { - case BinaryOperatorType.BitwiseAnd: - case BinaryOperatorType.BitwiseOr: - case BinaryOperatorType.ExclusiveOr: - spacePolicy = policy.SpaceAroundBitwiseOperator; - break; - case BinaryOperatorType.ConditionalAnd: - case BinaryOperatorType.ConditionalOr: - spacePolicy = policy.SpaceAroundLogicalOperator; - break; - case BinaryOperatorType.GreaterThan: - case BinaryOperatorType.GreaterThanOrEqual: - case BinaryOperatorType.LessThanOrEqual: - case BinaryOperatorType.LessThan: - spacePolicy = policy.SpaceAroundRelationalOperator; - break; - case BinaryOperatorType.Equality: - case BinaryOperatorType.InEquality: - spacePolicy = policy.SpaceAroundEqualityOperator; - break; - case BinaryOperatorType.Add: - case BinaryOperatorType.Subtract: - spacePolicy = policy.SpaceAroundAdditiveOperator; - break; - case BinaryOperatorType.Multiply: - case BinaryOperatorType.Divide: - case BinaryOperatorType.Modulus: - spacePolicy = policy.SpaceAroundMultiplicativeOperator; - break; - case BinaryOperatorType.ShiftLeft: - case BinaryOperatorType.ShiftRight: - spacePolicy = policy.SpaceAroundShiftOperator; - break; - case BinaryOperatorType.NullCoalescing: - spacePolicy = true; - break; - default: - throw new NotSupportedException("Invalid value for BinaryOperatorType"); + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + spacePolicy = policy.SpaceAroundBitwiseOperator; + break; + case BinaryOperatorType.ConditionalAnd: + case BinaryOperatorType.ConditionalOr: + spacePolicy = policy.SpaceAroundLogicalOperator; + break; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThanOrEqual: + case BinaryOperatorType.LessThan: + spacePolicy = policy.SpaceAroundRelationalOperator; + break; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + spacePolicy = policy.SpaceAroundEqualityOperator; + break; + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + spacePolicy = policy.SpaceAroundAdditiveOperator; + break; + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + spacePolicy = policy.SpaceAroundMultiplicativeOperator; + break; + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + spacePolicy = policy.SpaceAroundShiftOperator; + break; + case BinaryOperatorType.NullCoalescing: + spacePolicy = true; + break; + default: + throw new NotSupportedException ("Invalid value for BinaryOperatorType"); } - Space(spacePolicy); - WriteToken(BinaryOperatorExpression.GetOperatorSymbol(binaryOperatorExpression.Operator), BinaryOperatorExpression.OperatorRole); - Space(spacePolicy); - binaryOperatorExpression.Right.AcceptVisitor(this, data); - return EndNode(binaryOperatorExpression); + Space (spacePolicy); + WriteToken (BinaryOperatorExpression.GetOperatorSymbol (binaryOperatorExpression.Operator), BinaryOperatorExpression.OperatorRole); + Space (spacePolicy); + binaryOperatorExpression.Right.AcceptVisitor (this, data); + return EndNode (binaryOperatorExpression); } - public object VisitCastExpression(CastExpression castExpression, object data) + public object VisitCastExpression (CastExpression castExpression, object data) { - StartNode(castExpression); - LPar(); - Space(policy.SpacesWithinCastParentheses); - castExpression.Type.AcceptVisitor(this, data); - Space(policy.SpacesWithinCastParentheses); - RPar(); - Space(policy.SpaceAfterTypecast); - castExpression.Expression.AcceptVisitor(this, data); - return EndNode(castExpression); + StartNode (castExpression); + LPar (); + Space (policy.SpacesWithinCastParentheses); + castExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinCastParentheses); + RPar (); + Space (policy.SpaceAfterTypecast); + castExpression.Expression.AcceptVisitor (this, data); + return EndNode (castExpression); } - public object VisitCheckedExpression(CheckedExpression checkedExpression, object data) + public object VisitCheckedExpression (CheckedExpression checkedExpression, object data) { - StartNode(checkedExpression); - WriteKeyword("checked"); - LPar(); - Space(policy.SpacesWithinCheckedExpressionParantheses); - checkedExpression.Expression.AcceptVisitor(this, data); - Space(policy.SpacesWithinCheckedExpressionParantheses); - RPar(); - return EndNode(checkedExpression); + StartNode (checkedExpression); + WriteKeyword ("checked"); + LPar (); + Space (policy.SpacesWithinCheckedExpressionParantheses); + checkedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinCheckedExpressionParantheses); + RPar (); + return EndNode (checkedExpression); } - public object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + public object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) { - StartNode(conditionalExpression); - conditionalExpression.Condition.AcceptVisitor(this, data); + StartNode (conditionalExpression); + conditionalExpression.Condition.AcceptVisitor (this, data); - Space(policy.SpaceBeforeConditionalOperatorCondition); - WriteToken("?", ConditionalExpression.QuestionMarkRole); - Space(policy.SpaceAfterConditionalOperatorCondition); + Space (policy.SpaceBeforeConditionalOperatorCondition); + WriteToken ("?", ConditionalExpression.QuestionMarkRole); + Space (policy.SpaceAfterConditionalOperatorCondition); - conditionalExpression.TrueExpression.AcceptVisitor(this, data); + conditionalExpression.TrueExpression.AcceptVisitor (this, data); - Space(policy.SpaceBeforeConditionalOperatorSeparator); - WriteToken(":", ConditionalExpression.ColonRole); - Space(policy.SpaceAfterConditionalOperatorSeparator); + Space (policy.SpaceBeforeConditionalOperatorSeparator); + WriteToken (":", ConditionalExpression.ColonRole); + Space (policy.SpaceAfterConditionalOperatorSeparator); - conditionalExpression.FalseExpression.AcceptVisitor(this, data); + conditionalExpression.FalseExpression.AcceptVisitor (this, data); - return EndNode(conditionalExpression); + return EndNode (conditionalExpression); } - public object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + public object VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, object data) { - StartNode(defaultValueExpression); + StartNode (defaultValueExpression); - WriteKeyword("default"); - LPar(); - Space(policy.SpacesWithinTypeOfParentheses); - defaultValueExpression.Type.AcceptVisitor(this, data); - Space(policy.SpacesWithinTypeOfParentheses); - RPar(); + WriteKeyword ("default"); + LPar (); + Space (policy.SpacesWithinTypeOfParentheses); + defaultValueExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinTypeOfParentheses); + RPar (); - return EndNode(defaultValueExpression); + return EndNode (defaultValueExpression); } - public object VisitDirectionExpression(DirectionExpression directionExpression, object data) + public object VisitDirectionExpression (DirectionExpression directionExpression, object data) { - StartNode(directionExpression); + StartNode (directionExpression); switch (directionExpression.FieldDirection) { - case FieldDirection.Out: - WriteKeyword("out"); - break; - case FieldDirection.Ref: - WriteKeyword("ref"); - break; - default: - throw new NotSupportedException("Invalid value for FieldDirection"); + case FieldDirection.Out: + WriteKeyword ("out"); + break; + case FieldDirection.Ref: + WriteKeyword ("ref"); + break; + default: + throw new NotSupportedException ("Invalid value for FieldDirection"); } - Space(); - directionExpression.Expression.AcceptVisitor(this, data); + Space (); + directionExpression.Expression.AcceptVisitor (this, data); - return EndNode(directionExpression); + return EndNode (directionExpression); } - public object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + public object VisitIdentifierExpression (IdentifierExpression identifierExpression, object data) { - StartNode(identifierExpression); - WriteIdentifier(identifierExpression.Identifier); - WriteTypeArguments(identifierExpression.TypeArguments); - return EndNode(identifierExpression); + StartNode (identifierExpression); + WriteIdentifier (identifierExpression.Identifier); + WriteTypeArguments (identifierExpression.TypeArguments); + return EndNode (identifierExpression); } - public object VisitIndexerExpression(IndexerExpression indexerExpression, object data) + public object VisitIndexerExpression (IndexerExpression indexerExpression, object data) { - StartNode(indexerExpression); - indexerExpression.Target.AcceptVisitor(this, data); - Space(policy.SpaceBeforeMethodCallParentheses); - WriteCommaSeparatedListInBrackets(indexerExpression.Arguments); - return EndNode(indexerExpression); + StartNode (indexerExpression); + indexerExpression.Target.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInBrackets (indexerExpression.Arguments); + return EndNode (indexerExpression); } - public object VisitInvocationExpression(InvocationExpression invocationExpression, object data) + public object VisitInvocationExpression (InvocationExpression invocationExpression, object data) { - StartNode(invocationExpression); - invocationExpression.Target.AcceptVisitor(this, data); - Space(policy.SpaceBeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses); - return EndNode(invocationExpression); + StartNode (invocationExpression); + invocationExpression.Target.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (invocationExpression); } - public object VisitIsExpression(IsExpression isExpression, object data) + public object VisitIsExpression (IsExpression isExpression, object data) { - StartNode(isExpression); - isExpression.Expression.AcceptVisitor(this, data); - Space(); - WriteKeyword("is"); - isExpression.Type.AcceptVisitor(this, data); - return EndNode(isExpression); + StartNode (isExpression); + isExpression.Expression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("is"); + isExpression.Type.AcceptVisitor (this, data); + return EndNode (isExpression); } - public object VisitLambdaExpression(LambdaExpression lambdaExpression, object data) + public object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) { - StartNode(lambdaExpression); - if (LambdaNeedsParenthesis(lambdaExpression)) { - WriteCommaSeparatedListInParenthesis(lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + StartNode (lambdaExpression); + if (LambdaNeedsParenthesis (lambdaExpression)) { + WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); } else { - lambdaExpression.Parameters.Single().AcceptVisitor(this, data); + lambdaExpression.Parameters.Single ().AcceptVisitor (this, data); } - Space(); - WriteToken("=>", LambdaExpression.ArrowRole); - Space(); - lambdaExpression.Body.AcceptVisitor(this, data); - return EndNode(lambdaExpression); + Space (); + WriteToken ("=>", LambdaExpression.ArrowRole); + Space (); + lambdaExpression.Body.AcceptVisitor (this, data); + return EndNode (lambdaExpression); } - bool LambdaNeedsParenthesis(LambdaExpression lambdaExpression) + bool LambdaNeedsParenthesis (LambdaExpression lambdaExpression) { if (lambdaExpression.Parameters.Count != 1) return true; - var p = lambdaExpression.Parameters.Single(); + var p = lambdaExpression.Parameters.Single (); return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None); } - public object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + public object VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, object data) { - StartNode(memberReferenceExpression); - memberReferenceExpression.Target.AcceptVisitor(this, data); - WriteToken(".", MemberReferenceExpression.Roles.Dot); - WriteIdentifier(memberReferenceExpression.MemberName); - WriteTypeArguments(memberReferenceExpression.TypeArguments); - return EndNode(memberReferenceExpression); + StartNode (memberReferenceExpression); + memberReferenceExpression.Target.AcceptVisitor (this, data); + WriteToken (".", MemberReferenceExpression.Roles.Dot); + WriteIdentifier (memberReferenceExpression.MemberName); + WriteTypeArguments (memberReferenceExpression.TypeArguments); + return EndNode (memberReferenceExpression); } - public object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) + public object VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, object data) { - StartNode(namedArgumentExpression); - WriteIdentifier(namedArgumentExpression.Identifier); + StartNode (namedArgumentExpression); + WriteIdentifier (namedArgumentExpression.Identifier); if (namedArgumentExpression.Parent is ArrayInitializerExpression) { Space(); WriteToken("=", NamedArgumentExpression.Roles.Assign); } else { WriteToken(":", NamedArgumentExpression.Roles.Colon); } - Space(); - namedArgumentExpression.Expression.AcceptVisitor(this, data); - return EndNode(namedArgumentExpression); + Space (); + namedArgumentExpression.Expression.AcceptVisitor (this, data); + return EndNode (namedArgumentExpression); } - public object VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + public object VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) { - StartNode(nullReferenceExpression); - WriteKeyword("null"); - return EndNode(nullReferenceExpression); + StartNode (nullReferenceExpression); + WriteKeyword ("null"); + return EndNode (nullReferenceExpression); } - public object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) + public object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) { - StartNode(objectCreateExpression); - WriteKeyword("new"); - objectCreateExpression.Type.AcceptVisitor(this, data); + StartNode (objectCreateExpression); + WriteKeyword ("new"); + objectCreateExpression.Type.AcceptVisitor (this, data); bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull; // also use parenthesis if there is an '(' token and this isn't an anonymous type if (!objectCreateExpression.LParToken.IsNull && !objectCreateExpression.Type.IsNull) useParenthesis = true; if (useParenthesis) { - Space(policy.SpaceBeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses); } - objectCreateExpression.Initializer.AcceptVisitor(this, data); - return EndNode(objectCreateExpression); + objectCreateExpression.Initializer.AcceptVisitor (this, data); + return EndNode (objectCreateExpression); } - public object VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + public object VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) { - StartNode(anonymousTypeCreateExpression); - WriteKeyword("new"); - Space(); - LPar(); - RPar(); - Space(); - OpenBrace(policy.AnonymousMethodBraceStyle); + StartNode (anonymousTypeCreateExpression); + WriteKeyword ("new"); + Space (); + LPar (); + RPar (); + Space (); + OpenBrace (policy.AnonymousMethodBraceStyle); foreach (AstNode node in anonymousTypeCreateExpression.Initializer) { - node.AcceptVisitor(this, null); + node.AcceptVisitor (this, null); if (node.NextSibling != null) - Comma(node); + Comma (node); NewLine (); } - CloseBrace(policy.AnonymousMethodBraceStyle); - return EndNode(anonymousTypeCreateExpression); + CloseBrace (policy.AnonymousMethodBraceStyle); + return EndNode (anonymousTypeCreateExpression); } - public object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + public object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) { - StartNode(parenthesizedExpression); - LPar(); - Space(policy.SpacesWithinParentheses); - parenthesizedExpression.Expression.AcceptVisitor(this, data); - Space(policy.SpacesWithinParentheses); - RPar(); - return EndNode(parenthesizedExpression); + StartNode (parenthesizedExpression); + LPar (); + Space (policy.SpacesWithinParentheses); + parenthesizedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinParentheses); + RPar (); + return EndNode (parenthesizedExpression); } public object VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, object data) @@ -838,233 +875,251 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitEmptyExpression (EmptyExpression emptyExpression, object data) { + StartNode (emptyExpression); return EndNode (emptyExpression); } + #region VisitPrimitiveExpression - public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + public object VisitPrimitiveExpression (PrimitiveExpression primitiveExpression, object data) { - StartNode(primitiveExpression); - WritePrimitiveValue(primitiveExpression.Value); - return EndNode(primitiveExpression); + StartNode (primitiveExpression); + if (!string.IsNullOrEmpty (primitiveExpression.LiteralValue)) { + formatter.WriteToken (primitiveExpression.LiteralValue); + } else { + WritePrimitiveValue (primitiveExpression.Value); + } + return EndNode (primitiveExpression); } - void WritePrimitiveValue(object val) + void WritePrimitiveValue (object val) { if (val == null) { // usually NullReferenceExpression should be used for this, but we'll handle it anyways - WriteKeyword("null"); + WriteKeyword ("null"); return; } if (val is bool) { if ((bool)val) { - WriteKeyword("true"); + WriteKeyword ("true"); } else { - WriteKeyword("false"); + WriteKeyword ("false"); } return; } if (val is string) { - formatter.WriteToken("\"" + ConvertString(val.ToString()) + "\""); + formatter.WriteToken ("\"" + ConvertString (val.ToString ()) + "\""); lastWritten = LastWritten.Other; } else if (val is char) { - formatter.WriteToken("'" + ConvertCharLiteral((char)val) + "'"); + formatter.WriteToken ("'" + ConvertCharLiteral ((char)val) + "'"); lastWritten = LastWritten.Other; } else if (val is decimal) { - formatter.WriteToken(((decimal)val).ToString(NumberFormatInfo.InvariantInfo) + "m"); + formatter.WriteToken (((decimal)val).ToString (NumberFormatInfo.InvariantInfo) + "m"); lastWritten = LastWritten.Other; } else if (val is float) { float f = (float)val; - if (float.IsInfinity(f) || float.IsNaN(f)) { + if (float.IsInfinity (f) || float.IsNaN (f)) { // Strictly speaking, these aren't PrimitiveExpressions; // but we still support writing these to make life easier for code generators. - WriteKeyword("float"); - WriteToken(".", AstNode.Roles.Dot); - if (float.IsPositiveInfinity(f)) - WriteIdentifier("PositiveInfinity"); - else if (float.IsNegativeInfinity(f)) - WriteIdentifier("NegativeInfinity"); + WriteKeyword ("float"); + WriteToken (".", AstNode.Roles.Dot); + if (float.IsPositiveInfinity (f)) + WriteIdentifier ("PositiveInfinity"); + else if (float.IsNegativeInfinity (f)) + WriteIdentifier ("NegativeInfinity"); else - WriteIdentifier("NaN"); + WriteIdentifier ("NaN"); return; } - formatter.WriteToken(f.ToString("R", NumberFormatInfo.InvariantInfo) + "f"); + formatter.WriteToken (f.ToString ("R", NumberFormatInfo.InvariantInfo) + "f"); lastWritten = LastWritten.Other; } else if (val is double) { double f = (double)val; - if (double.IsInfinity(f) || double.IsNaN(f)) { + if (double.IsInfinity (f) || double.IsNaN (f)) { // Strictly speaking, these aren't PrimitiveExpressions; // but we still support writing these to make life easier for code generators. - WriteKeyword("double"); - WriteToken(".", AstNode.Roles.Dot); - if (double.IsPositiveInfinity(f)) - WriteIdentifier("PositiveInfinity"); - else if (double.IsNegativeInfinity(f)) - WriteIdentifier("NegativeInfinity"); + WriteKeyword ("double"); + WriteToken (".", AstNode.Roles.Dot); + if (double.IsPositiveInfinity (f)) + WriteIdentifier ("PositiveInfinity"); + else if (double.IsNegativeInfinity (f)) + WriteIdentifier ("NegativeInfinity"); else - WriteIdentifier("NaN"); + WriteIdentifier ("NaN"); return; } - string number = f.ToString("R", NumberFormatInfo.InvariantInfo); - if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) + string number = f.ToString ("R", NumberFormatInfo.InvariantInfo); + if (number.IndexOf ('.') < 0 && number.IndexOf ('E') < 0) number += ".0"; - formatter.WriteToken(number); + formatter.WriteToken (number); // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix lastWritten = LastWritten.KeywordOrIdentifier; } else if (val is IFormattable) { - StringBuilder b = new StringBuilder(); + StringBuilder b = new StringBuilder (); // if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) { // b.Append("0x"); // b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo)); // } else { - b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo)); + b.Append (((IFormattable)val).ToString (null, NumberFormatInfo.InvariantInfo)); // } if (val is uint || val is ulong) { - b.Append("u"); + b.Append ("u"); } if (val is long || val is ulong) { - b.Append("L"); + b.Append ("L"); } - formatter.WriteToken(b.ToString()); + formatter.WriteToken (b.ToString ()); // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix lastWritten = LastWritten.KeywordOrIdentifier; } else { - formatter.WriteToken(val.ToString()); + formatter.WriteToken (val.ToString ()); lastWritten = LastWritten.Other; } } - static string ConvertCharLiteral(char ch) + static string ConvertCharLiteral (char ch) { - if (ch == '\'') return "\\'"; - return ConvertChar(ch); + if (ch == '\'') + return "\\'"; + return ConvertChar (ch); } - static string ConvertChar(char ch) + /// + /// Gets the escape sequence for the specified character. + /// + /// This method does not convert ' or ". + public static string ConvertChar(char ch) { switch (ch) { - case '\\': - return "\\\\"; - case '\0': - return "\\0"; - case '\a': - return "\\a"; - case '\b': - return "\\b"; - case '\f': - return "\\f"; - case '\n': - return "\\n"; - case '\r': - return "\\r"; - case '\t': - return "\\t"; - case '\v': - return "\\v"; - default: - if (char.IsControl(ch) || char.IsSurrogate(ch)) { - return "\\u" + ((int)ch).ToString("x4"); - } else { - return ch.ToString(); - } + case '\\': + return "\\\\"; + case '\0': + return "\\0"; + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\f': + return "\\f"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + default: + if (char.IsControl(ch) || char.IsSurrogate(ch) || + // print all uncommon white spaces as numbers + (char.IsWhiteSpace(ch) && ch != ' ')) { + return "\\u" + ((int)ch).ToString ("x4"); + } else { + return ch.ToString (); + } } } - static string ConvertString(string str) + /// + /// Converts special characters to escape sequences within the given string. + /// + public static string ConvertString(string str) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder (); foreach (char ch in str) { if (ch == '"') - sb.Append("\\\""); + sb.Append ("\\\""); else - sb.Append(ConvertChar(ch)); + sb.Append (ConvertChar (ch)); } - return sb.ToString(); + return sb.ToString (); } + #endregion - public object VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data) + public object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) { - StartNode(sizeOfExpression); + StartNode (sizeOfExpression); - WriteKeyword("sizeof"); - LPar(); - Space(policy.SpacesWithinSizeOfParentheses); - sizeOfExpression.Type.AcceptVisitor(this, data); - Space(policy.SpacesWithinSizeOfParentheses); - RPar(); + WriteKeyword ("sizeof"); + LPar (); + Space (policy.SpacesWithinSizeOfParentheses); + sizeOfExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinSizeOfParentheses); + RPar (); - return EndNode(sizeOfExpression); + return EndNode (sizeOfExpression); } - public object VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) + public object VisitStackAllocExpression (StackAllocExpression stackAllocExpression, object data) { - StartNode(stackAllocExpression); - WriteKeyword("stackalloc"); - stackAllocExpression.Type.AcceptVisitor(this, data); - WriteCommaSeparatedListInBrackets(new[] { stackAllocExpression.CountExpression }); - return EndNode(stackAllocExpression); + StartNode (stackAllocExpression); + WriteKeyword ("stackalloc"); + stackAllocExpression.Type.AcceptVisitor (this, data); + WriteCommaSeparatedListInBrackets (new[] { stackAllocExpression.CountExpression }); + return EndNode (stackAllocExpression); } - public object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) + public object VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression, object data) { - StartNode(thisReferenceExpression); - WriteKeyword("this"); - return EndNode(thisReferenceExpression); + StartNode (thisReferenceExpression); + WriteKeyword ("this"); + return EndNode (thisReferenceExpression); } - public object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + public object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) { - StartNode(typeOfExpression); + StartNode (typeOfExpression); - WriteKeyword("typeof"); - LPar(); - Space(policy.SpacesWithinTypeOfParentheses); - typeOfExpression.Type.AcceptVisitor(this, data); - Space(policy.SpacesWithinTypeOfParentheses); - RPar(); + WriteKeyword ("typeof"); + LPar (); + Space (policy.SpacesWithinTypeOfParentheses); + typeOfExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinTypeOfParentheses); + RPar (); - return EndNode(typeOfExpression); + return EndNode (typeOfExpression); } - public object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + public object VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression, object data) { - StartNode(typeReferenceExpression); - typeReferenceExpression.Type.AcceptVisitor(this, data); - return EndNode(typeReferenceExpression); + StartNode (typeReferenceExpression); + typeReferenceExpression.Type.AcceptVisitor (this, data); + return EndNode (typeReferenceExpression); } - public object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + public object VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, object data) { - StartNode(unaryOperatorExpression); + StartNode (unaryOperatorExpression); UnaryOperatorType opType = unaryOperatorExpression.Operator; - string opSymbol = UnaryOperatorExpression.GetOperatorSymbol(opType); + string opSymbol = UnaryOperatorExpression.GetOperatorSymbol (opType); if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) - WriteToken(opSymbol, UnaryOperatorExpression.OperatorRole); - unaryOperatorExpression.Expression.AcceptVisitor(this, data); + WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); + unaryOperatorExpression.Expression.AcceptVisitor (this, data); if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) - WriteToken(opSymbol, UnaryOperatorExpression.OperatorRole); - return EndNode(unaryOperatorExpression); + WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); + return EndNode (unaryOperatorExpression); } - public object VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + public object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) { - StartNode(uncheckedExpression); - WriteKeyword("unchecked"); - LPar(); - Space(policy.SpacesWithinCheckedExpressionParantheses); - uncheckedExpression.Expression.AcceptVisitor(this, data); - Space(policy.SpacesWithinCheckedExpressionParantheses); - RPar(); - return EndNode(uncheckedExpression); + StartNode (uncheckedExpression); + WriteKeyword ("unchecked"); + LPar (); + Space (policy.SpacesWithinCheckedExpressionParantheses); + uncheckedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinCheckedExpressionParantheses); + RPar (); + return EndNode (uncheckedExpression); } + #endregion #region Query Expressions - public object VisitQueryExpression(QueryExpression queryExpression, object data) + public object VisitQueryExpression (QueryExpression queryExpression, object data) { - StartNode(queryExpression); + StartNode (queryExpression); bool indent = !(queryExpression.Parent is QueryContinuationClause); if (indent) { formatter.Indent(); @@ -1072,299 +1127,302 @@ namespace ICSharpCode.NRefactory.CSharp } bool first = true; foreach (var clause in queryExpression.Clauses) { - if (first) + if (first) { first = false; - else + } else { if (!(clause is QueryContinuationClause)) - NewLine(); - clause.AcceptVisitor(this, data); + NewLine (); + } + clause.AcceptVisitor (this, data); } if (indent) formatter.Unindent(); - return EndNode(queryExpression); - } - - public object VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, object data) - { - StartNode(queryContinuationClause); - queryContinuationClause.PrecedingQuery.AcceptVisitor(this, data); - Space(); - WriteKeyword("into", QueryContinuationClause.IntoKeywordRole); - Space(); - WriteIdentifier(queryContinuationClause.Identifier); - return EndNode(queryContinuationClause); - } - - public object VisitQueryFromClause(QueryFromClause queryFromClause, object data) - { - StartNode(queryFromClause); - WriteKeyword("from", QueryFromClause.FromKeywordRole); - queryFromClause.Type.AcceptVisitor(this, data); - Space(); - WriteIdentifier(queryFromClause.Identifier); - WriteKeyword("in", QueryFromClause.InKeywordRole); - queryFromClause.Expression.AcceptVisitor(this, data); - return EndNode(queryFromClause); - } - - public object VisitQueryLetClause(QueryLetClause queryLetClause, object data) - { - StartNode(queryLetClause); - WriteKeyword("let"); - Space(); - WriteIdentifier(queryLetClause.Identifier); - Space(policy.SpaceAroundAssignment); - WriteToken("=", QueryLetClause.Roles.Assign); - Space(policy.SpaceAroundAssignment); - queryLetClause.Expression.AcceptVisitor(this, data); - return EndNode(queryLetClause); - } - - public object VisitQueryWhereClause(QueryWhereClause queryWhereClause, object data) - { - StartNode(queryWhereClause); - WriteKeyword("where"); - Space(); - queryWhereClause.Condition.AcceptVisitor(this, data); - return EndNode(queryWhereClause); - } - - public object VisitQueryJoinClause(QueryJoinClause queryJoinClause, object data) - { - StartNode(queryJoinClause); - WriteKeyword("join", QueryJoinClause.JoinKeywordRole); - queryJoinClause.Type.AcceptVisitor(this, data); - Space(); - WriteIdentifier(queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole); - Space(); - WriteKeyword("in", QueryJoinClause.InKeywordRole); - Space(); - queryJoinClause.InExpression.AcceptVisitor(this, data); - Space(); - WriteKeyword("on", QueryJoinClause.OnKeywordRole); - Space(); - queryJoinClause.OnExpression.AcceptVisitor(this, data); - Space(); - WriteKeyword("equals", QueryJoinClause.EqualsKeywordRole); - Space(); - queryJoinClause.EqualsExpression.AcceptVisitor(this, data); + return EndNode (queryExpression); + } + + public object VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause, object data) + { + StartNode (queryContinuationClause); + queryContinuationClause.PrecedingQuery.AcceptVisitor (this, data); + Space (); + WriteKeyword ("into", QueryContinuationClause.IntoKeywordRole); + Space (); + WriteIdentifier (queryContinuationClause.Identifier); + return EndNode (queryContinuationClause); + } + + public object VisitQueryFromClause (QueryFromClause queryFromClause, object data) + { + StartNode (queryFromClause); + WriteKeyword ("from", QueryFromClause.FromKeywordRole); + queryFromClause.Type.AcceptVisitor (this, data); + Space (); + WriteIdentifier (queryFromClause.Identifier); + Space (); + WriteKeyword ("in", QueryFromClause.InKeywordRole); + Space (); + queryFromClause.Expression.AcceptVisitor (this, data); + return EndNode (queryFromClause); + } + + public object VisitQueryLetClause (QueryLetClause queryLetClause, object data) + { + StartNode (queryLetClause); + WriteKeyword ("let"); + Space (); + WriteIdentifier (queryLetClause.Identifier); + Space (policy.SpaceAroundAssignment); + WriteToken ("=", QueryLetClause.Roles.Assign); + Space (policy.SpaceAroundAssignment); + queryLetClause.Expression.AcceptVisitor (this, data); + return EndNode (queryLetClause); + } + + public object VisitQueryWhereClause (QueryWhereClause queryWhereClause, object data) + { + StartNode (queryWhereClause); + WriteKeyword ("where"); + Space (); + queryWhereClause.Condition.AcceptVisitor (this, data); + return EndNode (queryWhereClause); + } + + public object VisitQueryJoinClause (QueryJoinClause queryJoinClause, object data) + { + StartNode (queryJoinClause); + WriteKeyword ("join", QueryJoinClause.JoinKeywordRole); + queryJoinClause.Type.AcceptVisitor (this, data); + Space (); + WriteIdentifier (queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole); + Space (); + WriteKeyword ("in", QueryJoinClause.InKeywordRole); + Space (); + queryJoinClause.InExpression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("on", QueryJoinClause.OnKeywordRole); + Space (); + queryJoinClause.OnExpression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("equals", QueryJoinClause.EqualsKeywordRole); + Space (); + queryJoinClause.EqualsExpression.AcceptVisitor (this, data); if (queryJoinClause.IsGroupJoin) { - Space(); - WriteKeyword("into", QueryJoinClause.IntoKeywordRole); - WriteIdentifier(queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole); + Space (); + WriteKeyword ("into", QueryJoinClause.IntoKeywordRole); + WriteIdentifier (queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole); } - return EndNode(queryJoinClause); + return EndNode (queryJoinClause); } - public object VisitQueryOrderClause(QueryOrderClause queryOrderClause, object data) + public object VisitQueryOrderClause (QueryOrderClause queryOrderClause, object data) { - StartNode(queryOrderClause); - WriteKeyword("orderby"); - Space(); - WriteCommaSeparatedList(queryOrderClause.Orderings.SafeCast()); - return EndNode(queryOrderClause); + StartNode (queryOrderClause); + WriteKeyword ("orderby"); + Space (); + WriteCommaSeparatedList (queryOrderClause.Orderings.SafeCast ()); + return EndNode (queryOrderClause); } - public object VisitQueryOrdering(QueryOrdering queryOrdering, object data) + public object VisitQueryOrdering (QueryOrdering queryOrdering, object data) { - StartNode(queryOrdering); - queryOrdering.Expression.AcceptVisitor(this, data); + StartNode (queryOrdering); + queryOrdering.Expression.AcceptVisitor (this, data); switch (queryOrdering.Direction) { - case QueryOrderingDirection.Ascending: - Space(); - WriteKeyword("ascending"); - break; - case QueryOrderingDirection.Descending: - Space(); - WriteKeyword("descending"); - break; + case QueryOrderingDirection.Ascending: + Space (); + WriteKeyword ("ascending"); + break; + case QueryOrderingDirection.Descending: + Space (); + WriteKeyword ("descending"); + break; } - return EndNode(queryOrdering); + return EndNode (queryOrdering); } - public object VisitQuerySelectClause(QuerySelectClause querySelectClause, object data) + public object VisitQuerySelectClause (QuerySelectClause querySelectClause, object data) { - StartNode(querySelectClause); - WriteKeyword("select"); - Space(); - querySelectClause.Expression.AcceptVisitor(this, data); - return EndNode(querySelectClause); + StartNode (querySelectClause); + WriteKeyword ("select"); + Space (); + querySelectClause.Expression.AcceptVisitor (this, data); + return EndNode (querySelectClause); } - public object VisitQueryGroupClause(QueryGroupClause queryGroupClause, object data) + public object VisitQueryGroupClause (QueryGroupClause queryGroupClause, object data) { - StartNode(queryGroupClause); - WriteKeyword("group", QueryGroupClause.GroupKeywordRole); - Space(); - queryGroupClause.Projection.AcceptVisitor(this, data); - Space(); - WriteKeyword("by", QueryGroupClause.ByKeywordRole); - Space(); - queryGroupClause.Key.AcceptVisitor(this, data); - return EndNode(queryGroupClause); + StartNode (queryGroupClause); + WriteKeyword ("group", QueryGroupClause.GroupKeywordRole); + Space (); + queryGroupClause.Projection.AcceptVisitor (this, data); + Space (); + WriteKeyword ("by", QueryGroupClause.ByKeywordRole); + Space (); + queryGroupClause.Key.AcceptVisitor (this, data); + return EndNode (queryGroupClause); } + #endregion #region GeneralScope - public object VisitAttribute(Attribute attribute, object data) + public object VisitAttribute (Attribute attribute, object data) { - StartNode(attribute); - attribute.Type.AcceptVisitor(this, data); - Space(policy.SpaceBeforeMethodCallParentheses); - if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(AstNode.Roles.LPar).IsNull) - WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses); - return EndNode(attribute); + StartNode (attribute); + attribute.Type.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull) + WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (attribute); } - public object VisitAttributeSection(AttributeSection attributeSection, object data) + public object VisitAttributeSection (AttributeSection attributeSection, object data) { - StartNode(attributeSection); - WriteToken("[", AstNode.Roles.LBracket); + StartNode (attributeSection); + WriteToken ("[", AstNode.Roles.LBracket); if (!string.IsNullOrEmpty (attributeSection.AttributeTarget)) { - WriteToken(attributeSection.AttributeTarget, AttributeSection.TargetRole); - WriteToken(":", AttributeSection.Roles.Colon); - Space(); + WriteToken (attributeSection.AttributeTarget, AttributeSection.TargetRole); + WriteToken (":", AttributeSection.Roles.Colon); + Space (); } - WriteCommaSeparatedList(attributeSection.Attributes.SafeCast()); - WriteToken("]", AstNode.Roles.RBracket); + WriteCommaSeparatedList (attributeSection.Attributes.SafeCast ()); + WriteToken ("]", AstNode.Roles.RBracket); if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) - Space(); + Space (); else - NewLine(); - return EndNode(attributeSection); + NewLine (); + return EndNode (attributeSection); } - public object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + public object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) { - StartNode(delegateDeclaration); - WriteAttributes(delegateDeclaration.Attributes); - WriteModifiers(delegateDeclaration.ModifierTokens); - WriteKeyword("delegate"); - delegateDeclaration.ReturnType.AcceptVisitor(this, data); - Space(); - WriteIdentifier(delegateDeclaration.Name); - WriteTypeParameters(delegateDeclaration.TypeParameters); - Space(policy.SpaceBeforeDelegateDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + StartNode (delegateDeclaration); + WriteAttributes (delegateDeclaration.Attributes); + WriteModifiers (delegateDeclaration.ModifierTokens); + WriteKeyword ("delegate"); + delegateDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteIdentifier (delegateDeclaration.Name); + WriteTypeParameters (delegateDeclaration.TypeParameters); + Space (policy.SpaceBeforeDelegateDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); foreach (Constraint constraint in delegateDeclaration.Constraints) { - constraint.AcceptVisitor(this, data); + constraint.AcceptVisitor (this, data); } - Semicolon(); - return EndNode(delegateDeclaration); + Semicolon (); + return EndNode (delegateDeclaration); } - public object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + public object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) { - StartNode(namespaceDeclaration); - WriteKeyword("namespace"); - WriteQualifiedIdentifier(namespaceDeclaration.Identifiers); - OpenBrace(policy.NamespaceBraceStyle); + StartNode (namespaceDeclaration); + WriteKeyword ("namespace"); + WriteQualifiedIdentifier (namespaceDeclaration.Identifiers); + OpenBrace (policy.NamespaceBraceStyle); foreach (var member in namespaceDeclaration.Members) - member.AcceptVisitor(this, data); - CloseBrace(policy.NamespaceBraceStyle); - NewLine(); - return EndNode(namespaceDeclaration); + member.AcceptVisitor (this, data); + CloseBrace (policy.NamespaceBraceStyle); + NewLine (); + return EndNode (namespaceDeclaration); } - public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + public object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) { - StartNode(typeDeclaration); - WriteAttributes(typeDeclaration.Attributes); - WriteModifiers(typeDeclaration.ModifierTokens); + StartNode (typeDeclaration); + WriteAttributes (typeDeclaration.Attributes); + WriteModifiers (typeDeclaration.ModifierTokens); BraceStyle braceStyle; switch (typeDeclaration.ClassType) { - case ClassType.Enum: - WriteKeyword("enum"); - braceStyle = policy.EnumBraceStyle; - break; - case ClassType.Interface: - WriteKeyword("interface"); - braceStyle = policy.InterfaceBraceStyle; - break; - case ClassType.Struct: - WriteKeyword("struct"); - braceStyle = policy.StructBraceStyle; - break; - default: - WriteKeyword("class"); - braceStyle = policy.ClassBraceStyle; - break; + case ClassType.Enum: + WriteKeyword ("enum"); + braceStyle = policy.EnumBraceStyle; + break; + case ClassType.Interface: + WriteKeyword ("interface"); + braceStyle = policy.InterfaceBraceStyle; + break; + case ClassType.Struct: + WriteKeyword ("struct"); + braceStyle = policy.StructBraceStyle; + break; + default: + WriteKeyword ("class"); + braceStyle = policy.ClassBraceStyle; + break; } - WriteIdentifier(typeDeclaration.Name); - WriteTypeParameters(typeDeclaration.TypeParameters); - if (typeDeclaration.BaseTypes.Any()) { - Space(); - WriteToken(":", TypeDeclaration.ColonRole); - Space(); - WriteCommaSeparatedList(typeDeclaration.BaseTypes); + WriteIdentifier (typeDeclaration.Name); + WriteTypeParameters (typeDeclaration.TypeParameters); + if (typeDeclaration.BaseTypes.Any ()) { + Space (); + WriteToken (":", TypeDeclaration.ColonRole); + Space (); + WriteCommaSeparatedList (typeDeclaration.BaseTypes); } foreach (Constraint constraint in typeDeclaration.Constraints) { - constraint.AcceptVisitor(this, data); + constraint.AcceptVisitor (this, data); } - OpenBrace(braceStyle); + OpenBrace (braceStyle); if (typeDeclaration.ClassType == ClassType.Enum) { bool first = true; foreach (var member in typeDeclaration.Members) { if (first) { first = false; } else { - Comma(member, noSpaceAfterComma: true); - NewLine(); + Comma (member, noSpaceAfterComma: true); + NewLine (); } - member.AcceptVisitor(this, data); + member.AcceptVisitor (this, data); } - NewLine(); + NewLine (); } else { foreach (var member in typeDeclaration.Members) { - member.AcceptVisitor(this, data); + member.AcceptVisitor (this, data); } } - CloseBrace(braceStyle); - NewLine(); - return EndNode(typeDeclaration); + CloseBrace (braceStyle); + NewLine (); + return EndNode (typeDeclaration); } - public object VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, object data) + public object VisitUsingAliasDeclaration (UsingAliasDeclaration usingAliasDeclaration, object data) { - StartNode(usingAliasDeclaration); - WriteKeyword("using"); - WriteIdentifier(usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole); - Space(policy.SpaceAroundEqualityOperator); - WriteToken("=", AstNode.Roles.Assign); - Space(policy.SpaceAroundEqualityOperator); - usingAliasDeclaration.Import.AcceptVisitor(this, data); - Semicolon(); - return EndNode(usingAliasDeclaration); + StartNode (usingAliasDeclaration); + WriteKeyword ("using"); + WriteIdentifier (usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole); + Space (policy.SpaceAroundEqualityOperator); + WriteToken ("=", AstNode.Roles.Assign); + Space (policy.SpaceAroundEqualityOperator); + usingAliasDeclaration.Import.AcceptVisitor (this, data); + Semicolon (); + return EndNode (usingAliasDeclaration); } - public object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + public object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) { - StartNode(usingDeclaration); - WriteKeyword("using"); - usingDeclaration.Import.AcceptVisitor(this, data); - Semicolon(); - return EndNode(usingDeclaration); + StartNode (usingDeclaration); + WriteKeyword ("using"); + usingDeclaration.Import.AcceptVisitor (this, data); + Semicolon (); + return EndNode (usingDeclaration); } - public object VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + public object VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration, object data) { - StartNode(externAliasDeclaration); - WriteKeyword("extern"); + StartNode (externAliasDeclaration); + WriteKeyword ("extern"); Space (); - WriteKeyword("alias"); + WriteKeyword ("alias"); Space (); - externAliasDeclaration.NameToken.AcceptVisitor(this, data); - Semicolon(); - return EndNode(externAliasDeclaration); + externAliasDeclaration.NameToken.AcceptVisitor (this, data); + Semicolon (); + return EndNode (externAliasDeclaration); } - #endregion #region Statements - public object VisitBlockStatement(BlockStatement blockStatement, object data) + public object VisitBlockStatement (BlockStatement blockStatement, object data) { - StartNode(blockStatement); + StartNode (blockStatement); BraceStyle style; if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) { style = policy.AnonymousMethodBraceStyle; @@ -1384,187 +1442,187 @@ namespace ICSharpCode.NRefactory.CSharp else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) style = policy.EventRemoveBraceStyle; else - throw new NotSupportedException("Unknown type of accessor"); + throw new NotSupportedException ("Unknown type of accessor"); } else { style = policy.StatementBraceStyle; } - OpenBrace(style); + OpenBrace (style); foreach (var node in blockStatement.Statements) { - node.AcceptVisitor(this, data); + node.AcceptVisitor (this, data); } - CloseBrace(style); - NewLine(); - return EndNode(blockStatement); + CloseBrace (style); + NewLine (); + return EndNode (blockStatement); } - public object VisitBreakStatement(BreakStatement breakStatement, object data) + public object VisitBreakStatement (BreakStatement breakStatement, object data) { - StartNode(breakStatement); - WriteKeyword("break"); - Semicolon(); - return EndNode(breakStatement); + StartNode (breakStatement); + WriteKeyword ("break"); + Semicolon (); + return EndNode (breakStatement); } - public object VisitCheckedStatement(CheckedStatement checkedStatement, object data) + public object VisitCheckedStatement (CheckedStatement checkedStatement, object data) { - StartNode(checkedStatement); - WriteKeyword("checked"); - checkedStatement.Body.AcceptVisitor(this, data); - return EndNode(checkedStatement); + StartNode (checkedStatement); + WriteKeyword ("checked"); + checkedStatement.Body.AcceptVisitor (this, data); + return EndNode (checkedStatement); } - public object VisitContinueStatement(ContinueStatement continueStatement, object data) + public object VisitContinueStatement (ContinueStatement continueStatement, object data) { - StartNode(continueStatement); - WriteKeyword("continue"); - Semicolon(); - return EndNode(continueStatement); + StartNode (continueStatement); + WriteKeyword ("continue"); + Semicolon (); + return EndNode (continueStatement); } - public object VisitDoWhileStatement(DoWhileStatement doWhileStatement, object data) + public object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) { - StartNode(doWhileStatement); - WriteKeyword("do", DoWhileStatement.DoKeywordRole); - WriteEmbeddedStatement(doWhileStatement.EmbeddedStatement); - WriteKeyword("while", DoWhileStatement.WhileKeywordRole); - Space(policy.SpaceBeforeWhileParentheses); - LPar(); - Space(policy.SpacesWithinWhileParentheses); - doWhileStatement.Condition.AcceptVisitor(this, data); - Space(policy.SpacesWithinWhileParentheses); - RPar(); - Semicolon(); - return EndNode(doWhileStatement); + StartNode (doWhileStatement); + WriteKeyword ("do", DoWhileStatement.DoKeywordRole); + WriteEmbeddedStatement (doWhileStatement.EmbeddedStatement); + WriteKeyword ("while", DoWhileStatement.WhileKeywordRole); + Space (policy.SpaceBeforeWhileParentheses); + LPar (); + Space (policy.SpacesWithinWhileParentheses); + doWhileStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinWhileParentheses); + RPar (); + Semicolon (); + return EndNode (doWhileStatement); } - public object VisitEmptyStatement(EmptyStatement emptyStatement, object data) + public object VisitEmptyStatement (EmptyStatement emptyStatement, object data) { - StartNode(emptyStatement); - Semicolon(); - return EndNode(emptyStatement); + StartNode (emptyStatement); + Semicolon (); + return EndNode (emptyStatement); } - public object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) + public object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) { - StartNode(expressionStatement); - expressionStatement.Expression.AcceptVisitor(this, data); - Semicolon(); - return EndNode(expressionStatement); + StartNode (expressionStatement); + expressionStatement.Expression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (expressionStatement); } - public object VisitFixedStatement(FixedStatement fixedStatement, object data) + public object VisitFixedStatement (FixedStatement fixedStatement, object data) { - StartNode(fixedStatement); - WriteKeyword("fixed"); - Space(policy.SpaceBeforeUsingParentheses); - LPar(); - Space(policy.SpacesWithinUsingParentheses); - fixedStatement.Type.AcceptVisitor(this, data); - Space(); - WriteCommaSeparatedList(fixedStatement.Variables); - Space(policy.SpacesWithinUsingParentheses); - RPar(); - WriteEmbeddedStatement(fixedStatement.EmbeddedStatement); - return EndNode(fixedStatement); + StartNode (fixedStatement); + WriteKeyword ("fixed"); + Space (policy.SpaceBeforeUsingParentheses); + LPar (); + Space (policy.SpacesWithinUsingParentheses); + fixedStatement.Type.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (fixedStatement.Variables); + Space (policy.SpacesWithinUsingParentheses); + RPar (); + WriteEmbeddedStatement (fixedStatement.EmbeddedStatement); + return EndNode (fixedStatement); } - public object VisitForeachStatement(ForeachStatement foreachStatement, object data) + public object VisitForeachStatement (ForeachStatement foreachStatement, object data) { - StartNode(foreachStatement); - WriteKeyword("foreach"); - Space(policy.SpaceBeforeForeachParentheses); - LPar(); - Space(policy.SpacesWithinForeachParentheses); - foreachStatement.VariableType.AcceptVisitor(this, data); - Space(); - WriteIdentifier(foreachStatement.VariableName); - WriteKeyword("in", ForeachStatement.Roles.InKeyword); - Space(); - foreachStatement.InExpression.AcceptVisitor(this, data); - Space(policy.SpacesWithinForeachParentheses); - RPar(); - WriteEmbeddedStatement(foreachStatement.EmbeddedStatement); - return EndNode(foreachStatement); + StartNode (foreachStatement); + WriteKeyword ("foreach"); + Space (policy.SpaceBeforeForeachParentheses); + LPar (); + Space (policy.SpacesWithinForeachParentheses); + foreachStatement.VariableType.AcceptVisitor (this, data); + Space (); + WriteIdentifier (foreachStatement.VariableName); + WriteKeyword ("in", ForeachStatement.Roles.InKeyword); + Space (); + foreachStatement.InExpression.AcceptVisitor (this, data); + Space (policy.SpacesWithinForeachParentheses); + RPar (); + WriteEmbeddedStatement (foreachStatement.EmbeddedStatement); + return EndNode (foreachStatement); } - public object VisitForStatement(ForStatement forStatement, object data) + public object VisitForStatement (ForStatement forStatement, object data) { - StartNode(forStatement); - WriteKeyword("for"); - Space(policy.SpaceBeforeForParentheses); - LPar(); - Space(policy.SpacesWithinForParentheses); + StartNode (forStatement); + WriteKeyword ("for"); + Space (policy.SpaceBeforeForParentheses); + LPar (); + Space (policy.SpacesWithinForParentheses); - WriteCommaSeparatedList(forStatement.Initializers.SafeCast()); + WriteCommaSeparatedList (forStatement.Initializers.SafeCast ()); Space (policy.SpaceBeforeForSemicolon); - WriteToken(";", AstNode.Roles.Semicolon); + WriteToken (";", AstNode.Roles.Semicolon); Space (policy.SpaceAfterForSemicolon); - forStatement.Condition.AcceptVisitor(this, data); + forStatement.Condition.AcceptVisitor (this, data); Space (policy.SpaceBeforeForSemicolon); - WriteToken(";", AstNode.Roles.Semicolon); - Space(policy.SpaceAfterForSemicolon); + WriteToken (";", AstNode.Roles.Semicolon); + Space (policy.SpaceAfterForSemicolon); - WriteCommaSeparatedList(forStatement.Iterators.SafeCast()); + WriteCommaSeparatedList (forStatement.Iterators.SafeCast ()); - Space(policy.SpacesWithinForParentheses); - RPar(); - WriteEmbeddedStatement(forStatement.EmbeddedStatement); - return EndNode(forStatement); + Space (policy.SpacesWithinForParentheses); + RPar (); + WriteEmbeddedStatement (forStatement.EmbeddedStatement); + return EndNode (forStatement); } - public object VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, object data) + public object VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, object data) { - StartNode(gotoCaseStatement); - WriteKeyword("goto"); - WriteKeyword("case", GotoCaseStatement.CaseKeywordRole); - Space(); - gotoCaseStatement.LabelExpression.AcceptVisitor(this, data); - Semicolon(); - return EndNode(gotoCaseStatement); + StartNode (gotoCaseStatement); + WriteKeyword ("goto"); + WriteKeyword ("case", GotoCaseStatement.CaseKeywordRole); + Space (); + gotoCaseStatement.LabelExpression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (gotoCaseStatement); } - public object VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, object data) + public object VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, object data) { - StartNode(gotoDefaultStatement); - WriteKeyword("goto"); - WriteKeyword("default", GotoDefaultStatement.DefaultKeywordRole); - Semicolon(); - return EndNode(gotoDefaultStatement); + StartNode (gotoDefaultStatement); + WriteKeyword ("goto"); + WriteKeyword ("default", GotoDefaultStatement.DefaultKeywordRole); + Semicolon (); + return EndNode (gotoDefaultStatement); } - public object VisitGotoStatement(GotoStatement gotoStatement, object data) + public object VisitGotoStatement (GotoStatement gotoStatement, object data) { - StartNode(gotoStatement); - WriteKeyword("goto"); - WriteIdentifier(gotoStatement.Label); - Semicolon(); - return EndNode(gotoStatement); + StartNode (gotoStatement); + WriteKeyword ("goto"); + WriteIdentifier (gotoStatement.Label); + Semicolon (); + return EndNode (gotoStatement); } - public object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) + public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) { - StartNode(ifElseStatement); - WriteKeyword("if", IfElseStatement.IfKeywordRole); - Space(policy.SpaceBeforeIfParentheses); - LPar(); - Space(policy.SpacesWithinIfParentheses); - ifElseStatement.Condition.AcceptVisitor(this, data); - Space(policy.SpacesWithinIfParentheses); - RPar(); - WriteEmbeddedStatement(ifElseStatement.TrueStatement); + StartNode (ifElseStatement); + WriteKeyword ("if", IfElseStatement.IfKeywordRole); + Space (policy.SpaceBeforeIfParentheses); + LPar (); + Space (policy.SpacesWithinIfParentheses); + ifElseStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinIfParentheses); + RPar (); + WriteEmbeddedStatement (ifElseStatement.TrueStatement); if (!ifElseStatement.FalseStatement.IsNull) { - WriteKeyword("else", IfElseStatement.ElseKeywordRole); - WriteEmbeddedStatement(ifElseStatement.FalseStatement); + WriteKeyword ("else", IfElseStatement.ElseKeywordRole); + WriteEmbeddedStatement (ifElseStatement.FalseStatement); } - return EndNode(ifElseStatement); + return EndNode (ifElseStatement); } - public object VisitLabelStatement(LabelStatement labelStatement, object data) + public object VisitLabelStatement (LabelStatement labelStatement, object data) { - StartNode(labelStatement); - WriteIdentifier(labelStatement.Label); - WriteToken(":", LabelStatement.Roles.Colon); + StartNode (labelStatement); + WriteIdentifier (labelStatement.Label); + WriteToken (":", LabelStatement.Roles.Colon); bool foundLabelledStatement = false; for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) { if (tmp.Role == labelStatement.Role) { @@ -1575,322 +1633,338 @@ namespace ICSharpCode.NRefactory.CSharp // introduce an EmptyStatement so that the output becomes syntactically valid WriteToken(";", LabelStatement.Roles.Semicolon); } - NewLine(); - return EndNode(labelStatement); + NewLine (); + return EndNode (labelStatement); } - public object VisitLockStatement(LockStatement lockStatement, object data) + public object VisitLockStatement (LockStatement lockStatement, object data) { - StartNode(lockStatement); - WriteKeyword("lock"); - Space(policy.SpaceBeforeLockParentheses); - LPar(); - Space(policy.SpacesWithinLockParentheses); - lockStatement.Expression.AcceptVisitor(this, data); - Space(policy.SpacesWithinLockParentheses); - RPar(); - WriteEmbeddedStatement(lockStatement.EmbeddedStatement); - return EndNode(lockStatement); + StartNode (lockStatement); + WriteKeyword ("lock"); + Space (policy.SpaceBeforeLockParentheses); + LPar (); + Space (policy.SpacesWithinLockParentheses); + lockStatement.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinLockParentheses); + RPar (); + WriteEmbeddedStatement (lockStatement.EmbeddedStatement); + return EndNode (lockStatement); } - public object VisitReturnStatement(ReturnStatement returnStatement, object data) + public object VisitReturnStatement (ReturnStatement returnStatement, object data) { - StartNode(returnStatement); - WriteKeyword("return"); + StartNode (returnStatement); + WriteKeyword ("return"); if (!returnStatement.Expression.IsNull) { - Space(); - returnStatement.Expression.AcceptVisitor(this, data); + Space (); + returnStatement.Expression.AcceptVisitor (this, data); } - Semicolon(); - return EndNode(returnStatement); - } - - public object VisitSwitchStatement(SwitchStatement switchStatement, object data) - { - StartNode(switchStatement); - WriteKeyword("switch"); - Space(policy.SpaceBeforeSwitchParentheses); - LPar(); - Space(policy.SpacesWithinSwitchParentheses); - switchStatement.Expression.AcceptVisitor(this, data); - Space(policy.SpacesWithinSwitchParentheses); - RPar(); - OpenBrace(policy.StatementBraceStyle); + Semicolon (); + return EndNode (returnStatement); + } + + public object VisitSwitchStatement (SwitchStatement switchStatement, object data) + { + StartNode (switchStatement); + WriteKeyword ("switch"); + Space (policy.SpaceBeforeSwitchParentheses); + LPar (); + Space (policy.SpacesWithinSwitchParentheses); + switchStatement.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinSwitchParentheses); + RPar (); + OpenBrace (policy.StatementBraceStyle); + if (!policy.IndentSwitchBody) + formatter.Unindent (); + foreach (var section in switchStatement.SwitchSections) - section.AcceptVisitor(this, data); - CloseBrace(policy.StatementBraceStyle); - NewLine(); - return EndNode(switchStatement); + section.AcceptVisitor (this, data); + + if (!policy.IndentSwitchBody) + formatter.Indent (); + CloseBrace (policy.StatementBraceStyle); + NewLine (); + return EndNode (switchStatement); } - public object VisitSwitchSection(SwitchSection switchSection, object data) + public object VisitSwitchSection (SwitchSection switchSection, object data) { - StartNode(switchSection); + StartNode (switchSection); bool first = true; foreach (var label in switchSection.CaseLabels) { if (!first) - NewLine(); - label.AcceptVisitor(this, data); + NewLine (); + label.AcceptVisitor (this, data); first = false; } - foreach (var statement in switchSection.Statements) - statement.AcceptVisitor(this, data); - return EndNode(switchSection); + if (policy.IndentCaseBody) + formatter.Indent (); + + foreach (var statement in switchSection.Statements) { + NewLine (); + statement.AcceptVisitor (this, data); + } + + if (policy.IndentCaseBody) + formatter.Unindent (); + + return EndNode (switchSection); } - public object VisitCaseLabel(CaseLabel caseLabel, object data) + public object VisitCaseLabel (CaseLabel caseLabel, object data) { - StartNode(caseLabel); + StartNode (caseLabel); if (caseLabel.Expression.IsNull) { - WriteKeyword("default"); + WriteKeyword ("default"); } else { - WriteKeyword("case"); - Space(); - caseLabel.Expression.AcceptVisitor(this, data); + WriteKeyword ("case"); + Space (); + caseLabel.Expression.AcceptVisitor (this, data); } - WriteToken(":", CaseLabel.Roles.Colon); - return EndNode(caseLabel); + WriteToken (":", CaseLabel.Roles.Colon); + return EndNode (caseLabel); } - public object VisitThrowStatement(ThrowStatement throwStatement, object data) + public object VisitThrowStatement (ThrowStatement throwStatement, object data) { - StartNode(throwStatement); - WriteKeyword("throw"); + StartNode (throwStatement); + WriteKeyword ("throw"); if (!throwStatement.Expression.IsNull) { - Space(); - throwStatement.Expression.AcceptVisitor(this, data); + Space (); + throwStatement.Expression.AcceptVisitor (this, data); } - Semicolon(); - return EndNode(throwStatement); + Semicolon (); + return EndNode (throwStatement); } - public object VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) + public object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) { - StartNode(tryCatchStatement); - WriteKeyword("try", TryCatchStatement.TryKeywordRole); - tryCatchStatement.TryBlock.AcceptVisitor(this, data); + StartNode (tryCatchStatement); + WriteKeyword ("try", TryCatchStatement.TryKeywordRole); + tryCatchStatement.TryBlock.AcceptVisitor (this, data); foreach (var catchClause in tryCatchStatement.CatchClauses) - catchClause.AcceptVisitor(this, data); + catchClause.AcceptVisitor (this, data); if (!tryCatchStatement.FinallyBlock.IsNull) { - WriteKeyword("finally", TryCatchStatement.FinallyKeywordRole); - tryCatchStatement.FinallyBlock.AcceptVisitor(this, data); + WriteKeyword ("finally", TryCatchStatement.FinallyKeywordRole); + tryCatchStatement.FinallyBlock.AcceptVisitor (this, data); } - return EndNode(tryCatchStatement); + return EndNode (tryCatchStatement); } - public object VisitCatchClause(CatchClause catchClause, object data) + public object VisitCatchClause (CatchClause catchClause, object data) { - StartNode(catchClause); - WriteKeyword("catch"); + StartNode (catchClause); + WriteKeyword ("catch"); if (!catchClause.Type.IsNull) { - Space(policy.SpaceBeforeCatchParentheses); - LPar(); - Space(policy.SpacesWithinCatchParentheses); - catchClause.Type.AcceptVisitor(this, data); + Space (policy.SpaceBeforeCatchParentheses); + LPar (); + Space (policy.SpacesWithinCatchParentheses); + catchClause.Type.AcceptVisitor (this, data); if (!string.IsNullOrEmpty(catchClause.VariableName)) { - Space(); - WriteIdentifier(catchClause.VariableName); + Space (); + WriteIdentifier (catchClause.VariableName); } - Space(policy.SpacesWithinCatchParentheses); - RPar(); + Space (policy.SpacesWithinCatchParentheses); + RPar (); } - catchClause.Body.AcceptVisitor(this, data); - return EndNode(catchClause); + catchClause.Body.AcceptVisitor (this, data); + return EndNode (catchClause); } - public object VisitUncheckedStatement(UncheckedStatement uncheckedStatement, object data) + public object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) { - StartNode(uncheckedStatement); - WriteKeyword("unchecked"); - uncheckedStatement.Body.AcceptVisitor(this, data); - return EndNode(uncheckedStatement); + StartNode (uncheckedStatement); + WriteKeyword ("unchecked"); + uncheckedStatement.Body.AcceptVisitor (this, data); + return EndNode (uncheckedStatement); } - public object VisitUnsafeStatement(UnsafeStatement unsafeStatement, object data) + public object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) { - StartNode(unsafeStatement); - WriteKeyword("unsafe"); - unsafeStatement.Body.AcceptVisitor(this, data); - return EndNode(unsafeStatement); + StartNode (unsafeStatement); + WriteKeyword ("unsafe"); + unsafeStatement.Body.AcceptVisitor (this, data); + return EndNode (unsafeStatement); } - public object VisitUsingStatement(UsingStatement usingStatement, object data) + public object VisitUsingStatement (UsingStatement usingStatement, object data) { - StartNode(usingStatement); - WriteKeyword("using"); - Space(policy.SpaceBeforeUsingParentheses); - LPar(); - Space(policy.SpacesWithinUsingParentheses); + StartNode (usingStatement); + WriteKeyword ("using"); + Space (policy.SpaceBeforeUsingParentheses); + LPar (); + Space (policy.SpacesWithinUsingParentheses); - usingStatement.ResourceAcquisition.AcceptVisitor(this, data); + usingStatement.ResourceAcquisition.AcceptVisitor (this, data); - Space(policy.SpacesWithinUsingParentheses); - RPar(); + Space (policy.SpacesWithinUsingParentheses); + RPar (); - WriteEmbeddedStatement(usingStatement.EmbeddedStatement); + WriteEmbeddedStatement (usingStatement.EmbeddedStatement); - return EndNode(usingStatement); + return EndNode (usingStatement); } - public object VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data) + public object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) { - StartNode(variableDeclarationStatement); - variableDeclarationStatement.Type.AcceptVisitor(this, data); - Space(); - WriteCommaSeparatedList(variableDeclarationStatement.Variables); - Semicolon(); - return EndNode(variableDeclarationStatement); + StartNode (variableDeclarationStatement); + variableDeclarationStatement.Type.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (variableDeclarationStatement.Variables); + Semicolon (); + return EndNode (variableDeclarationStatement); } - public object VisitWhileStatement(WhileStatement whileStatement, object data) + public object VisitWhileStatement (WhileStatement whileStatement, object data) { - StartNode(whileStatement); - WriteKeyword("while", WhileStatement.WhileKeywordRole); - Space(policy.SpaceBeforeWhileParentheses); - LPar(); - Space(policy.SpacesWithinWhileParentheses); - whileStatement.Condition.AcceptVisitor(this, data); - Space(policy.SpacesWithinWhileParentheses); - RPar(); - WriteEmbeddedStatement(whileStatement.EmbeddedStatement); - return EndNode(whileStatement); + StartNode (whileStatement); + WriteKeyword ("while", WhileStatement.WhileKeywordRole); + Space (policy.SpaceBeforeWhileParentheses); + LPar (); + Space (policy.SpacesWithinWhileParentheses); + whileStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinWhileParentheses); + RPar (); + WriteEmbeddedStatement (whileStatement.EmbeddedStatement); + return EndNode (whileStatement); } - public object VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, object data) + public object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) { - StartNode(yieldBreakStatement); - WriteKeyword("yield", YieldBreakStatement.YieldKeywordRole); - WriteKeyword("break", YieldBreakStatement.BreakKeywordRole); - Semicolon(); - return EndNode(yieldBreakStatement); + StartNode (yieldBreakStatement); + WriteKeyword ("yield", YieldBreakStatement.YieldKeywordRole); + WriteKeyword ("break", YieldBreakStatement.BreakKeywordRole); + Semicolon (); + return EndNode (yieldBreakStatement); } - public object VisitYieldStatement(YieldStatement yieldStatement, object data) + public object VisitYieldStatement (YieldStatement yieldStatement, object data) { - StartNode(yieldStatement); - WriteKeyword("yield", YieldStatement.YieldKeywordRole); - WriteKeyword("return", YieldStatement.ReturnKeywordRole); - Space(); - yieldStatement.Expression.AcceptVisitor(this, data); - Semicolon(); - return EndNode(yieldStatement); + StartNode (yieldStatement); + WriteKeyword ("yield", YieldStatement.YieldKeywordRole); + WriteKeyword ("return", YieldStatement.ReturnKeywordRole); + Space (); + yieldStatement.Expression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (yieldStatement); } + #endregion #region TypeMembers - public object VisitAccessor(Accessor accessor, object data) + public object VisitAccessor (Accessor accessor, object data) { - StartNode(accessor); - WriteAttributes(accessor.Attributes); - WriteModifiers(accessor.ModifierTokens); + StartNode (accessor); + WriteAttributes (accessor.Attributes); + WriteModifiers (accessor.ModifierTokens); if (accessor.Role == PropertyDeclaration.GetterRole) { - WriteKeyword("get"); + WriteKeyword ("get"); } else if (accessor.Role == PropertyDeclaration.SetterRole) { - WriteKeyword("set"); + WriteKeyword ("set"); } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) { - WriteKeyword("add"); + WriteKeyword ("add"); } else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) { - WriteKeyword("remove"); + WriteKeyword ("remove"); } - WriteMethodBody(accessor.Body); - return EndNode(accessor); + WriteMethodBody (accessor.Body); + return EndNode (accessor); } - public object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + public object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) { - StartNode(constructorDeclaration); - WriteAttributes(constructorDeclaration.Attributes); - WriteModifiers(constructorDeclaration.ModifierTokens); + StartNode (constructorDeclaration); + WriteAttributes (constructorDeclaration.Attributes); + WriteModifiers (constructorDeclaration.ModifierTokens); TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration; - WriteIdentifier(type != null ? type.Name : constructorDeclaration.Name); - Space(policy.SpaceBeforeConstructorDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + WriteIdentifier (type != null ? type.Name : constructorDeclaration.Name); + Space (policy.SpaceBeforeConstructorDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); if (!constructorDeclaration.Initializer.IsNull) { - Space(); - constructorDeclaration.Initializer.AcceptVisitor(this, data); + Space (); + constructorDeclaration.Initializer.AcceptVisitor (this, data); } - WriteMethodBody(constructorDeclaration.Body); - return EndNode(constructorDeclaration); + WriteMethodBody (constructorDeclaration.Body); + return EndNode (constructorDeclaration); } - public object VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) + public object VisitConstructorInitializer (ConstructorInitializer constructorInitializer, object data) { - StartNode(constructorInitializer); - WriteToken(":", ConstructorInitializer.Roles.Colon); - Space(); + StartNode (constructorInitializer); + WriteToken (":", ConstructorInitializer.Roles.Colon); + Space (); if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) { - WriteKeyword("this"); + WriteKeyword ("this"); } else { - WriteKeyword("base"); + WriteKeyword ("base"); } - Space(policy.SpaceBeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses); - return EndNode(constructorInitializer); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (constructorInitializer); } - public object VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + public object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) { - StartNode(destructorDeclaration); - WriteAttributes(destructorDeclaration.Attributes); - WriteModifiers(destructorDeclaration.ModifierTokens); - WriteToken("~", DestructorDeclaration.TildeRole); + StartNode (destructorDeclaration); + WriteAttributes (destructorDeclaration.Attributes); + WriteModifiers (destructorDeclaration.ModifierTokens); + WriteToken ("~", DestructorDeclaration.TildeRole); TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration; - WriteIdentifier(type != null ? type.Name : destructorDeclaration.Name); - Space(policy.SpaceBeforeConstructorDeclarationParentheses); - LPar(); - RPar(); - WriteMethodBody(destructorDeclaration.Body); - return EndNode(destructorDeclaration); + WriteIdentifier (type != null ? type.Name : destructorDeclaration.Name); + Space (policy.SpaceBeforeConstructorDeclarationParentheses); + LPar (); + RPar (); + WriteMethodBody (destructorDeclaration.Body); + return EndNode (destructorDeclaration); } - public object VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + public object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) { - StartNode(enumMemberDeclaration); - WriteAttributes(enumMemberDeclaration.Attributes); - WriteModifiers(enumMemberDeclaration.ModifierTokens); - WriteIdentifier(enumMemberDeclaration.Name); + StartNode (enumMemberDeclaration); + WriteAttributes (enumMemberDeclaration.Attributes); + WriteModifiers (enumMemberDeclaration.ModifierTokens); + WriteIdentifier (enumMemberDeclaration.Name); if (!enumMemberDeclaration.Initializer.IsNull) { - Space(policy.SpaceAroundAssignment); - WriteToken("=", EnumMemberDeclaration.Roles.Assign); - Space(policy.SpaceAroundAssignment); - enumMemberDeclaration.Initializer.AcceptVisitor(this, data); - } - return EndNode(enumMemberDeclaration); - } - - public object VisitEventDeclaration(EventDeclaration eventDeclaration, object data) - { - StartNode(eventDeclaration); - WriteAttributes(eventDeclaration.Attributes); - WriteModifiers(eventDeclaration.ModifierTokens); - WriteKeyword("event"); - eventDeclaration.ReturnType.AcceptVisitor(this, data); - Space(); - WriteCommaSeparatedList(eventDeclaration.Variables); - Semicolon(); - return EndNode(eventDeclaration); - } - - public object VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration, object data) - { - StartNode(customEventDeclaration); - WriteAttributes(customEventDeclaration.Attributes); - WriteModifiers(customEventDeclaration.ModifierTokens); - WriteKeyword("event"); - customEventDeclaration.ReturnType.AcceptVisitor(this, data); - Space(); - WritePrivateImplementationType(customEventDeclaration.PrivateImplementationType); - WriteIdentifier(customEventDeclaration.Name); - OpenBrace(policy.EventBraceStyle); + Space (policy.SpaceAroundAssignment); + WriteToken ("=", EnumMemberDeclaration.Roles.Assign); + Space (policy.SpaceAroundAssignment); + enumMemberDeclaration.Initializer.AcceptVisitor (this, data); + } + return EndNode (enumMemberDeclaration); + } + + public object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) + { + StartNode (eventDeclaration); + WriteAttributes (eventDeclaration.Attributes); + WriteModifiers (eventDeclaration.ModifierTokens); + WriteKeyword ("event"); + eventDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (eventDeclaration.Variables); + Semicolon (); + return EndNode (eventDeclaration); + } + + public object VisitCustomEventDeclaration (CustomEventDeclaration customEventDeclaration, object data) + { + StartNode (customEventDeclaration); + WriteAttributes (customEventDeclaration.Attributes); + WriteModifiers (customEventDeclaration.ModifierTokens); + WriteKeyword ("event"); + customEventDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (customEventDeclaration.PrivateImplementationType); + WriteIdentifier (customEventDeclaration.Name); + OpenBrace (policy.EventBraceStyle); // output add/remove in their original order foreach (AstNode node in customEventDeclaration.Children) { if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) { - node.AcceptVisitor(this, data); + node.AcceptVisitor (this, data); } } - CloseBrace(policy.EventBraceStyle); - NewLine(); - return EndNode(customEventDeclaration); + CloseBrace (policy.EventBraceStyle); + NewLine (); + return EndNode (customEventDeclaration); } public object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) @@ -1907,399 +1981,402 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) { - StartNode(fixedFieldDeclaration); - WriteAttributes(fixedFieldDeclaration.Attributes); - WriteModifiers(fixedFieldDeclaration.ModifierTokens); - WriteKeyword("fixed"); - Space(); + StartNode (fixedFieldDeclaration); + WriteAttributes (fixedFieldDeclaration.Attributes); + WriteModifiers (fixedFieldDeclaration.ModifierTokens); + WriteKeyword ("fixed"); + Space (); fixedFieldDeclaration.ReturnType.AcceptVisitor (this, data); - Space(); - WriteCommaSeparatedList(fixedFieldDeclaration.Variables); - Semicolon(); - return EndNode(fixedFieldDeclaration); + Space (); + WriteCommaSeparatedList (fixedFieldDeclaration.Variables); + Semicolon (); + return EndNode (fixedFieldDeclaration); } public object VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, object data) { - StartNode(fixedVariableInitializer); - WriteIdentifier(fixedVariableInitializer.Name); + StartNode (fixedVariableInitializer); + WriteIdentifier (fixedVariableInitializer.Name); if (!fixedVariableInitializer.CountExpression.IsNull) { - WriteToken("[", AstNode.Roles.LBracket); - Space(policy.SpacesWithinBrackets); - fixedVariableInitializer.CountExpression.AcceptVisitor(this, data); - Space(policy.SpacesWithinBrackets); - WriteToken("]", AstNode.Roles.RBracket); + WriteToken ("[", AstNode.Roles.LBracket); + Space (policy.SpacesWithinBrackets); + fixedVariableInitializer.CountExpression.AcceptVisitor (this, data); + Space (policy.SpacesWithinBrackets); + WriteToken ("]", AstNode.Roles.RBracket); } - return EndNode(fixedVariableInitializer); + return EndNode (fixedVariableInitializer); } - public object VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + public object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) { - StartNode(indexerDeclaration); - WriteAttributes(indexerDeclaration.Attributes); - WriteModifiers(indexerDeclaration.ModifierTokens); - indexerDeclaration.ReturnType.AcceptVisitor(this, data); - WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType); + StartNode (indexerDeclaration); + WriteAttributes (indexerDeclaration.Attributes); + WriteModifiers (indexerDeclaration.ModifierTokens); + indexerDeclaration.ReturnType.AcceptVisitor (this, data); + WritePrivateImplementationType (indexerDeclaration.PrivateImplementationType); WriteKeyword ("this"); - Space(policy.SpaceBeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - OpenBrace(policy.PropertyBraceStyle); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInBrackets (indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + OpenBrace (policy.PropertyBraceStyle); // output get/set in their original order foreach (AstNode node in indexerDeclaration.Children) { if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { - node.AcceptVisitor(this, data); + node.AcceptVisitor (this, data); } } - CloseBrace(policy.PropertyBraceStyle); - NewLine(); - return EndNode(indexerDeclaration); + CloseBrace (policy.PropertyBraceStyle); + NewLine (); + return EndNode (indexerDeclaration); } - public object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + public object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) { - StartNode(methodDeclaration); - WriteAttributes(methodDeclaration.Attributes); - WriteModifiers(methodDeclaration.ModifierTokens); - methodDeclaration.ReturnType.AcceptVisitor(this, data); - Space(); - WritePrivateImplementationType(methodDeclaration.PrivateImplementationType); - WriteIdentifier(methodDeclaration.Name); - WriteTypeParameters(methodDeclaration.TypeParameters); - Space(policy.SpaceBeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + StartNode (methodDeclaration); + WriteAttributes (methodDeclaration.Attributes); + WriteModifiers (methodDeclaration.ModifierTokens); + methodDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (methodDeclaration.PrivateImplementationType); + WriteIdentifier (methodDeclaration.Name); + WriteTypeParameters (methodDeclaration.TypeParameters); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); foreach (Constraint constraint in methodDeclaration.Constraints) { - constraint.AcceptVisitor(this, data); + constraint.AcceptVisitor (this, data); } - WriteMethodBody(methodDeclaration.Body); - return EndNode(methodDeclaration); + WriteMethodBody (methodDeclaration.Body); + return EndNode (methodDeclaration); } - public object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + public object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) { - StartNode(operatorDeclaration); - WriteAttributes(operatorDeclaration.Attributes); - WriteModifiers(operatorDeclaration.ModifierTokens); + StartNode (operatorDeclaration); + WriteAttributes (operatorDeclaration.Attributes); + WriteModifiers (operatorDeclaration.ModifierTokens); if (operatorDeclaration.OperatorType == OperatorType.Explicit) { - WriteKeyword("explicit", OperatorDeclaration.OperatorTypeRole); + WriteKeyword ("explicit", OperatorDeclaration.OperatorTypeRole); } else if (operatorDeclaration.OperatorType == OperatorType.Implicit) { - WriteKeyword("implicit", OperatorDeclaration.OperatorTypeRole); + WriteKeyword ("implicit", OperatorDeclaration.OperatorTypeRole); } else { - operatorDeclaration.ReturnType.AcceptVisitor(this, data); + operatorDeclaration.ReturnType.AcceptVisitor (this, data); } - WriteKeyword("operator", OperatorDeclaration.OperatorKeywordRole); - Space(); + WriteKeyword ("operator", OperatorDeclaration.OperatorKeywordRole); + Space (); if (operatorDeclaration.OperatorType == OperatorType.Explicit - || operatorDeclaration.OperatorType == OperatorType.Implicit) - { - operatorDeclaration.ReturnType.AcceptVisitor(this, data); + || operatorDeclaration.OperatorType == OperatorType.Implicit) { + operatorDeclaration.ReturnType.AcceptVisitor (this, data); } else { - WriteToken(OperatorDeclaration.GetToken(operatorDeclaration.OperatorType), OperatorDeclaration.OperatorTypeRole); + WriteToken (OperatorDeclaration.GetToken (operatorDeclaration.OperatorType), OperatorDeclaration.OperatorTypeRole); } - Space(policy.SpaceBeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - WriteMethodBody(operatorDeclaration.Body); - return EndNode(operatorDeclaration); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + WriteMethodBody (operatorDeclaration.Body); + return EndNode (operatorDeclaration); } - public object VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) + public object VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, object data) { - StartNode(parameterDeclaration); - WriteAttributes(parameterDeclaration.Attributes); + StartNode (parameterDeclaration); + WriteAttributes (parameterDeclaration.Attributes); switch (parameterDeclaration.ParameterModifier) { - case ParameterModifier.Ref: - WriteKeyword("ref", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.Out: - WriteKeyword("out", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.Params: - WriteKeyword("params", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.This: - WriteKeyword("this", ParameterDeclaration.ModifierRole); - break; + case ParameterModifier.Ref: + WriteKeyword ("ref", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Out: + WriteKeyword ("out", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Params: + WriteKeyword ("params", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.This: + WriteKeyword ("this", ParameterDeclaration.ModifierRole); + break; } - parameterDeclaration.Type.AcceptVisitor(this, data); - if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name)) - Space(); - if (!string.IsNullOrEmpty(parameterDeclaration.Name)) - WriteIdentifier(parameterDeclaration.Name); + parameterDeclaration.Type.AcceptVisitor (this, data); + if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty (parameterDeclaration.Name)) + Space (); + if (!string.IsNullOrEmpty (parameterDeclaration.Name)) + WriteIdentifier (parameterDeclaration.Name); if (!parameterDeclaration.DefaultExpression.IsNull) { - Space(policy.SpaceAroundAssignment); - WriteToken("=", ParameterDeclaration.Roles.Assign); - Space(policy.SpaceAroundAssignment); - parameterDeclaration.DefaultExpression.AcceptVisitor(this, data); + Space (policy.SpaceAroundAssignment); + WriteToken ("=", ParameterDeclaration.Roles.Assign); + Space (policy.SpaceAroundAssignment); + parameterDeclaration.DefaultExpression.AcceptVisitor (this, data); } - return EndNode(parameterDeclaration); + return EndNode (parameterDeclaration); } - public object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + public object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) { - StartNode(propertyDeclaration); - WriteAttributes(propertyDeclaration.Attributes); - WriteModifiers(propertyDeclaration.ModifierTokens); - propertyDeclaration.ReturnType.AcceptVisitor(this, data); - Space(); - WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType); - WriteIdentifier(propertyDeclaration.Name); - OpenBrace(policy.PropertyBraceStyle); + StartNode (propertyDeclaration); + WriteAttributes (propertyDeclaration.Attributes); + WriteModifiers (propertyDeclaration.ModifierTokens); + propertyDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (propertyDeclaration.PrivateImplementationType); + WriteIdentifier (propertyDeclaration.Name); + OpenBrace (policy.PropertyBraceStyle); // output get/set in their original order foreach (AstNode node in propertyDeclaration.Children) { if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { - node.AcceptVisitor(this, data); + node.AcceptVisitor (this, data); } } - CloseBrace(policy.PropertyBraceStyle); - NewLine(); - return EndNode(propertyDeclaration); + CloseBrace (policy.PropertyBraceStyle); + NewLine (); + return EndNode (propertyDeclaration); } + #endregion #region Other nodes - public object VisitVariableInitializer(VariableInitializer variableInitializer, object data) + public object VisitVariableInitializer (VariableInitializer variableInitializer, object data) { - StartNode(variableInitializer); - WriteIdentifier(variableInitializer.Name); + StartNode (variableInitializer); + WriteIdentifier (variableInitializer.Name); if (!variableInitializer.Initializer.IsNull) { - Space(policy.SpaceAroundAssignment); - WriteToken("=", VariableInitializer.Roles.Assign); - Space(policy.SpaceAroundAssignment); - variableInitializer.Initializer.AcceptVisitor(this, data); + Space (policy.SpaceAroundAssignment); + WriteToken ("=", VariableInitializer.Roles.Assign); + Space (policy.SpaceAroundAssignment); + variableInitializer.Initializer.AcceptVisitor (this, data); } - return EndNode(variableInitializer); + return EndNode (variableInitializer); } - public object VisitCompilationUnit(CompilationUnit compilationUnit, object data) + public object VisitCompilationUnit (CompilationUnit compilationUnit, object data) { // don't do node tracking as we visit all children directly foreach (AstNode node in compilationUnit.Children) - node.AcceptVisitor(this, data); + node.AcceptVisitor (this, data); return null; } - public object VisitSimpleType(SimpleType simpleType, object data) + public object VisitSimpleType (SimpleType simpleType, object data) { - StartNode(simpleType); - WriteIdentifier(simpleType.Identifier); - WriteTypeArguments(simpleType.TypeArguments); - return EndNode(simpleType); + StartNode (simpleType); + WriteIdentifier (simpleType.Identifier); + WriteTypeArguments (simpleType.TypeArguments); + return EndNode (simpleType); } - public object VisitMemberType(MemberType memberType, object data) + public object VisitMemberType (MemberType memberType, object data) { - StartNode(memberType); - memberType.Target.AcceptVisitor(this, data); + StartNode (memberType); + memberType.Target.AcceptVisitor (this, data); if (memberType.IsDoubleColon) - WriteToken("::", MemberType.Roles.Dot); + WriteToken ("::", MemberType.Roles.Dot); else - WriteToken(".", MemberType.Roles.Dot); - WriteIdentifier(memberType.MemberName); - WriteTypeArguments(memberType.TypeArguments); - return EndNode(memberType); + WriteToken (".", MemberType.Roles.Dot); + WriteIdentifier (memberType.MemberName); + WriteTypeArguments (memberType.TypeArguments); + return EndNode (memberType); } - public object VisitComposedType(ComposedType composedType, object data) + public object VisitComposedType (ComposedType composedType, object data) { - StartNode(composedType); - composedType.BaseType.AcceptVisitor(this, data); + StartNode (composedType); + composedType.BaseType.AcceptVisitor (this, data); if (composedType.HasNullableSpecifier) - WriteToken("?", ComposedType.NullableRole); + WriteToken ("?", ComposedType.NullableRole); for (int i = 0; i < composedType.PointerRank; i++) - WriteToken("*", ComposedType.PointerRole); + WriteToken ("*", ComposedType.PointerRole); foreach (var node in composedType.ArraySpecifiers) - node.AcceptVisitor(this, data); - return EndNode(composedType); + node.AcceptVisitor (this, data); + return EndNode (composedType); } - public object VisitArraySpecifier(ArraySpecifier arraySpecifier, object data) + public object VisitArraySpecifier (ArraySpecifier arraySpecifier, object data) { - StartNode(arraySpecifier); - WriteToken("[", ArraySpecifier.Roles.LBracket); + StartNode (arraySpecifier); + WriteToken ("[", ArraySpecifier.Roles.LBracket); foreach (var comma in arraySpecifier.GetChildrenByRole(ArraySpecifier.Roles.Comma)) { - WriteSpecialsUpToNode(comma); - formatter.WriteToken(","); + WriteSpecialsUpToNode (comma); + formatter.WriteToken (","); lastWritten = LastWritten.Other; } - WriteToken("]", ArraySpecifier.Roles.RBracket); - return EndNode(arraySpecifier); + WriteToken ("]", ArraySpecifier.Roles.RBracket); + return EndNode (arraySpecifier); } - public object VisitPrimitiveType(PrimitiveType primitiveType, object data) + public object VisitPrimitiveType (PrimitiveType primitiveType, object data) { - StartNode(primitiveType); - WriteKeyword(primitiveType.Keyword); + StartNode (primitiveType); + WriteKeyword (primitiveType.Keyword); if (primitiveType.Keyword == "new") { // new() constraint - LPar(); - RPar(); + LPar (); + RPar (); } - return EndNode(primitiveType); + return EndNode (primitiveType); } - public object VisitComment(Comment comment, object data) + public object VisitComment (Comment comment, object data) { if (lastWritten == LastWritten.Division) { // When there's a comment starting after a division operator // "1.0 / /*comment*/a", then we need to insert a space in front of the comment. - formatter.Space(); + formatter.Space (); } - formatter.WriteComment(comment.CommentType, comment.Content); + formatter.StartNode(comment); + formatter.WriteComment (comment.CommentType, comment.Content); + formatter.EndNode(comment); lastWritten = LastWritten.Whitespace; return null; } - public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + public object VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, object data) { - StartNode(typeParameterDeclaration); - WriteAttributes(typeParameterDeclaration.Attributes); + StartNode (typeParameterDeclaration); + WriteAttributes (typeParameterDeclaration.Attributes); switch (typeParameterDeclaration.Variance) { - case VarianceModifier.Invariant: - break; - case VarianceModifier.Covariant: - WriteKeyword("out"); - break; - case VarianceModifier.Contravariant: - WriteKeyword("in"); - break; - default: - throw new NotSupportedException("Invalid value for VarianceModifier"); + case VarianceModifier.Invariant: + break; + case VarianceModifier.Covariant: + WriteKeyword ("out"); + break; + case VarianceModifier.Contravariant: + WriteKeyword ("in"); + break; + default: + throw new NotSupportedException ("Invalid value for VarianceModifier"); } - WriteIdentifier(typeParameterDeclaration.Name); - return EndNode(typeParameterDeclaration); + WriteIdentifier (typeParameterDeclaration.Name); + return EndNode (typeParameterDeclaration); } - public object VisitConstraint(Constraint constraint, object data) + public object VisitConstraint (Constraint constraint, object data) { - StartNode(constraint); - Space(); - WriteKeyword("where"); - WriteIdentifier(constraint.TypeParameter); - Space(); - WriteToken(":", Constraint.ColonRole); - Space(); - WriteCommaSeparatedList(constraint.BaseTypes); - return EndNode(constraint); + StartNode (constraint); + Space (); + WriteKeyword ("where"); + WriteIdentifier (constraint.TypeParameter); + Space (); + WriteToken (":", Constraint.ColonRole); + Space (); + WriteCommaSeparatedList (constraint.BaseTypes); + return EndNode (constraint); } - public object VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) + public object VisitCSharpTokenNode (CSharpTokenNode cSharpTokenNode, object data) { CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken; if (mod != null) { - StartNode(mod); - WriteKeyword(CSharpModifierToken.GetModifierName(mod.Modifier)); - return EndNode(mod); + StartNode (mod); + WriteKeyword (CSharpModifierToken.GetModifierName (mod.Modifier)); + return EndNode (mod); } else { - throw new NotSupportedException("Should never visit individual tokens"); + throw new NotSupportedException ("Should never visit individual tokens"); } } - public object VisitIdentifier(Identifier identifier, object data) + public object VisitIdentifier (Identifier identifier, object data) { - StartNode(identifier); - WriteIdentifier(identifier.Name); - return EndNode(identifier); + StartNode (identifier); + WriteIdentifier (identifier.Name); + return EndNode (identifier); } + #endregion #region Pattern Nodes - public object VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, object data) + public object VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, object data) { - StartNode(placeholder); - pattern.AcceptVisitor(this, data); - return EndNode(placeholder); + StartNode (placeholder); + pattern.AcceptVisitor (this, data); + return EndNode (placeholder); } - object IPatternAstVisitor.VisitAnyNode(AnyNode anyNode, object data) + object IPatternAstVisitor.VisitAnyNode (AnyNode anyNode, object data) { - if (!string.IsNullOrEmpty(anyNode.GroupName)) { - WriteIdentifier(anyNode.GroupName); - WriteToken(":", AstNode.Roles.Colon); + if (!string.IsNullOrEmpty (anyNode.GroupName)) { + WriteIdentifier (anyNode.GroupName); + WriteToken (":", AstNode.Roles.Colon); } - WriteKeyword("anyNode"); + WriteKeyword ("anyNode"); return null; } - object IPatternAstVisitor.VisitBackreference(Backreference backreference, object data) + object IPatternAstVisitor.VisitBackreference (Backreference backreference, object data) { - WriteKeyword("backreference"); - LPar(); - WriteIdentifier(backreference.ReferencedGroupName); - RPar(); + WriteKeyword ("backreference"); + LPar (); + WriteIdentifier (backreference.ReferencedGroupName); + RPar (); return null; } - object IPatternAstVisitor.VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference, object data) + object IPatternAstVisitor.VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference, object data) { - WriteKeyword("identifierBackreference"); - LPar(); - WriteIdentifier(identifierExpressionBackreference.ReferencedGroupName); - RPar(); + WriteKeyword ("identifierBackreference"); + LPar (); + WriteIdentifier (identifierExpressionBackreference.ReferencedGroupName); + RPar (); return null; } - object IPatternAstVisitor.VisitChoice(Choice choice, object data) + object IPatternAstVisitor.VisitChoice (Choice choice, object data) { - WriteKeyword("choice"); - Space(); - LPar(); - NewLine(); - formatter.Indent(); + WriteKeyword ("choice"); + Space (); + LPar (); + NewLine (); + formatter.Indent (); foreach (INode alternative in choice) { - VisitNodeInPattern(alternative, data); - if (alternative != choice.Last()) - WriteToken(",", AstNode.Roles.Comma); - NewLine(); + VisitNodeInPattern (alternative, data); + if (alternative != choice.Last ()) + WriteToken (",", AstNode.Roles.Comma); + NewLine (); } - formatter.Unindent(); - RPar(); + formatter.Unindent (); + RPar (); return null; } - object IPatternAstVisitor.VisitNamedNode(NamedNode namedNode, object data) + object IPatternAstVisitor.VisitNamedNode (NamedNode namedNode, object data) { - if (!string.IsNullOrEmpty(namedNode.GroupName)) { - WriteIdentifier(namedNode.GroupName); - WriteToken(":", AstNode.Roles.Colon); + if (!string.IsNullOrEmpty (namedNode.GroupName)) { + WriteIdentifier (namedNode.GroupName); + WriteToken (":", AstNode.Roles.Colon); } - VisitNodeInPattern(namedNode.ChildNode, data); + VisitNodeInPattern (namedNode.ChildNode, data); return null; } - object IPatternAstVisitor.VisitRepeat(Repeat repeat, object data) + object IPatternAstVisitor.VisitRepeat (Repeat repeat, object data) { - WriteKeyword("repeat"); - LPar(); + WriteKeyword ("repeat"); + LPar (); if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) { - WriteIdentifier(repeat.MinCount.ToString()); - WriteToken(",", AstNode.Roles.Comma); - WriteIdentifier(repeat.MaxCount.ToString()); - WriteToken(",", AstNode.Roles.Comma); + WriteIdentifier (repeat.MinCount.ToString ()); + WriteToken (",", AstNode.Roles.Comma); + WriteIdentifier (repeat.MaxCount.ToString ()); + WriteToken (",", AstNode.Roles.Comma); } - VisitNodeInPattern(repeat.ChildNode, data); - RPar(); + VisitNodeInPattern (repeat.ChildNode, data); + RPar (); return null; } - object IPatternAstVisitor.VisitOptionalNode(OptionalNode optionalNode, object data) + object IPatternAstVisitor.VisitOptionalNode (OptionalNode optionalNode, object data) { - WriteKeyword("optional"); - LPar(); - VisitNodeInPattern(optionalNode.ChildNode, data); - RPar(); + WriteKeyword ("optional"); + LPar (); + VisitNodeInPattern (optionalNode.ChildNode, data); + RPar (); return null; } - void VisitNodeInPattern(INode childNode, object data) + void VisitNodeInPattern (INode childNode, object data) { AstNode astNode = childNode as AstNode; if (astNode != null) { - astNode.AcceptVisitor(this, data); + astNode.AcceptVisitor (this, data); } else { Pattern pattern = childNode as Pattern; if (pattern != null) { - pattern.AcceptVisitor(this, data); + pattern.AcceptVisitor (this, data); } else { - throw new InvalidOperationException("Unknown node type in pattern"); + throw new InvalidOperationException ("Unknown node type in pattern"); } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs index f8c1340e58..a901cb78a0 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -14,12 +14,24 @@ namespace ICSharpCode.NRefactory.CSharp readonly TextWriter textWriter; int indentation; bool needsIndent = true; + + public int Indentation { + get { + return this.indentation; + } + set { + this.indentation = value; + } + } + + public string IndentationString { get; set; } public TextWriterOutputFormatter(TextWriter textWriter) { if (textWriter == null) throw new ArgumentNullException("textWriter"); this.textWriter = textWriter; + this.IndentationString = "\t"; } public void WriteIdentifier(string ident) @@ -48,18 +60,68 @@ namespace ICSharpCode.NRefactory.CSharp public void OpenBrace(BraceStyle style) { - WriteIndentation(); - textWriter.Write(' '); - textWriter.Write('{'); + switch (style) { + case BraceStyle.DoNotChange: + case BraceStyle.EndOfLine: + WriteIndentation(); + textWriter.Write(' '); + textWriter.Write('{'); + break; + case BraceStyle.EndOfLineWithoutSpace: + WriteIndentation(); + textWriter.Write('{'); + break; + case BraceStyle.NextLine: + NewLine (); + WriteIndentation(); + textWriter.Write('{'); + break; + + case BraceStyle.NextLineShifted: + NewLine (); + Indent(); + WriteIndentation(); + textWriter.Write('{'); + NewLine(); + return; + case BraceStyle.NextLineShifted2: + NewLine (); + Indent(); + WriteIndentation(); + textWriter.Write('{'); + break; + default: + throw new ArgumentOutOfRangeException (); + } Indent(); NewLine(); } public void CloseBrace(BraceStyle style) { - Unindent(); - WriteIndentation(); - textWriter.Write('}'); + switch (style) { + case BraceStyle.DoNotChange: + case BraceStyle.EndOfLine: + case BraceStyle.EndOfLineWithoutSpace: + case BraceStyle.NextLine: + Unindent(); + WriteIndentation(); + textWriter.Write('}'); + break; + case BraceStyle.NextLineShifted: + WriteIndentation(); + textWriter.Write('}'); + Unindent(); + break; + case BraceStyle.NextLineShifted2: + Unindent(); + WriteIndentation(); + textWriter.Write('}'); + Unindent(); + break; + default: + throw new ArgumentOutOfRangeException (); + } } void WriteIndentation() @@ -67,7 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp if (needsIndent) { needsIndent = false; for (int i = 0; i < indentation; i++) { - textWriter.Write('\t'); + textWriter.Write(this.IndentationString); } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs new file mode 100644 index 0000000000..d9274ecee8 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -0,0 +1,3155 @@ +// +// CSharpParser.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Mono.CSharp; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class CSharpParser + { + class ConversionVisitor : StructuralVisitor + { + CompilationUnit unit = new CompilationUnit (); + internal bool convertTypeSystemMode; + + public CompilationUnit Unit { + get { + return unit; + } + set { + unit = value; + } + } + + public LocationsBag LocationsBag { + get; + private set; + } + + public ConversionVisitor (bool convertTypeSystemMode, LocationsBag locationsBag) + { + this.convertTypeSystemMode = convertTypeSystemMode; + this.LocationsBag = locationsBag; + } + + public static AstLocation Convert (Mono.CSharp.Location loc) + { + return new AstLocation (loc.Row, loc.Column); + } + + + #region Global + Stack namespaceStack = new Stack (); + + void AddTypeArguments (ATypeNameExpression texpr, AstType result) + { + if (texpr.TypeArguments == null || texpr.TypeArguments.Args == null) + return; + var loc = LocationsBag.GetLocations (texpr.TypeArguments); + if (loc != null && loc.Count >= 2) + result.AddChild (new CSharpTokenNode (Convert (loc [loc.Count - 2]), 1), AstType.Roles.LChevron); + int i = 0; + foreach (var arg in texpr.TypeArguments.Args) { + result.AddChild (ConvertToType (arg), AstType.Roles.TypeArgument); + if (loc != null && i < loc.Count - 2) + result.AddChild (new CSharpTokenNode (Convert (loc [i++]), 1), AstType.Roles.Comma); + } + if (loc != null && loc.Count >= 2) + result.AddChild (new CSharpTokenNode (Convert (loc [loc.Count - 1]), 1), AstType.Roles.RChevron); + } + + AstType ConvertToType (MemberName memberName) + { + AstType result; + if (memberName.Left != null) { + result = new MemberType () { MemberName = memberName.Name }; + result.AddChild (ConvertToType (memberName.Left), MemberType.TargetRole); + } else { + result = new SimpleType () { Identifier = memberName.Name }; + } + if (memberName.TypeArguments != null && !memberName.TypeArguments.IsEmpty) { + foreach (var arg in memberName.TypeArguments.Args) { + result.AddChild (ConvertToType (arg), AstType.Roles.TypeArgument); + } + } + return result; + } + + AstType ConvertToType (Mono.CSharp.Expression typeName) + { + if (typeName == null) // may happen in typeof(Generic<,,,,>) + return new SimpleType (); + + if (typeName is TypeExpression) { + var typeExpr = (Mono.CSharp.TypeExpression)typeName; + return new PrimitiveType (typeExpr.GetSignatureForError (), Convert (typeExpr.Location)); + } + + if (typeName is Mono.CSharp.QualifiedAliasMember) { + var qam = (Mono.CSharp.QualifiedAliasMember)typeName; + var memberType = new MemberType (); + memberType.Target = new SimpleType (qam.alias, Convert (qam.Location)); + memberType.IsDoubleColon = true; + memberType.MemberName = qam.Name; + return memberType; + } + + if (typeName is MemberAccess) { + MemberAccess ma = (MemberAccess)typeName; + + var memberType = new MemberType (); + memberType.AddChild (ConvertToType (ma.LeftExpression), MemberType.TargetRole); + memberType.MemberNameToken = Identifier.Create (ma.Name, Convert (ma.Location)); + + AddTypeArguments (ma, memberType); + return memberType; + } + + if (typeName is SimpleName) { + var sn = (SimpleName)typeName; + var result = new SimpleType (sn.Name, Convert (sn.Location)); + AddTypeArguments (sn, result); + return result; + } + + if (typeName is ComposedCast) { + var cc = (ComposedCast)typeName; + var baseType = ConvertToType (cc.Left); + var result = new ComposedType () { BaseType = baseType }; + var ccSpec = cc.Spec; + while (ccSpec != null) { + if (ccSpec.IsNullable) { + result.HasNullableSpecifier = true; + } else if (ccSpec.IsPointer) { + result.PointerRank++; + } else { + var location = LocationsBag.GetLocations (ccSpec); + var spec = new ArraySpecifier () { Dimensions = ccSpec.Dimension }; + spec.AddChild (new CSharpTokenNode (Convert (ccSpec.Location), 1), FieldDeclaration.Roles.LBracket); + if (location != null) + spec.AddChild (new CSharpTokenNode (Convert (location [0]), 1), FieldDeclaration.Roles.RBracket); + + result.ArraySpecifiers.Add (spec); + } + ccSpec = ccSpec.Next; + } + return result; + } + + if (typeName is SpecialContraintExpr) { + var sce = (SpecialContraintExpr)typeName; + switch (sce.Constraint) { + case SpecialConstraint.Class: + return new PrimitiveType ("class", Convert (sce.Location)); + case SpecialConstraint.Struct: + return new PrimitiveType ("struct", Convert (sce.Location)); + case SpecialConstraint.Constructor: + return new PrimitiveType ("new", Convert (sce.Location)); + } + } + System.Console.WriteLine ("Error while converting :" + typeName + " - unknown type name"); + System.Console.WriteLine (Environment.StackTrace); + return new SimpleType ("unknown"); + } + + IEnumerable GetAttributes (List optAttributes) + { + if (optAttributes == null) + yield break; + foreach (var attr in optAttributes) { + Attribute result = new Attribute (); + result.Type = ConvertToType (attr.TypeNameExpression); + var loc = LocationsBag.GetLocations (attr); + result.HasArgumentList = loc != null; + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LPar); + + if (attr.PosArguments != null) { + foreach (var arg in attr.PosArguments) { + result.AddChild ((Expression)arg.Expr.Accept (this), Attribute.Roles.Argument); + } + } + if (attr.NamedArguments != null) { + foreach (NamedArgument na in attr.NamedArguments) { + var newArg = new AssignmentExpression (); + newArg.Operator = AssignmentOperatorType.Assign; + newArg.AddChild (new IdentifierExpression (na.Name, Convert (na.Location)), AssignmentExpression.LeftRole); + + var argLoc = LocationsBag.GetLocations (na); + if (argLoc != null) + newArg.AddChild (new CSharpTokenNode (Convert (argLoc[0]), 1), AssignmentExpression.Roles.Assign); + newArg.AddChild ((Expression)na.Expr.Accept (this), AssignmentExpression.RightRole); + result.AddChild (newArg, Attribute.Roles.Argument); + } + } + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RPar); + + yield return result; + } + } + + AttributeSection ConvertAttributeSection (List optAttributes) + { + if (optAttributes == null) + return null; + + AttributeSection result = new AttributeSection (); + var loc = LocationsBag.GetLocations (optAttributes); + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LBracket); + + result.AttributeTarget = optAttributes.First ().ExplicitTarget; + foreach (var attr in GetAttributes (optAttributes)) { + result.AddChild (attr, AttributeSection.AttributeRole); + } + + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RBracket); + return result; + } + + public override void Visit (UsingsBag.Namespace nspace) + { + NamespaceDeclaration nDecl = null; + if (nspace.Name != null) { + nDecl = new NamespaceDeclaration (); + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.NamespaceLocation), "namespace".Length), NamespaceDeclaration.Roles.Keyword); + ConvertNamespaceName (nspace.Name, nDecl); + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.OpenBrace), 1), NamespaceDeclaration.Roles.LBrace); + AddToNamespace (nDecl); + namespaceStack.Push (nDecl); + + } + VisitNamespaceUsings (nspace); + VisitNamespaceBody (nspace); + + if (nDecl != null) { + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.CloseBrace), 1), NamespaceDeclaration.Roles.RBrace); + if (!nspace.OptSemicolon.IsNull) + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.OptSemicolon), 1), NamespaceDeclaration.Roles.Semicolon); + + namespaceStack.Pop (); + } + } + + void ConvertNamespaceName (MemberName memberName, NamespaceDeclaration namespaceDecl) + { + AstNode insertPos = null; + while (memberName != null) { + Identifier newIdent = Identifier.Create (memberName.Name, Convert (memberName.Location)); + namespaceDecl.InsertChildBefore (insertPos, newIdent, NamespaceDeclaration.Roles.Identifier); + insertPos = newIdent; + memberName = memberName.Left; + } + } + + public override void Visit (UsingsBag.Using u) + { + UsingDeclaration ud = new UsingDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.UsingLocation), "using".Length), UsingDeclaration.Roles.Keyword); + ud.AddChild (ConvertImport (u.NSpace), UsingDeclaration.ImportRole); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + public override void Visit (UsingsBag.AliasUsing u) + { + UsingAliasDeclaration ud = new UsingAliasDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.UsingLocation), "using".Length), UsingAliasDeclaration.Roles.Keyword); + ud.AddChild (Identifier.Create (u.Identifier.Value, Convert (u.Identifier.Location)), UsingAliasDeclaration.AliasRole); + ud.AddChild (new CSharpTokenNode (Convert (u.AssignLocation), 1), UsingAliasDeclaration.Roles.Assign); + ud.AddChild (ConvertImport (u.Nspace), UsingAliasDeclaration.ImportRole); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingAliasDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + public override void Visit (UsingsBag.ExternAlias u) + { + var ud = new ExternAliasDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.ExternLocation), "extern".Length), ExternAliasDeclaration.Roles.Keyword); + ud.AddChild (new CSharpTokenNode (Convert (u.AliasLocation), "alias".Length), ExternAliasDeclaration.AliasRole); + ud.AddChild (Identifier.Create (u.Identifier.Value, Convert (u.Identifier.Location)), ExternAliasDeclaration.Roles.Identifier); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingAliasDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + AstType ConvertImport (MemberName memberName) + { + if (memberName.Left != null) { + // left.name + var t = new MemberType(); + t.IsDoubleColon = memberName.IsDoubleColon; + t.AddChild (ConvertImport (memberName.Left), MemberType.TargetRole); + t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), MemberType.Roles.Identifier); + AddTypeArguments (t, (List)null, memberName.TypeArguments); + return t; + } else { + SimpleType t = new SimpleType(); + t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), SimpleType.Roles.Identifier); + AddTypeArguments (t, (List)null, memberName.TypeArguments); + return t; + } + } + + public override void Visit (MemberCore member) + { + Console.WriteLine ("Unknown member:"); + Console.WriteLine (member.GetType () + "-> Member {0}", member.GetSignatureForError ()); + } + + Stack typeStack = new Stack (); + + public override void Visit (Class c) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Class; + AddAttributeSection (newType, c); + + var location = LocationsBag.GetMemberLocation (c); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "class".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (c.MemberName.Name, Convert (c.MemberName.Location)), AstNode.Roles.Identifier); + if (c.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (c.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, c.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newType, c); + } + if (c.TypeBaseExpressions != null) { + foreach (var baseTypes in c.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (c); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Struct s) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Struct; + AddAttributeSection (newType, s); + var location = LocationsBag.GetMemberLocation (s); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "struct".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (s.MemberName.Name, Convert (s.MemberName.Location)), AstNode.Roles.Identifier); + if (s.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (s.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, s.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newType, s); + } + + if (s.TypeBaseExpressions != null) { + foreach (var baseTypes in s.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (s); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Interface i) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Interface; + AddAttributeSection (newType, i); + var location = LocationsBag.GetMemberLocation (i); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "interface".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (i.MemberName.Name, Convert (i.MemberName.Location)), AstNode.Roles.Identifier); + if (i.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (i.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, i.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); + AddConstraints (newType, i); + } + if (i.TypeBaseExpressions != null) { + foreach (var baseTypes in i.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (i); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Mono.CSharp.Delegate d) + { + DelegateDeclaration newDelegate = new DelegateDeclaration (); + var location = LocationsBag.GetMemberLocation (d); + AddAttributeSection (newDelegate, d); + AddModifiers (newDelegate, location); + if (location != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), TypeDeclaration.Roles.Keyword); + newDelegate.AddChild (ConvertToType (d.ReturnType), AstNode.Roles.Type); + newDelegate.AddChild (Identifier.Create (d.MemberName.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); + if (d.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (d.MemberName); + if (typeArgLocation != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newDelegate, typeArgLocation, d.MemberName.TypeArguments); + if (typeArgLocation != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newDelegate, d); + } + if (location != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DelegateDeclaration.Roles.LPar); + AddParameter (newDelegate, d.Parameters); + + if (location != null) { + newDelegate.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DelegateDeclaration.Roles.RPar); + newDelegate.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DelegateDeclaration.Roles.Semicolon); + } + AddType (newDelegate); + } + + void AddType (AttributedNode child) + { + if (typeStack.Count > 0) { + typeStack.Peek ().AddChild (child, TypeDeclaration.MemberRole); + } else { + AddToNamespace (child); + } + } + + void AddToNamespace (AstNode child) + { + if (namespaceStack.Count > 0) { + namespaceStack.Peek ().AddChild (child, NamespaceDeclaration.MemberRole); + } else { + unit.AddChild (child, CompilationUnit.MemberRole); + } + } + + public override void Visit (Mono.CSharp.Enum e) + { + TypeDeclaration newType = new TypeDeclaration (); + AddAttributeSection (newType, e); + newType.ClassType = ClassType.Enum; + var location = LocationsBag.GetMemberLocation (e); + + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location [0]), "enum".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), AstNode.Roles.Identifier); + + if (e.BaseTypeExpression != null) + newType.AddChild (ConvertToType (e.BaseTypeExpression), TypeDeclaration.BaseTypeRole); + + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (e); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (EnumMember em) + { + EnumMemberDeclaration newField = new EnumMemberDeclaration (); + AddAttributeSection (newField, em); + newField.AddChild (Identifier.Create (em.Name, Convert (em.Location)), AstNode.Roles.Identifier); + + if (em.Initializer != null) { + newField.AddChild ((Expression)em.Initializer.Accept (this), EnumMemberDeclaration.InitializerRole); + } + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + } + #endregion + + #region Type members + + + public override void Visit (FixedField f) + { + var location = LocationsBag.GetMemberLocation (f); + + var newField = new FixedFieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location [0]), "fixed".Length), FixedFieldDeclaration.Roles.Keyword); + newField.AddChild (ConvertToType (f.TypeName), FixedFieldDeclaration.Roles.Type); + + var variable = new FixedVariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), FixedFieldDeclaration.Roles.Identifier); + if (!f.Initializer.IsNull) { + var bracketLocations = LocationsBag.GetLocations (f.Initializer); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.LBracket); + + variable.AddChild ((Expression)f.Initializer.Accept (this), FieldDeclaration.Roles.Expression); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.RBracket); + } + newField.AddChild (variable, FixedFieldDeclaration.VariableRole); + + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc [0]), 1), FieldDeclaration.Roles.Comma); + + variable = new FixedVariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), FieldDeclaration.Roles.Identifier); + if (!decl.Initializer.IsNull) { + var bracketLocations = LocationsBag.GetLocations (f.Initializer); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.LBracket); + variable.AddChild ((Expression)decl.Initializer.Accept (this), FieldDeclaration.Roles.Expression); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.RBracket); + } + newField.AddChild (variable, FixedFieldDeclaration.VariableRole); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FieldDeclaration.Roles.Semicolon); + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + + } + + public override void Visit (Field f) + { + var location = LocationsBag.GetMemberLocation (f); + + FieldDeclaration newField = new FieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + newField.AddChild (ConvertToType (f.TypeName), FieldDeclaration.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), FieldDeclaration.Roles.Identifier); + + if (f.Initializer != null) { + if (location != null) + variable.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)f.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), FieldDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + } + + public override void Visit (Const f) + { + var location = LocationsBag.GetMemberLocation (f); + + FieldDeclaration newField = new FieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + if (location != null) + newField.AddChild (new CSharpModifierToken (Convert (location [0]), Modifiers.Const), AttributedNode.ModifierRole); + newField.AddChild (ConvertToType (f.TypeName), FieldDeclaration.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), VariableInitializer.Roles.Identifier); + + if (f.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (f.Initializer.Location), 1), VariableInitializer.Roles.Assign); + variable.AddChild ((Expression)f.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), FieldDeclaration.Roles.Identifier); + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FieldDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + + + } + + public override void Visit (Operator o) + { + OperatorDeclaration newOperator = new OperatorDeclaration (); + newOperator.OperatorType = (OperatorType)o.OperatorType; + + var location = LocationsBag.GetMemberLocation (o); + AddAttributeSection (newOperator, o); + AddModifiers (newOperator, location); + + newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); + + if (o.OperatorType == Operator.OpType.Implicit) { + if (location != null) { + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "implicit".Length), OperatorDeclaration.OperatorTypeRole); + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + } + } else if (o.OperatorType == Operator.OpType.Explicit) { + if (location != null) { + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "explicit".Length), OperatorDeclaration.OperatorTypeRole); + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + } + } else { + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + + int opLength = OperatorDeclaration.GetToken(newOperator.OperatorType).Length; + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), opLength), OperatorDeclaration.OperatorTypeRole); + } + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[2]), 1), OperatorDeclaration.Roles.LPar); + AddParameter (newOperator, o.ParameterInfo); + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[3]), 1), OperatorDeclaration.Roles.RPar); + + if (o.Block != null) + newOperator.AddChild ((BlockStatement)o.Block.Accept (this), OperatorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newOperator, TypeDeclaration.MemberRole); + } + + public void AddAttributeSection (AstNode parent, Attributable a) + { + if (a.OptAttributes == null) + return; + foreach (var attr in a.OptAttributes.Sections) { + parent.AddChild (ConvertAttributeSection (attr), AttributedNode.AttributeRole); + } + } + + public override void Visit (Indexer indexer) + { + IndexerDeclaration newIndexer = new IndexerDeclaration (); + AddAttributeSection (newIndexer, indexer); + var location = LocationsBag.GetMemberLocation (indexer); + AddModifiers (newIndexer, location); + + if (indexer.MemberName.Left != null) + newIndexer.AddChild (ConvertToType (indexer.MemberName.Left), IndexerDeclaration.PrivateImplementationTypeRole); + newIndexer.AddChild (ConvertToType (indexer.TypeName), IndexerDeclaration.Roles.Type); + + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IndexerDeclaration.Roles.LBracket); + AddParameter (newIndexer, indexer.ParameterInfo); + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IndexerDeclaration.Roles.RBracket); + + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[2]), 1), IndexerDeclaration.Roles.LBrace); + if (indexer.Get != null) { + Accessor getAccessor = new Accessor (); + var getLocation = LocationsBag.GetMemberLocation (indexer.Get); + AddAttributeSection (getAccessor, indexer.Get); + AddModifiers (getAccessor, getLocation); + if (getLocation != null) + getAccessor.AddChild (new CSharpTokenNode (Convert (indexer.Get.Location), "get".Length), PropertyDeclaration.Roles.Keyword); + if (indexer.Get.Block != null) { + getAccessor.AddChild ((BlockStatement)indexer.Get.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (getLocation != null && getLocation.Count > 0) + newIndexer.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newIndexer.AddChild (getAccessor, PropertyDeclaration.GetterRole); + } + + if (indexer.Set != null) { + Accessor setAccessor = new Accessor (); + var setLocation = LocationsBag.GetMemberLocation (indexer.Set); + AddAttributeSection (setAccessor, indexer.Set); + AddModifiers (setAccessor, setLocation); + if (setLocation != null) + setAccessor.AddChild (new CSharpTokenNode (Convert (indexer.Set.Location), "set".Length), PropertyDeclaration.Roles.Keyword); + + if (indexer.Set.Block != null) { + setAccessor.AddChild ((BlockStatement)indexer.Set.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (setLocation != null && setLocation.Count > 0) + newIndexer.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newIndexer.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } + + if (location != null) { + newIndexer.AddChild (new CSharpTokenNode (Convert (location[3]), 1), IndexerDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newIndexer.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Peek ().AddChild (newIndexer, TypeDeclaration.MemberRole); + } + + public override void Visit (Method m) + { + MethodDeclaration newMethod = new MethodDeclaration (); + AddAttributeSection (newMethod, m); + var location = LocationsBag.GetMemberLocation (m); + AddModifiers (newMethod, location); + + newMethod.AddChild (ConvertToType (m.TypeName), AstNode.Roles.Type); + if (m.MethodName.Left != null) + newMethod.AddChild (ConvertToType (m.MethodName.Left), MethodDeclaration.PrivateImplementationTypeRole); + + newMethod.AddChild (Identifier.Create (m.MethodName.Name, Convert (m.Location)), AstNode.Roles.Identifier); + + if (m.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (m.MemberName); + if (typeArgLocation != null) + newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeParameters (newMethod, typeArgLocation, m.MemberName.TypeArguments); + if (typeArgLocation != null) + newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); + AddConstraints (newMethod, m.GenericMethod); + } + + if (location != null) + newMethod.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LPar); + AddParameter (newMethod, m.ParameterInfo); + + if (location != null) + newMethod.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RPar); + if (m.Block != null) { + var bodyBlock = (BlockStatement)m.Block.Accept (this); +// if (m.Block is ToplevelBlock) { +// newMethod.AddChild (bodyBlock.FirstChild.NextSibling, MethodDeclaration.Roles.Body); +// } else { + newMethod.AddChild (bodyBlock, MethodDeclaration.Roles.Body); +// } + } else if (location != null && location.Count < 3) { + // parser error, set end node to max value. + newMethod.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Peek ().AddChild (newMethod, TypeDeclaration.MemberRole); + } + + static Dictionary modifierTable = new Dictionary (); + static string[] keywordTable; + + static ConversionVisitor () + { + modifierTable [Mono.CSharp.Modifiers.NEW] = ICSharpCode.NRefactory.CSharp.Modifiers.New; + modifierTable [Mono.CSharp.Modifiers.PUBLIC] = ICSharpCode.NRefactory.CSharp.Modifiers.Public; + modifierTable [Mono.CSharp.Modifiers.PROTECTED] = ICSharpCode.NRefactory.CSharp.Modifiers.Protected; + modifierTable [Mono.CSharp.Modifiers.PRIVATE] = ICSharpCode.NRefactory.CSharp.Modifiers.Private; + modifierTable [Mono.CSharp.Modifiers.INTERNAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Internal; + modifierTable [Mono.CSharp.Modifiers.ABSTRACT] = ICSharpCode.NRefactory.CSharp.Modifiers.Abstract; + modifierTable [Mono.CSharp.Modifiers.VIRTUAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Virtual; + modifierTable [Mono.CSharp.Modifiers.SEALED] = ICSharpCode.NRefactory.CSharp.Modifiers.Sealed; + modifierTable [Mono.CSharp.Modifiers.STATIC] = ICSharpCode.NRefactory.CSharp.Modifiers.Static; + modifierTable [Mono.CSharp.Modifiers.OVERRIDE] = ICSharpCode.NRefactory.CSharp.Modifiers.Override; + modifierTable [Mono.CSharp.Modifiers.READONLY] = ICSharpCode.NRefactory.CSharp.Modifiers.Readonly; + modifierTable [Mono.CSharp.Modifiers.PARTIAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Partial; + modifierTable [Mono.CSharp.Modifiers.EXTERN] = ICSharpCode.NRefactory.CSharp.Modifiers.Extern; + modifierTable [Mono.CSharp.Modifiers.VOLATILE] = ICSharpCode.NRefactory.CSharp.Modifiers.Volatile; + modifierTable [Mono.CSharp.Modifiers.UNSAFE] = ICSharpCode.NRefactory.CSharp.Modifiers.Unsafe; + + keywordTable = new string[255]; + for (int i = 0; i< keywordTable.Length; i++) + keywordTable [i] = "unknown"; + + keywordTable [(int)BuiltinTypeSpec.Type.Other] = "void"; + keywordTable [(int)BuiltinTypeSpec.Type.String] = "string"; + keywordTable [(int)BuiltinTypeSpec.Type.Int] = "int"; + keywordTable [(int)BuiltinTypeSpec.Type.Object] = "object"; + keywordTable [(int)BuiltinTypeSpec.Type.Float] = "float"; + keywordTable [(int)BuiltinTypeSpec.Type.Double] = "double"; + keywordTable [(int)BuiltinTypeSpec.Type.Long] = "long"; + keywordTable [(int)BuiltinTypeSpec.Type.Byte] = "byte"; + keywordTable [(int)BuiltinTypeSpec.Type.UInt] = "uint"; + keywordTable [(int)BuiltinTypeSpec.Type.ULong] = "ulong"; + keywordTable [(int)BuiltinTypeSpec.Type.Short] = "short"; + keywordTable [(int)BuiltinTypeSpec.Type.UShort] = "ushort"; + keywordTable [(int)BuiltinTypeSpec.Type.SByte] = "sbyte"; + keywordTable [(int)BuiltinTypeSpec.Type.Decimal] = "decimal"; + keywordTable [(int)BuiltinTypeSpec.Type.Char] = "char"; + } + + void AddModifiers (AttributedNode parent, LocationsBag.MemberLocations location) + { + if (location == null || location.Modifiers == null) + return; + foreach (var modifier in location.Modifiers) { + parent.AddChild (new CSharpModifierToken (Convert (modifier.Item2), modifierTable[modifier.Item1]), AttributedNode.ModifierRole); + } + } + + public override void Visit (Property p) + { + PropertyDeclaration newProperty = new PropertyDeclaration (); + AddAttributeSection (newProperty, p); + var location = LocationsBag.GetMemberLocation (p); + AddModifiers (newProperty, location); + newProperty.AddChild (ConvertToType (p.TypeName), AstNode.Roles.Type); + if (p.MemberName.Left != null) + newProperty.AddChild (ConvertToType (p.MemberName.Left), PropertyDeclaration.PrivateImplementationTypeRole); + + newProperty.AddChild (Identifier.Create (p.MemberName.Name, Convert (p.Location)), PropertyDeclaration.Roles.Identifier); + + if (location != null) + newProperty.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LBrace); + + if (p.Get != null) { + Accessor getAccessor = new Accessor (); + AddAttributeSection (getAccessor, p.Get); + var getLocation = LocationsBag.GetMemberLocation (p.Get); + AddModifiers (getAccessor, getLocation); + getAccessor.AddChild (new CSharpTokenNode (Convert (p.Get.Location), "get".Length), PropertyDeclaration.Roles.Keyword); + + if (p.Get.Block != null) { + getAccessor.AddChild ((BlockStatement)p.Get.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (getLocation != null && getLocation.Count > 0) + newProperty.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); + } + + if (p.Set != null) { + Accessor setAccessor = new Accessor (); + AddAttributeSection (setAccessor, p.Set); + var setLocation = LocationsBag.GetMemberLocation (p.Set); + AddModifiers (setAccessor, setLocation); + setAccessor.AddChild (new CSharpTokenNode (Convert (p.Set.Location), "set".Length), PropertyDeclaration.Roles.Keyword); + + if (p.Set.Block != null) { + setAccessor.AddChild ((BlockStatement)p.Set.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (setLocation != null && setLocation.Count > 0) + newProperty.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } + if (location != null && location.Count > 1) { + newProperty.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newProperty.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + typeStack.Peek ().AddChild (newProperty, TypeDeclaration.MemberRole); + } + + public override void Visit (Constructor c) + { + ConstructorDeclaration newConstructor = new ConstructorDeclaration (); + AddAttributeSection (newConstructor, c); + var location = LocationsBag.GetMemberLocation (c); + AddModifiers (newConstructor, location); + newConstructor.AddChild (Identifier.Create (c.MemberName.Name, Convert (c.MemberName.Location)), AstNode.Roles.Identifier); + if (location != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LPar); + + AddParameter (newConstructor, c.ParameterInfo); + if (location != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RPar); + + if (c.Initializer != null) { + var initializer = new ConstructorInitializer (); + initializer.ConstructorInitializerType = c.Initializer is ConstructorBaseInitializer ? ConstructorInitializerType.Base : ConstructorInitializerType.This; + var initializerLocation = LocationsBag.GetLocations (c.Initializer); + + if (initializerLocation != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.Colon); + if (initializerLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.LPar); + AddArguments (initializer, LocationsBag.GetLocations (c.Initializer.Arguments), c.Initializer.Arguments); + if (initializerLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.RPar); + newConstructor.AddChild (initializer, ConstructorDeclaration.InitializerRole); + } + + if (c.Block != null) + newConstructor.AddChild ((BlockStatement)c.Block.Accept (this), ConstructorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newConstructor, TypeDeclaration.MemberRole); + } + + public override void Visit (Destructor d) + { + DestructorDeclaration newDestructor = new DestructorDeclaration (); + AddAttributeSection (newDestructor, d); + var location = LocationsBag.GetMemberLocation (d); + AddModifiers (newDestructor, location); + if (location != null) + newDestructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), DestructorDeclaration.TildeRole); + newDestructor.AddChild (Identifier.Create (d.MemberName.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); + + if (location != null) { + newDestructor.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DestructorDeclaration.Roles.LPar); + newDestructor.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DestructorDeclaration.Roles.RPar); + } + + if (d.Block != null) + newDestructor.AddChild ((BlockStatement)d.Block.Accept (this), DestructorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newDestructor, TypeDeclaration.MemberRole); + } + + public override void Visit (EventField e) + { + EventDeclaration newEvent = new EventDeclaration (); + AddAttributeSection (newEvent, e); + var location = LocationsBag.GetMemberLocation (e); + AddModifiers (newEvent, location); + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), EventDeclaration.Roles.Keyword); + newEvent.AddChild (ConvertToType (e.TypeName), AstNode.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), FieldDeclaration.Roles.Identifier); + + if (e.Initializer != null) { + if (location != null) + variable.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)e.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newEvent.AddChild (variable, FieldDeclaration.Roles.Variable); + if (e.Declarators != null) { + foreach (var decl in e.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newEvent.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); + + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newEvent.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), EventDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole); + } + + public override void Visit (EventProperty ep) + { + CustomEventDeclaration newEvent = new CustomEventDeclaration (); + AddAttributeSection (newEvent, ep); + var location = LocationsBag.GetMemberLocation (ep); + AddModifiers (newEvent, location); + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), CustomEventDeclaration.Roles.Keyword); + newEvent.AddChild (ConvertToType (ep.TypeName), CustomEventDeclaration.Roles.Type); + if (ep.MemberName.Left != null) + newEvent.AddChild (ConvertToType (ep.MemberName.Left), CustomEventDeclaration.PrivateImplementationTypeRole); + + newEvent.AddChild (Identifier.Create (ep.MemberName.Name, Convert (ep.Location)), CustomEventDeclaration.Roles.Identifier); + + if (location != null && location.Count >= 2) + newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CustomEventDeclaration.Roles.LBrace); + + if (ep.Add != null) { + Accessor addAccessor = new Accessor (); + AddAttributeSection (addAccessor, ep.Add); + var addLocation = LocationsBag.GetMemberLocation (ep.Add); + AddModifiers (addAccessor, addLocation); + addAccessor.AddChild (new CSharpTokenNode (Convert (ep.Add.Location), "add".Length), CustomEventDeclaration.Roles.Keyword); + if (ep.Add.Block != null) + addAccessor.AddChild ((BlockStatement)ep.Add.Block.Accept (this), CustomEventDeclaration.Roles.Body); + newEvent.AddChild (addAccessor, CustomEventDeclaration.AddAccessorRole); + } + + if (ep.Remove != null) { + Accessor removeAccessor = new Accessor (); + AddAttributeSection (removeAccessor, ep.Remove); + var removeLocation = LocationsBag.GetMemberLocation (ep.Remove); + AddModifiers (removeAccessor, removeLocation); + removeAccessor.AddChild (new CSharpTokenNode (Convert (ep.Remove.Location), "remove".Length), CustomEventDeclaration.Roles.Keyword); + + if (ep.Remove.Block != null) + removeAccessor.AddChild ((BlockStatement)ep.Remove.Block.Accept (this), CustomEventDeclaration.Roles.Body); + newEvent.AddChild (removeAccessor, CustomEventDeclaration.RemoveAccessorRole); + } + if (location != null && location.Count >= 3) { + newEvent.AddChild (new CSharpTokenNode (Convert (location[2]), 1), CustomEventDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newEvent.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole); + } + + #endregion + + #region Statements + public override object Visit (Mono.CSharp.Statement stmt) + { + Console.WriteLine ("unknown statement:" + stmt); + return null; + } + + public override object Visit (BlockVariableDeclaration blockVariableDeclaration) + { + var result = new VariableDeclarationStatement (); + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), VariableDeclarationStatement.Roles.Type); + + var varInit = new VariableInitializer (); + var location = LocationsBag.GetLocations (blockVariableDeclaration); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (location != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[0]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, VariableDeclarationStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), VariableInitializer.Roles.Comma); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } else { + } + result.AddChild (init, VariableDeclarationStatement.Roles.Variable); + } + } + if (location != null && (blockVariableDeclaration.Initializer == null || location.Count > 1)) + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), VariableDeclarationStatement.Roles.Semicolon); + return result; + } + + public override object Visit (BlockConstantDeclaration blockVariableDeclaration) + { + var result = new VariableDeclarationStatement (); + + var location = LocationsBag.GetLocations (blockVariableDeclaration); + if (location != null) + result.AddChild (new CSharpModifierToken (Convert (location [0]), ICSharpCode.NRefactory.CSharp.Modifiers.Const), VariableDeclarationStatement.ModifierRole); + + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), VariableDeclarationStatement.Roles.Type); + + var varInit = new VariableInitializer (); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (location != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[1]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, VariableDeclarationStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null) + init.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc[1]), 1), VariableInitializer.Roles.Comma); + } else { + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), VariableInitializer.Roles.Comma); + } + result.AddChild (init, VariableDeclarationStatement.Roles.Variable); + } + } + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), VariableDeclarationStatement.Roles.Semicolon); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + return result; + } + + public override object Visit (Mono.CSharp.EmptyStatement emptyStatement) + { + var result = new EmptyStatement (); + result.Location = Convert (emptyStatement.loc); + return result; + } + + public override object Visit (EmptyExpressionStatement emptyExpressionStatement) + { + return new EmptyExpression (Convert (emptyExpressionStatement.Location)); + } + + public override object Visit (If ifStatement) + { + var result = new IfElseStatement (); + + var location = LocationsBag.GetLocations (ifStatement); + + result.AddChild (new CSharpTokenNode (Convert (ifStatement.loc), "if".Length), IfElseStatement.IfKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IfElseStatement.Roles.LPar); + result.AddChild ((Expression)ifStatement.Expr.Accept (this), IfElseStatement.Roles.Condition); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IfElseStatement.Roles.RPar); + + if (ifStatement.TrueStatement != null) + result.AddChild ((Statement)ifStatement.TrueStatement.Accept (this), IfElseStatement.TrueRole); + + if (ifStatement.FalseStatement != null) { + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "else".Length), IfElseStatement.ElseKeywordRole); + result.AddChild ((Statement)ifStatement.FalseStatement.Accept (this), IfElseStatement.FalseRole); + } + + return result; + } + + public override object Visit (Do doStatement) + { + var result = new DoWhileStatement (); + var location = LocationsBag.GetLocations (doStatement); + result.AddChild (new CSharpTokenNode (Convert (doStatement.loc), "do".Length), DoWhileStatement.DoKeywordRole); + result.AddChild ((Statement)doStatement.EmbeddedStatement.Accept (this), WhileStatement.Roles.EmbeddedStatement); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "while".Length), DoWhileStatement.WhileKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DoWhileStatement.Roles.LPar); + result.AddChild ((Expression)doStatement.expr.Accept (this), DoWhileStatement.Roles.Condition); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DoWhileStatement.Roles.RPar); + result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DoWhileStatement.Roles.Semicolon); + } + + return result; + } + + public override object Visit (While whileStatement) + { + var result = new WhileStatement (); + var location = LocationsBag.GetLocations (whileStatement); + result.AddChild (new CSharpTokenNode (Convert (whileStatement.loc), "while".Length), WhileStatement.WhileKeywordRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), WhileStatement.Roles.LPar); + if (whileStatement.expr != null) + result.AddChild ((Expression)whileStatement.expr.Accept (this), WhileStatement.Roles.Condition); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), WhileStatement.Roles.RPar); + if (whileStatement.Statement != null) + result.AddChild ((Statement)whileStatement.Statement.Accept (this), WhileStatement.Roles.EmbeddedStatement); + return result; + } + + void AddStatementOrList (ForStatement forStatement, Mono.CSharp.Statement init, Role role) + { + if (init == null) + return; + if (init is StatementList) { + foreach (var stmt in ((StatementList)init).Statements) { + forStatement.AddChild ((Statement)stmt.Accept (this), role); + } + } else if (init is Mono.CSharp.EmptyStatement) { + + } else { + forStatement.AddChild ((Statement)init.Accept (this), role); + } + } + + public override object Visit (For forStatement) + { + var result = new ForStatement (); + + var location = LocationsBag.GetLocations (forStatement); + + result.AddChild (new CSharpTokenNode (Convert (forStatement.loc), "for".Length), ForStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), ForStatement.Roles.LPar); + + AddStatementOrList (result, forStatement.InitStatement, ForStatement.InitializerRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ForStatement.Roles.Semicolon); + if (forStatement.Test != null) + result.AddChild ((Expression)forStatement.Test.Accept (this), ForStatement.Roles.Condition); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForStatement.Roles.Semicolon); + + AddStatementOrList (result, forStatement.Increment, ForStatement.IteratorRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [3]), 1), ForStatement.Roles.RPar); + + if (forStatement.Statement != null) + result.AddChild ((Statement)forStatement.Statement.Accept (this), ForStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (StatementExpression statementExpression) + { + var result = new ExpressionStatement (); + object expr = statementExpression.Expr.Accept (this); + if (expr != null) + result.AddChild ((Expression)expr, ExpressionStatement.Roles.Expression); + var location = LocationsBag.GetLocations (statementExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ExpressionStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Return returnStatement) + { + var result = new ReturnStatement (); + + result.AddChild (new CSharpTokenNode (Convert (returnStatement.loc), "return".Length), ReturnStatement.Roles.Keyword); + if (returnStatement.Expr != null) + result.AddChild ((Expression)returnStatement.Expr.Accept (this), ReturnStatement.Roles.Expression); + + var location = LocationsBag.GetLocations (returnStatement); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ReturnStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (Goto gotoStatement) + { + var result = new GotoStatement (); + var location = LocationsBag.GetLocations (gotoStatement); + result.AddChild (new CSharpTokenNode (Convert (gotoStatement.loc), "goto".Length), GotoStatement.Roles.Keyword); + result.AddChild (Identifier.Create (gotoStatement.Target, Convert (gotoStatement.loc)), GotoStatement.Roles.Identifier); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), GotoStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (LabeledStatement labeledStatement) + { + var result = new LabelStatement (); + result.AddChild (Identifier.Create (labeledStatement.Name, Convert (labeledStatement.loc)), LabelStatement.Roles.Identifier); + return result; + } + + public override object Visit (GotoDefault gotoDefault) + { + var result = new GotoDefaultStatement (); + result.AddChild (new CSharpTokenNode (Convert (gotoDefault.loc), "goto".Length), GotoDefaultStatement.Roles.Keyword); + var location = LocationsBag.GetLocations (gotoDefault); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "default".Length), GotoDefaultStatement.DefaultKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), GotoDefaultStatement.Roles.Semicolon); + } + + return result; + } + + public override object Visit (GotoCase gotoCase) + { + var result = new GotoCaseStatement (); + result.AddChild (new CSharpTokenNode (Convert (gotoCase.loc), "goto".Length), GotoCaseStatement.Roles.Keyword); + + var location = LocationsBag.GetLocations (gotoCase); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "case".Length), GotoCaseStatement.CaseKeywordRole); + result.AddChild ((Expression)gotoCase.Expr.Accept (this), GotoCaseStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), GotoCaseStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Throw throwStatement) + { + var result = new ThrowStatement (); + var location = LocationsBag.GetLocations (throwStatement); + + result.AddChild (new CSharpTokenNode (Convert (throwStatement.loc), "throw".Length), ThrowStatement.Roles.Keyword); + if (throwStatement.Expr != null) + result.AddChild ((Expression)throwStatement.Expr.Accept (this), ThrowStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ThrowStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Break breakStatement) + { + var result = new BreakStatement (); + var location = LocationsBag.GetLocations (breakStatement); + + result.AddChild (new CSharpTokenNode (Convert (breakStatement.loc), "break".Length), BreakStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), BreakStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Continue continueStatement) + { + var result = new ContinueStatement (); + var location = LocationsBag.GetLocations (continueStatement); + result.AddChild (new CSharpTokenNode (Convert (continueStatement.loc), "continue".Length), ContinueStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ContinueStatement.Roles.Semicolon); + return result; + } + + public static bool IsLower (Location left, Location right) + { + return left.Row < right.Row || left.Row == right.Row && left.Column < right.Column; + } + + public UsingStatement CreateUsingStatement (Block blockStatement) + { + var usingResult = new UsingStatement (); + Mono.CSharp.Statement cur = blockStatement.Statements[0]; + if (cur is Using) { + Using u = (Using)cur; + usingResult.AddChild (new CSharpTokenNode (Convert (u.loc), "using".Length), UsingStatement.Roles.Keyword); + usingResult.AddChild (new CSharpTokenNode (Convert (blockStatement.StartLocation), 1), UsingStatement.Roles.LPar); + if (u.Variables != null) { + var initializer = new VariableInitializer () { + NameToken = Identifier.Create (u.Variables.Variable.Name, Convert (u.Variables.Variable.Location)), + }; + + var loc = LocationsBag.GetLocations (u.Variables); + if (loc != null) + initializer.AddChild (new CSharpTokenNode (Convert (loc[1]), 1), VariableInitializer.Roles.Assign); + if (u.Variables.Initializer != null) + initializer.Initializer = u.Variables.Initializer.Accept (this) as Expression; + + var varDec = new VariableDeclarationStatement () { + Type = ConvertToType (u.Variables.TypeExpression), + Variables = { initializer } + }; + usingResult.AddChild (varDec, UsingStatement.ResourceAcquisitionRole); + } + cur = u.Statement; + usingResult.AddChild (new CSharpTokenNode (Convert (blockStatement.EndLocation), 1), UsingStatement.Roles.RPar); + usingResult.AddChild ((Statement)cur.Accept (this), UsingStatement.Roles.EmbeddedStatement); + } + return usingResult; + } + + void AddBlockChildren (BlockStatement result, Block blockStatement, ref int curLocal) + { + if (convertTypeSystemMode) { + return; + } + foreach (Mono.CSharp.Statement stmt in blockStatement.Statements) { + if (stmt == null) + continue; + /* if (curLocal < localVariables.Count && IsLower (localVariables[curLocal].Location, stmt.loc)) { + result.AddChild (CreateVariableDeclaration (localVariables[curLocal]), AstNode.Roles.Statement); + curLocal++; + }*/ + if (stmt is Block && !(stmt is ToplevelBlock || stmt is ExplicitBlock)) { + AddBlockChildren (result, (Block)stmt, ref curLocal); + } else { + result.AddChild ((Statement)stmt.Accept (this), BlockStatement.StatementRole); + } + } + } + + public override object Visit (Block blockStatement) + { + if (blockStatement.IsCompilerGenerated && blockStatement.Statements.Any ()) { + if (blockStatement.Statements.First () is Using) + return CreateUsingStatement (blockStatement); + return blockStatement.Statements.Last ().Accept (this); + } + var result = new BlockStatement (); + result.AddChild (new CSharpTokenNode (Convert (blockStatement.StartLocation), 1), AstNode.Roles.LBrace); + int curLocal = 0; + AddBlockChildren (result, blockStatement, ref curLocal); + + result.AddChild (new CSharpTokenNode (Convert (blockStatement.EndLocation), 1), AstNode.Roles.RBrace); + return result; + } + + public override object Visit (Switch switchStatement) + { + var result = new SwitchStatement (); + + var location = LocationsBag.GetLocations (switchStatement); + result.AddChild (new CSharpTokenNode (Convert (switchStatement.loc), "switch".Length), SwitchStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), SwitchStatement.Roles.LPar); + if (switchStatement.Expr != null) + result.AddChild ((Expression)switchStatement.Expr.Accept (this), SwitchStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), SwitchStatement.Roles.RPar); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), SwitchStatement.Roles.LBrace); + foreach (var section in switchStatement.Sections) { + var newSection = new SwitchSection (); + foreach (var caseLabel in section.Labels) { + var newLabel = new CaseLabel (); + newLabel.AddChild (new CSharpTokenNode (Convert (caseLabel.Location), "case".Length), SwitchStatement.Roles.Keyword); + if (caseLabel.Label != null) + newLabel.AddChild ((Expression)caseLabel.Label.Accept (this), SwitchStatement.Roles.Expression); + + newSection.AddChild (newLabel, SwitchSection.CaseLabelRole); + } + + var blockStatement = section.Block; + var bodyBlock = new BlockStatement (); + int curLocal = 0; + AddBlockChildren (bodyBlock, blockStatement, ref curLocal); + foreach (var statement in bodyBlock.Statements) { + statement.Remove (); + newSection.AddChild (statement, SwitchSection.Roles.EmbeddedStatement); + + } + result.AddChild (newSection, SwitchStatement.SwitchSectionRole); + } + + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), SwitchStatement.Roles.RBrace); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + return result; + } + + public override object Visit (Lock lockStatement) + { + var result = new LockStatement (); + var location = LocationsBag.GetLocations (lockStatement); + result.AddChild (new CSharpTokenNode (Convert (lockStatement.loc), "lock".Length), LockStatement.Roles.Keyword); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), LockStatement.Roles.LPar); + result.AddChild ((Expression)lockStatement.Expr.Accept (this), LockStatement.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), LockStatement.Roles.RPar); + result.AddChild ((Statement)lockStatement.Statement.Accept (this), LockStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (Unchecked uncheckedStatement) + { + var result = new UncheckedStatement (); + result.AddChild (new CSharpTokenNode (Convert (uncheckedStatement.loc), "unchecked".Length), UncheckedStatement.Roles.Keyword); + result.AddChild ((BlockStatement)uncheckedStatement.Block.Accept (this), UncheckedStatement.Roles.Body); + return result; + } + + + public override object Visit (Checked checkedStatement) + { + var result = new CheckedStatement (); + result.AddChild (new CSharpTokenNode (Convert (checkedStatement.loc), "checked".Length), CheckedStatement.Roles.Keyword); + result.AddChild ((BlockStatement)checkedStatement.Block.Accept (this), CheckedStatement.Roles.Body); + return result; + } + + public override object Visit (Unsafe unsafeStatement) + { + var result = new UnsafeStatement (); + result.AddChild (new CSharpTokenNode (Convert (unsafeStatement.loc), "unsafe".Length), UnsafeStatement.Roles.Keyword); + result.AddChild ((BlockStatement)unsafeStatement.Block.Accept (this), UnsafeStatement.Roles.Body); + return result; + } + + public override object Visit (Fixed fixedStatement) + { + var result = new FixedStatement (); + var location = LocationsBag.GetLocations (fixedStatement); + + result.AddChild (new CSharpTokenNode (Convert (fixedStatement.loc), "fixed".Length), FixedStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FixedStatement.Roles.LPar); + + if (fixedStatement.Variables != null) { + var blockVariableDeclaration = fixedStatement.Variables; + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), FixedStatement.Roles.Type); + var varInit = new VariableInitializer (); + var initLocation = LocationsBag.GetLocations (blockVariableDeclaration); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (initLocation != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[0]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, FixedStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), VariableInitializer.Roles.Comma); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } else { + } + result.AddChild (init, FixedStatement.Roles.Variable); + } + } + } + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FixedStatement.Roles.RPar); + result.AddChild ((Statement)fixedStatement.Statement.Accept (this), FixedStatement.Roles.EmbeddedStatement); + return result; + } + + public override object Visit (TryFinally tryFinallyStatement) + { + TryCatchStatement result; + var location = LocationsBag.GetLocations (tryFinallyStatement); + + if (tryFinallyStatement.Stmt is TryCatch) { + result = (TryCatchStatement)tryFinallyStatement.Stmt.Accept (this); + } else { + result = new TryCatchStatement (); + result.AddChild (new CSharpTokenNode (Convert (tryFinallyStatement.loc), "try".Length), TryCatchStatement.TryKeywordRole); + if (tryFinallyStatement.Stmt != null) + result.AddChild ((BlockStatement)tryFinallyStatement.Stmt.Accept (this), TryCatchStatement.TryBlockRole); + } + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "finally".Length), TryCatchStatement.FinallyKeywordRole); + result.AddChild ((BlockStatement)tryFinallyStatement.Fini.Accept (this), TryCatchStatement.FinallyBlockRole); + + return result; + } + + CatchClause ConvertCatch (Catch ctch) + { + CatchClause result = new CatchClause (); + var location = LocationsBag.GetLocations (ctch); + result.AddChild (new CSharpTokenNode (Convert (ctch.loc), "catch".Length), CatchClause.Roles.Keyword); + if (ctch.TypeExpression != null) { + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CatchClause.Roles.LPar); + + result.AddChild (ConvertToType (ctch.TypeExpression), CatchClause.Roles.Type); + if (ctch.Variable != null && !string.IsNullOrEmpty (ctch.Variable.Name)) + result.AddChild (Identifier.Create (ctch.Variable.Name, Convert (ctch.Variable.Location)), CatchClause.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CatchClause.Roles.RPar); + } + + if (ctch.Block != null) + result.AddChild ((BlockStatement)ctch.Block.Accept (this), CatchClause.Roles.Body); + + return result; + } + + public override object Visit (TryCatch tryCatchStatement) + { + var result = new TryCatchStatement (); + result.AddChild (new CSharpTokenNode (Convert (tryCatchStatement.loc), "try".Length), TryCatchStatement.TryKeywordRole); + if (tryCatchStatement.Block != null) + result.AddChild ((BlockStatement)tryCatchStatement.Block.Accept (this), TryCatchStatement.TryBlockRole); + foreach (Catch ctch in tryCatchStatement.Specific) { + result.AddChild (ConvertCatch (ctch), TryCatchStatement.CatchClauseRole); + } + if (tryCatchStatement.General != null) + result.AddChild (ConvertCatch (tryCatchStatement.General), TryCatchStatement.CatchClauseRole); + + return result; + } + + public override object Visit (Using usingStatement) + { + var result = new UsingStatement (); + var location = LocationsBag.GetLocations (usingStatement); + + result.AddChild (new CSharpTokenNode (Convert (usingStatement.loc), "using".Length), UsingStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), UsingStatement.Roles.LPar); + if (usingStatement.Expression != null) + result.AddChild ((AstNode)usingStatement.Expression.Accept (this), UsingStatement.ResourceAcquisitionRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), UsingStatement.Roles.RPar); + + if (usingStatement.Statement != null) + result.AddChild ((Statement)usingStatement.Statement.Accept (this), UsingStatement.Roles.EmbeddedStatement); + return result; + } + + public override object Visit (Foreach foreachStatement) + { + var result = new ForeachStatement (); + + var location = LocationsBag.GetLocations (foreachStatement); + + result.AddChild (new CSharpTokenNode (Convert (foreachStatement.loc), "foreach".Length), ForeachStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), ForeachStatement.Roles.LPar); + + if (foreachStatement.TypeExpr != null) + result.AddChild (ConvertToType (foreachStatement.TypeExpr), ForeachStatement.Roles.Type); + if (foreachStatement.Variable != null) + result.AddChild (Identifier.Create (foreachStatement.Variable.Name, Convert (foreachStatement.Variable.Location)), ForeachStatement.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), "in".Length), ForeachStatement.Roles.InKeyword); + + if (foreachStatement.Expr != null) + result.AddChild ((Expression)foreachStatement.Expr.Accept (this), ForeachStatement.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForeachStatement.Roles.RPar); + if (foreachStatement.Statement != null) + result.AddChild ((Statement)foreachStatement.Statement.Accept (this), ForeachStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (Yield yieldStatement) + { + var result = new YieldStatement (); + var location = LocationsBag.GetLocations (yieldStatement); + + result.AddChild (new CSharpTokenNode (Convert (yieldStatement.loc), "yield".Length), YieldStatement.YieldKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "return".Length), YieldStatement.ReturnKeywordRole); + if (yieldStatement.Expr != null) + result.AddChild ((Expression)yieldStatement.Expr.Accept (this), YieldStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (YieldBreak yieldBreakStatement) + { + var result = new YieldBreakStatement (); + var location = LocationsBag.GetLocations (yieldBreakStatement); + result.AddChild (new CSharpTokenNode (Convert (yieldBreakStatement.loc), "yield".Length), YieldBreakStatement.YieldKeywordRole); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "break".Length), YieldBreakStatement.BreakKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldBreakStatement.Roles.Semicolon); + } + return result; + } + #endregion + + #region Expression + public override object Visit (Mono.CSharp.Expression expression) + { + Console.WriteLine ("Visit unknown expression:" + expression); + System.Console.WriteLine (Environment.StackTrace); + return null; + } + + public override object Visit (Mono.CSharp.DefaultParameterValueExpression defaultParameterValueExpression) + { + return defaultParameterValueExpression.Child.Accept (this); + } + + public override object Visit (TypeExpression typeExpression) + { + return new TypeReferenceExpression (new PrimitiveType (keywordTable [(int)typeExpression.Type.BuiltinType], Convert (typeExpression.Location))); + } + + public override object Visit (LocalVariableReference localVariableReference) + { + return Identifier.Create (localVariableReference.Name, Convert (localVariableReference.Location));; + } + + public override object Visit (MemberAccess memberAccess) + { + Expression result; + if (memberAccess.LeftExpression is Indirection) { + var ind = memberAccess.LeftExpression as Indirection; + result = new PointerReferenceExpression (); + result.AddChild ((Expression)ind.Expr.Accept (this), PointerReferenceExpression.Roles.TargetExpression); + result.AddChild (new CSharpTokenNode (Convert (ind.Location), "->".Length), PointerReferenceExpression.ArrowRole); + } else { + result = new MemberReferenceExpression (); + if (memberAccess.LeftExpression != null) { + var leftExpr = memberAccess.LeftExpression.Accept (this); + result.AddChild ((Expression)leftExpr, MemberReferenceExpression.Roles.TargetExpression); + } + } + + result.AddChild (Identifier.Create (memberAccess.Name, Convert (memberAccess.Location)), MemberReferenceExpression.Roles.Identifier); + + if (memberAccess.TypeArguments != null) { + var location = LocationsBag.GetLocations (memberAccess); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeArguments (result, location, memberAccess.TypeArguments); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MemberReferenceExpression.Roles.RChevron); + } + return result; + } + + public override object Visit (QualifiedAliasMember qualifiedAliasMember) + { + var result = new MemberType (); + result.Target = new SimpleType (qualifiedAliasMember.alias, Convert (qualifiedAliasMember.Location)); + result.IsDoubleColon = true; + var location = LocationsBag.GetLocations (qualifiedAliasMember); + result.AddChild (Identifier.Create (qualifiedAliasMember.Name, location != null ? Convert (location[0]) : AstLocation.Empty), MemberReferenceExpression.Roles.Identifier); + return new TypeReferenceExpression () { Type = result }; + } + + public override object Visit (Constant constant) + { + if (constant.GetValue () == null) + return new NullReferenceExpression (Convert (constant.Location)); + string literalValue; + if (constant is ILiteralConstant) { + literalValue = new string (((ILiteralConstant)constant).ParsedValue); + } else { + literalValue = constant.GetValueAsLiteral (); + } + var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), literalValue); + return result; + } + + public override object Visit (SimpleName simpleName) + { + var result = new IdentifierExpression (); + result.AddChild (Identifier.Create (simpleName.Name, Convert (simpleName.Location)), IdentifierExpression.Roles.Identifier); + if (simpleName.TypeArguments != null) { + var location = LocationsBag.GetLocations (simpleName); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IdentifierExpression.Roles.LChevron); + AddTypeArguments (result, location, simpleName.TypeArguments); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IdentifierExpression.Roles.RChevron); + } + return result; + } + + public override object Visit (BooleanExpression booleanExpression) + { + return booleanExpression.Expr.Accept (this); + } + + + public override object Visit (Mono.CSharp.ParenthesizedExpression parenthesizedExpression) + { + var result = new ParenthesizedExpression (); + var location = LocationsBag.GetLocations (parenthesizedExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ParenthesizedExpression.Roles.LPar); + result.AddChild ((Expression)parenthesizedExpression.Expr.Accept (this), ParenthesizedExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ParenthesizedExpression.Roles.RPar); + return result; + } + + public override object Visit (Unary unaryExpression) + { + var result = new UnaryOperatorExpression (); + switch (unaryExpression.Oper) { + case Unary.Operator.UnaryPlus: + result.Operator = UnaryOperatorType.Plus; + break; + case Unary.Operator.UnaryNegation: + result.Operator = UnaryOperatorType.Minus; + break; + case Unary.Operator.LogicalNot: + result.Operator = UnaryOperatorType.Not; + break; + case Unary.Operator.OnesComplement: + result.Operator = UnaryOperatorType.BitNot; + break; + case Unary.Operator.AddressOf: + result.Operator = UnaryOperatorType.AddressOf; + break; + } + result.AddChild (new CSharpTokenNode (Convert (unaryExpression.Location), 1), UnaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)unaryExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression); + return result; + } + + public override object Visit (UnaryMutator unaryMutatorExpression) + { + var result = new UnaryOperatorExpression (); + + var expression = (Expression)unaryMutatorExpression.Expr.Accept (this); + switch (unaryMutatorExpression.UnaryMutatorMode) { + case UnaryMutator.Mode.PostDecrement: + result.Operator = UnaryOperatorType.PostDecrement; + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + break; + case UnaryMutator.Mode.PostIncrement: + result.Operator = UnaryOperatorType.PostIncrement; + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + break; + + case UnaryMutator.Mode.PreIncrement: + result.Operator = UnaryOperatorType.Increment; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + break; + case UnaryMutator.Mode.PreDecrement: + result.Operator = UnaryOperatorType.Decrement; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + break; + } + + return result; + } + + public override object Visit (Indirection indirectionExpression) + { + var result = new UnaryOperatorExpression (); + result.Operator = UnaryOperatorType.Dereference; + var location = LocationsBag.GetLocations (indirectionExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)indirectionExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression); + return result; + } + + public override object Visit (Is isExpression) + { + var result = new IsExpression (); + result.AddChild ((Expression)isExpression.Expr.Accept (this), IsExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (isExpression.Location), "is".Length), IsExpression.Roles.Keyword); + result.AddChild (ConvertToType (isExpression.ProbeType), IsExpression.Roles.Type); + return result; + } + + public override object Visit (As asExpression) + { + var result = new AsExpression (); + result.AddChild ((Expression)asExpression.Expr.Accept (this), AsExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (asExpression.Location), "as".Length), AsExpression.Roles.Keyword); + result.AddChild (ConvertToType (asExpression.ProbeType), AsExpression.Roles.Type); + return result; + } + + public override object Visit (Cast castExpression) + { + var result = new CastExpression (); + var location = LocationsBag.GetLocations (castExpression); + + result.AddChild (new CSharpTokenNode (Convert (castExpression.Location), 1), CastExpression.Roles.LPar); + if (castExpression.TargetType != null) + result.AddChild (ConvertToType (castExpression.TargetType), CastExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CastExpression.Roles.RPar); + if (castExpression.Expr != null) + result.AddChild ((Expression)castExpression.Expr.Accept (this), CastExpression.Roles.Expression); + return result; + } + + public override object Visit (ComposedCast composedCast) + { + var result = new ComposedType (); + result.AddChild (ConvertToType (composedCast.Left), ComposedType.Roles.Type); + + var spec = composedCast.Spec; + while (spec != null) { + if (spec.IsNullable) { + result.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.NullableRole); + } else if (spec.IsPointer) { + result.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.PointerRole); + } else { + var aSpec = new ArraySpecifier (); + aSpec.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.Roles.LBracket); + var location = LocationsBag.GetLocations (spec); + if (location != null) + aSpec.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.Roles.RBracket); + result.AddChild (aSpec, ComposedType.ArraySpecifierRole); + } + spec = spec.Next; + } + + return result; + } + + public override object Visit (Mono.CSharp.DefaultValueExpression defaultValueExpression) + { + var result = new DefaultValueExpression (); + result.AddChild (new CSharpTokenNode (Convert (defaultValueExpression.Location), "default".Length), CastExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (defaultValueExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CastExpression.Roles.LPar); + result.AddChild (ConvertToType (defaultValueExpression.Expr), CastExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CastExpression.Roles.RPar); + return result; + } + + public override object Visit (Binary binaryExpression) + { + var result = new BinaryOperatorExpression (); + int opLength = 1; + switch (binaryExpression.Oper) { + case Binary.Operator.Multiply: + result.Operator = BinaryOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = BinaryOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = BinaryOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = BinaryOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = BinaryOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = BinaryOperatorType.ShiftLeft; + opLength = 2; + break; + case Binary.Operator.RightShift: + result.Operator = BinaryOperatorType.ShiftRight; + opLength = 2; + break; + case Binary.Operator.LessThan: + result.Operator = BinaryOperatorType.LessThan; + break; + case Binary.Operator.GreaterThan: + result.Operator = BinaryOperatorType.GreaterThan; + break; + case Binary.Operator.LessThanOrEqual: + result.Operator = BinaryOperatorType.LessThanOrEqual; + opLength = 2; + break; + case Binary.Operator.GreaterThanOrEqual: + result.Operator = BinaryOperatorType.GreaterThanOrEqual; + opLength = 2; + break; + case Binary.Operator.Equality: + result.Operator = BinaryOperatorType.Equality; + opLength = 2; + break; + case Binary.Operator.Inequality: + result.Operator = BinaryOperatorType.InEquality; + opLength = 2; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = BinaryOperatorType.BitwiseAnd; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = BinaryOperatorType.ExclusiveOr; + break; + case Binary.Operator.BitwiseOr: + result.Operator = BinaryOperatorType.BitwiseOr; + break; + case Binary.Operator.LogicalAnd: + result.Operator = BinaryOperatorType.ConditionalAnd; + opLength = 2; + break; + case Binary.Operator.LogicalOr: + result.Operator = BinaryOperatorType.ConditionalOr; + opLength = 2; + break; + } + + result.AddChild ((Expression)binaryExpression.Left.Accept (this), BinaryOperatorExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (binaryExpression.Location), opLength), BinaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)binaryExpression.Right.Accept (this), BinaryOperatorExpression.RightRole); + return result; + } + + public override object Visit (Mono.CSharp.Nullable.NullCoalescingOperator nullCoalescingOperator) + { + var result = new BinaryOperatorExpression (); + result.Operator = BinaryOperatorType.NullCoalescing; + result.AddChild ((Expression)nullCoalescingOperator.Left.Accept (this), BinaryOperatorExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (nullCoalescingOperator.Location), 2), BinaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)nullCoalescingOperator.Right.Accept (this), BinaryOperatorExpression.RightRole); + return result; + } + + public override object Visit (Conditional conditionalExpression) + { + var result = new ConditionalExpression (); + + result.AddChild ((Expression)conditionalExpression.Expr.Accept (this), ConditionalExpression.Roles.Condition); + var location = LocationsBag.GetLocations (conditionalExpression); + + result.AddChild (new CSharpTokenNode (Convert (conditionalExpression.Location), 1), ConditionalExpression.QuestionMarkRole); + result.AddChild ((Expression)conditionalExpression.TrueExpr.Accept (this), ConditionalExpression.TrueRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConditionalExpression.ColonRole); + result.AddChild ((Expression)conditionalExpression.FalseExpr.Accept (this), ConditionalExpression.FalseRole); + return result; + } + + void AddParameter (AstNode parent, Mono.CSharp.AParametersCollection parameters) + { + if (parameters == null) + return; + var paramLocation = LocationsBag.GetLocations (parameters); + + for (int i = 0; i < parameters.Count; i++) { + if (paramLocation != null && i > 0 && i - 1 < paramLocation.Count) + parent.AddChild (new CSharpTokenNode (Convert (paramLocation [i - 1]), 1), ParameterDeclaration.Roles.Comma); + var p = (Parameter)parameters.FixedParameters [i]; + var location = LocationsBag.GetLocations (p); + + ParameterDeclaration parameterDeclarationExpression = new ParameterDeclaration (); + AddAttributeSection (parameterDeclarationExpression, p); + switch (p.ModFlags) { + case Parameter.Modifier.OUT: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Out; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "out".Length), ParameterDeclaration.Roles.Keyword); + break; + case Parameter.Modifier.REF: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Ref; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "ref".Length), ParameterDeclaration.Roles.Keyword); + break; + case Parameter.Modifier.PARAMS: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Params; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "params".Length), ParameterDeclaration.Roles.Keyword); + break; + default: + if (p.HasExtensionMethodModifier) { + parameterDeclarationExpression.ParameterModifier = ParameterModifier.This; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "this".Length), ParameterDeclaration.Roles.Keyword); + } + break; + } + if (p.TypeExpression != null) // lambdas may have no types (a, b) => ... + parameterDeclarationExpression.AddChild (ConvertToType (p.TypeExpression), ParameterDeclaration.Roles.Type); + if (p.Name != null) + parameterDeclarationExpression.AddChild (Identifier.Create (p.Name, Convert (p.Location)), ParameterDeclaration.Roles.Identifier); + if (p.HasDefaultValue) { + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ParameterDeclaration.Roles.Assign); + parameterDeclarationExpression.AddChild ((Expression)p.DefaultValue.Accept (this), ParameterDeclaration.Roles.Expression); + } + parent.AddChild (parameterDeclarationExpression, InvocationExpression.Roles.Parameter); + } + } + + void AddTypeParameters (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = (TypeParameterName)typeArguments.Args[i]; + if (arg == null) + continue; + TypeParameterDeclaration tp = new TypeParameterDeclaration(); + // TODO: attributes +// if (arg.Variance != Variance.None) +// throw new NotImplementedException(); // TODO: variance + tp.AddChild (Identifier.Create (arg.Name, Convert (arg.Location)), InvocationExpression.Roles.Identifier); + parent.AddChild (tp, InvocationExpression.Roles.TypeParameter); + } + } + + void AddTypeArguments (AstNode parent, LocationsBag.MemberLocations location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = typeArguments.Args[i]; + if (arg == null) + continue; + parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + } + } + + void AddTypeArguments (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = typeArguments.Args[i]; + if (arg == null) + continue; + parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + } + } + + void AddConstraints (AstNode parent, DeclSpace d) + { + if (d == null || d.Constraints == null) + return; + for (int i = 0; i < d.PlainConstraints.Count; i++) { + Constraints c = d.PlainConstraints [i]; + var location = LocationsBag.GetLocations (c); + var constraint = new Constraint (); + if (location != null) + constraint.AddChild (new CSharpTokenNode (Convert (location [0]), "where".Length), InvocationExpression.Roles.Keyword); + constraint.AddChild (Identifier.Create (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier); + if (location != null && location.Count > 1) + constraint.AddChild (new CSharpTokenNode (Convert (location [1]), 1), Constraint.ColonRole); + foreach (var expr in c.ConstraintExpressions) + constraint.AddChild (ConvertToType (expr), Constraint.BaseTypeRole); + parent.AddChild (constraint, AstNode.Roles.Constraint); + } + } + + Expression ConvertArgument (Argument arg) + { + if (arg is NamedArgument) { + var na = (NamedArgument)arg; + NamedArgumentExpression newArg = new NamedArgumentExpression(); + newArg.AddChild (Identifier.Create (na.Name, Convert (na.Location)), NamedArgumentExpression.Roles.Identifier); + + var loc = LocationsBag.GetLocations (na); + if (loc != null) + newArg.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), NamedArgumentExpression.Roles.Assign); + + if (arg.ArgType == Argument.AType.Out || arg.ArgType == Argument.AType.Ref) { + DirectionExpression direction = new DirectionExpression (); + direction.FieldDirection = arg.ArgType == Argument.AType.Out ? FieldDirection.Out : FieldDirection.Ref; + var argLocation = LocationsBag.GetLocations (arg); + if (argLocation != null) + direction.AddChild (new CSharpTokenNode (Convert (argLocation[0]), "123".Length), InvocationExpression.Roles.Keyword); + direction.AddChild ((Expression)arg.Expr.Accept (this), InvocationExpression.Roles.Expression); + newArg.AddChild (direction, NamedArgumentExpression.Roles.Expression); + } else { + newArg.AddChild ((Expression)na.Expr.Accept (this), NamedArgumentExpression.Roles.Expression); + } + return newArg; + } + + if (arg.ArgType == Argument.AType.Out || arg.ArgType == Argument.AType.Ref) { + DirectionExpression direction = new DirectionExpression (); + direction.FieldDirection = arg.ArgType == Argument.AType.Out ? FieldDirection.Out : FieldDirection.Ref; + var argLocation = LocationsBag.GetLocations (arg); + if (argLocation != null) + direction.AddChild (new CSharpTokenNode (Convert (argLocation[0]), "123".Length), InvocationExpression.Roles.Keyword); + direction.AddChild ((Expression)arg.Expr.Accept (this), InvocationExpression.Roles.Expression); + return direction; + } + + return (Expression)arg.Expr.Accept (this); + } + + void AddArguments (AstNode parent, object location, Mono.CSharp.Arguments args) + { + if (args == null) + return; + + var commaLocations = LocationsBag.GetLocations (args); + + for (int i = 0; i < args.Count; i++) { + parent.AddChild (ConvertArgument (args[i]), InvocationExpression.Roles.Argument); + if (commaLocations != null && i > 0) { + int idx = commaLocations.Count - i; + if (idx >= 0) + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[idx]), 1), InvocationExpression.Roles.Comma); + } + } + if (commaLocations != null && commaLocations.Count > args.Count) + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[0]), 1), InvocationExpression.Roles.Comma); + } + + public override object Visit (Invocation invocationExpression) + { + var result = new InvocationExpression (); + var location = LocationsBag.GetLocations (invocationExpression); + result.AddChild ((Expression)invocationExpression.Expression.Accept (this), InvocationExpression.Roles.TargetExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), InvocationExpression.Roles.LPar); + AddArguments (result, location, invocationExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), InvocationExpression.Roles.RPar); + return result; + } + + public override object Visit (New newExpression) + { + var result = new ObjectCreateExpression (); + + var location = LocationsBag.GetLocations (newExpression); + result.AddChild (new CSharpTokenNode (Convert (newExpression.Location), "new".Length), ObjectCreateExpression.Roles.Keyword); + + if (newExpression.TypeRequested != null) + result.AddChild (ConvertToType (newExpression.TypeRequested), ObjectCreateExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ObjectCreateExpression.Roles.LPar); + AddArguments (result, location, newExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + + return result; + } + + public override object Visit (NewAnonymousType newAnonymousType) + { + var result = new AnonymousTypeCreateExpression (); + if (newAnonymousType.Parameters == null) + return result; + foreach (var par in newAnonymousType.Parameters) { + var location = LocationsBag.GetLocations (par); + + if (location == null) { + result.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + } else { + var namedArgument = new NamedArgumentExpression (); + namedArgument.AddChild (Identifier.Create (par.Name, Convert (par.Location)), AnonymousTypeCreateExpression.Roles.Identifier); + namedArgument.AddChild (new CSharpTokenNode (Convert (location[0]), 1), AnonymousTypeCreateExpression.Roles.Assign); + namedArgument.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + result.AddChild (namedArgument, AnonymousTypeCreateExpression.Roles.Expression); + } + } + return result; + } + + + public override object Visit (NewInitialize newInitializeExpression) + { + var result = new ObjectCreateExpression (); + result.AddChild (new CSharpTokenNode (Convert (newInitializeExpression.Location), "new".Length), ObjectCreateExpression.Roles.Keyword); + + if (newInitializeExpression.TypeRequested != null) + result.AddChild (ConvertToType (newInitializeExpression.TypeRequested), ObjectCreateExpression.Roles.Type); + + var location = LocationsBag.GetLocations (newInitializeExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ObjectCreateExpression.Roles.LPar); + AddArguments (result, location, newInitializeExpression.Arguments); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + + return result; + } + + + public override object Visit (ArrayCreation arrayCreationExpression) + { + var result = new ArrayCreateExpression (); + + var location = LocationsBag.GetLocations (arrayCreationExpression); + if (arrayCreationExpression.NewType != null) + result.AddChild (ConvertToType (arrayCreationExpression.NewType), ArrayCreateExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayCreateExpression.Roles.LBracket); + if (arrayCreationExpression.Arguments != null) { + var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Arguments); + for (int i = 0 ;i < arrayCreationExpression.Arguments.Count; i++) { + result.AddChild ((Expression)arrayCreationExpression.Arguments[i].Accept (this), ArrayCreateExpression.Roles.Argument); + if (commaLocations != null && i > 0) + result.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), ArrayCreateExpression.Roles.Comma); + } + } + var next = arrayCreationExpression.Rank.Next; + while (next != null) { + ArraySpecifier spec = new ArraySpecifier (next.Dimension); + var loc = LocationsBag.GetLocations (next); + spec.AddChild (new CSharpTokenNode (Convert (next.Location), 1), ArraySpecifier.Roles.LBracket); + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), ArraySpecifier.Roles.RBracket); + result.AddChild (spec, ArrayCreateExpression.AdditionalArraySpecifierRole); + next = next.Next; + } + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayCreateExpression.Roles.RBracket); + + if (arrayCreationExpression.Initializers != null && arrayCreationExpression.Initializers.Count != 0) { + var initLocation = LocationsBag.GetLocations (arrayCreationExpression.Initializers); + ArrayInitializerExpression initializer = new ArrayInitializerExpression(); + + initializer.AddChild (new CSharpTokenNode (Convert (arrayCreationExpression.Initializers.Location), 1), ArrayCreateExpression.Roles.LBrace); + var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Initializers.Elements); + for (int i = 0; i < arrayCreationExpression.Initializers.Count; i++) { + initializer.AddChild ((Expression)arrayCreationExpression.Initializers[i].Accept (this), ArrayInitializerExpression.Roles.Expression); + if (commaLocations != null && i > 0) { + initializer.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), IndexerExpression.Roles.Comma); + } + } + + if (initLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (initLocation[initLocation.Count - 1]), 1), ArrayCreateExpression.Roles.RBrace); + result.AddChild (initializer, ArrayCreateExpression.InitializerRole); + } + + return result; + } + + public override object Visit (This thisExpression) + { + var result = new ThisReferenceExpression (); + result.Location = Convert (thisExpression.Location); + return result; + } + + public override object Visit (ArglistAccess argListAccessExpression) + { + var result = new UndocumentedExpression () { + UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess + }; + result.AddChild (new CSharpTokenNode (Convert (argListAccessExpression.Location), "__arglist".Length), UndocumentedExpression.Roles.Keyword); + return result; + } + + #region Undocumented expressions + public override object Visit (Arglist argListExpression) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }; + result.AddChild (new CSharpTokenNode (Convert (argListExpression.Location), "__arglist".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (argListExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + AddArguments (result, location, argListExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (MakeRefExpr makeRefExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (makeRefExpr.Location), "__makeref".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (makeRefExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + if (makeRefExpr.Expr != null) + result.AddChild ((Expression)makeRefExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (RefTypeExpr refTypeExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (refTypeExpr.Location), "__reftype".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (refTypeExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + if (refTypeExpr.Expr != null) + result.AddChild ((Expression)refTypeExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (RefValueExpr refValueExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (refValueExpr.Location), "__refvalue".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (refValueExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + + if (refValueExpr.Expr != null) + result.AddChild ((Expression)refValueExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + + if (refValueExpr.FullNamedExpression != null) + result.AddChild ((Expression)refValueExpr.FullNamedExpression.Accept (this), UndocumentedExpression.Roles.Argument); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + #endregion + + public override object Visit (TypeOf typeOfExpression) + { + var result = new TypeOfExpression (); + var location = LocationsBag.GetLocations (typeOfExpression); + result.AddChild (new CSharpTokenNode (Convert (typeOfExpression.Location), "typeof".Length), TypeOfExpression.Roles.Keyword); + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild (ConvertToType (typeOfExpression.TypeExpression), TypeOfExpression.Roles.Type); + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (SizeOf sizeOfExpression) + { + var result = new SizeOfExpression (); + var location = LocationsBag.GetLocations (sizeOfExpression); + result.AddChild (new CSharpTokenNode (Convert (sizeOfExpression.Location), "sizeof".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild (ConvertToType (sizeOfExpression.QueriedType), TypeOfExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (CheckedExpr checkedExpression) + { + var result = new CheckedExpression (); + var location = LocationsBag.GetLocations (checkedExpression); + result.AddChild (new CSharpTokenNode (Convert (checkedExpression.Location), "checked".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild ((Expression)checkedExpression.Expr.Accept (this), TypeOfExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (UnCheckedExpr uncheckedExpression) + { + var result = new UncheckedExpression (); + var location = LocationsBag.GetLocations (uncheckedExpression); + result.AddChild (new CSharpTokenNode (Convert (uncheckedExpression.Location), "unchecked".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild ((Expression)uncheckedExpression.Expr.Accept (this), TypeOfExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (ElementAccess elementAccessExpression) + { + IndexerExpression result = new IndexerExpression (); + var location = LocationsBag.GetLocations (elementAccessExpression); + + result.AddChild ((Expression)elementAccessExpression.Expr.Accept (this), IndexerExpression.Roles.TargetExpression); + result.AddChild (new CSharpTokenNode (Convert (elementAccessExpression.Location), 1), TypeOfExpression.Roles.LBracket); + AddArguments (result, location, elementAccessExpression.Arguments); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.RBracket); + return result; + } + + public override object Visit (BaseThis baseAccessExpression) + { + var result = new BaseReferenceExpression (); + result.Location = Convert (baseAccessExpression.Location); + return result; + } + + public override object Visit (StackAlloc stackAllocExpression) + { + var result = new StackAllocExpression (); + + var location = LocationsBag.GetLocations (stackAllocExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "stackalloc".Length), StackAllocExpression.Roles.Keyword); + result.AddChild (ConvertToType (stackAllocExpression.TypeExpression), StackAllocExpression.Roles.Type); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), StackAllocExpression.Roles.LBracket); + result.AddChild ((Expression)stackAllocExpression.CountExpression.Accept (this), StackAllocExpression.Roles.Expression); + if (location != null && location.Count > 2) + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), StackAllocExpression.Roles.RBracket); + return result; + } + + public override object Visit (SimpleAssign simpleAssign) + { + var result = new AssignmentExpression (); + + result.Operator = AssignmentOperatorType.Assign; + if (simpleAssign.Target != null) + result.AddChild ((Expression)simpleAssign.Target.Accept (this), AssignmentExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (simpleAssign.Location), 1), AssignmentExpression.OperatorRole); + if (simpleAssign.Source != null) { + result.AddChild ((Expression)simpleAssign.Source.Accept (this), AssignmentExpression.RightRole); + } + return result; + } + + public override object Visit (CompoundAssign compoundAssign) + { + var result = new AssignmentExpression (); + int opLength = 2; + switch (compoundAssign.Op) { + case Binary.Operator.Multiply: + result.Operator = AssignmentOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = AssignmentOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = AssignmentOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = AssignmentOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = AssignmentOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = AssignmentOperatorType.ShiftLeft; + opLength = 3; + break; + case Binary.Operator.RightShift: + result.Operator = AssignmentOperatorType.ShiftRight; + opLength = 3; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = AssignmentOperatorType.BitwiseAnd; + break; + case Binary.Operator.BitwiseOr: + result.Operator = AssignmentOperatorType.BitwiseOr; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = AssignmentOperatorType.ExclusiveOr; + break; + } + + result.AddChild ((Expression)compoundAssign.Target.Accept (this), AssignmentExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (compoundAssign.Location), opLength), AssignmentExpression.OperatorRole); + result.AddChild ((Expression)compoundAssign.Source.Accept (this), AssignmentExpression.RightRole); + return result; + } + + public override object Visit (Mono.CSharp.AnonymousMethodExpression anonymousMethodExpression) + { + var result = new AnonymousMethodExpression (); + var location = LocationsBag.GetLocations (anonymousMethodExpression); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword); + + if (location.Count > 1) { + result.HasParameterList = true; + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AnonymousMethodExpression.Roles.LPar); + AddParameter (result, anonymousMethodExpression.Parameters); + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AnonymousMethodExpression.Roles.RPar); + } + } + result.AddChild ((BlockStatement)anonymousMethodExpression.Block.Accept (this), AnonymousMethodExpression.Roles.Body); + return result; + } + + public override object Visit (Mono.CSharp.LambdaExpression lambdaExpression) + { + var result = new LambdaExpression (); + var location = LocationsBag.GetLocations (lambdaExpression); + + if (location == null || location.Count == 1) { + AddParameter (result, lambdaExpression.Parameters); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), "=>".Length), LambdaExpression.ArrowRole); + } else { + result.AddChild (new CSharpTokenNode (Convert (lambdaExpression.Location), 1), LambdaExpression.Roles.LPar); + AddParameter (result, lambdaExpression.Parameters); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), LambdaExpression.Roles.RPar); + result.AddChild (new CSharpTokenNode (Convert (location [1]), "=>".Length), LambdaExpression.ArrowRole); + } + } + if (lambdaExpression.Block.IsCompilerGenerated) { + ContextualReturn generatedReturn = (ContextualReturn)lambdaExpression.Block.Statements [0]; + result.AddChild ((AstNode)generatedReturn.Expr.Accept (this), LambdaExpression.BodyRole); + } else { + result.AddChild ((AstNode)lambdaExpression.Block.Accept (this), LambdaExpression.BodyRole); + } + + return result; + } + + public override object Visit (ConstInitializer constInitializer) + { + return constInitializer.Expr.Accept (this); + } + + public override object Visit (ArrayInitializer arrayInitializer) + { + var result = new ArrayInitializerExpression (); + var location = LocationsBag.GetLocations (arrayInitializer); + result.AddChild (new CSharpTokenNode (Convert (arrayInitializer.Location), "{".Length), ArrayInitializerExpression.Roles.LBrace); + var commaLocations = LocationsBag.GetLocations (arrayInitializer.Elements); + for (int i = 0; i < arrayInitializer.Count; i++) { + result.AddChild ((Expression)arrayInitializer[i].Accept (this), ArrayInitializerExpression.Roles.Expression); + if (commaLocations != null && i < commaLocations.Count) + result.AddChild (new CSharpTokenNode (Convert (commaLocations[i]), ",".Length), ArrayInitializerExpression.Roles.Comma); + } + + if (location != null) { + if (location.Count == 2) // optional comma + result.AddChild (new CSharpTokenNode (Convert (location[1]), ",".Length), ArrayInitializerExpression.Roles.Comma); + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), "}".Length), ArrayInitializerExpression.Roles.RBrace); + } + return result; + } + + #endregion + + #region LINQ expressions + public override object Visit (Mono.CSharp.Linq.QueryExpression queryExpression) + { + var result = new QueryExpression (); + + var currentClause = queryExpression.next; + + while (currentClause != null) { + QueryClause clause = (QueryClause)currentClause.Accept (this); + if (clause is QueryContinuationClause) { + // insert preceding query at beginning of QueryContinuationClause + clause.InsertChildAfter(null, result, QueryContinuationClause.PrecedingQueryRole); + // create a new QueryExpression for the remaining query + result = new QueryExpression(); + } + result.AddChild (clause, QueryExpression.ClauseRole); + currentClause = currentClause.next; + } + + return result; + } + + public override object Visit (Mono.CSharp.Linq.QueryStartClause queryStart) + { + if (queryStart.Expr == null) { + var intoClause = new QueryContinuationClause (); + intoClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "into".Length), QueryContinuationClause.IntoKeywordRole); + intoClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryContinuationClause.Roles.Identifier); + return intoClause; + } + + var fromClause = new QueryFromClause (); + var location = LocationsBag.GetLocations (queryStart); + + fromClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "from".Length), QueryFromClause.FromKeywordRole); + + if (queryStart.IdentifierType != null) + fromClause.AddChild (ConvertToType (queryStart.IdentifierType), QueryFromClause.Roles.Type); + + fromClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryFromClause.Roles.Identifier); + + if (location != null) + fromClause.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryFromClause.InKeywordRole); + fromClause.AddChild ((Expression)queryStart.Expr.Accept (this), QueryFromClause.Roles.Expression); + return fromClause; + } + + public override object Visit (Mono.CSharp.Linq.SelectMany queryStart) + { + var fromClause = new QueryFromClause (); + var location = LocationsBag.GetLocations (queryStart); + + fromClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "from".Length), QueryFromClause.FromKeywordRole); + + if (queryStart.IdentifierType != null) + fromClause.AddChild (ConvertToType (queryStart.IdentifierType), QueryFromClause.Roles.Type); + + fromClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryFromClause.Roles.Identifier); + + if (location != null) + fromClause.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryFromClause.InKeywordRole); + fromClause.AddChild ((Expression)queryStart.Expr.Accept (this), QueryFromClause.Roles.Expression); + return fromClause; + } + + public override object Visit (Mono.CSharp.Linq.Select sel) + { + var result = new QuerySelectClause (); + result.AddChild (new CSharpTokenNode (Convert (sel.Location), "select".Length), QueryWhereClause.Roles.Keyword); + result.AddChild ((Expression)sel.Expr.Accept (this), QueryWhereClause.Roles.Expression); + return result; + } + + public override object Visit (Mono.CSharp.Linq.GroupBy groupBy) + { + var result = new QueryGroupClause (); + var location = LocationsBag.GetLocations (groupBy); + result.AddChild (new CSharpTokenNode (Convert (groupBy.Location), "group".Length), QueryGroupClause.GroupKeywordRole); + result.AddChild ((Expression)groupBy.ElementSelector.Accept (this), QueryGroupClause.KeyRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "by".Length), QueryGroupClause.ByKeywordRole); + result.AddChild ((Expression)groupBy.Expr.Accept (this), QueryGroupClause.ProjectionRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Let l) + { + var result = new QueryLetClause (); + var location = LocationsBag.GetLocations (l); + + result.AddChild (new CSharpTokenNode (Convert (l.Location), "let".Length), QueryLetClause.Roles.Keyword); + result.AddChild (Identifier.Create (l.IntoVariable.Name, Convert (l.IntoVariable.Location)), Identifier.Roles.Identifier); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), QueryLetClause.Roles.Assign); + result.AddChild ((Expression)l.Expr.Accept (this), QueryLetClause.Roles.Expression); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Where w) + { + var result = new QueryWhereClause (); + var location = LocationsBag.GetLocations (w); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "where".Length), QueryWhereClause.Roles.Keyword); + result.AddChild ((Expression)w.Expr.Accept (this), QueryWhereClause.Roles.Condition); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Join join) + { + var result = new QueryJoinClause (); + var location = LocationsBag.GetLocations (join); + result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); + + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); + // TODO: on expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); + // TODO: equals expression + + return result; + } + + public override object Visit (Mono.CSharp.Linq.GroupJoin join) + { + var result = new QueryJoinClause (); + var location = LocationsBag.GetLocations (join); + result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); + + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); + + // TODO: on expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); + // TODO: equals expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[3]), "into".Length), QueryJoinClause.IntoKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + return result; + } + + public override object Visit (Mono.CSharp.Linq.OrderByAscending orderByAscending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)orderByAscending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (orderByAscending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Ascending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.OrderByDescending orderByDescending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)orderByDescending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (orderByDescending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Descending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.ThenByAscending thenByAscending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)thenByAscending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (thenByAscending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Ascending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.ThenByDescending thenByDescending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)thenByDescending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (thenByDescending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Descending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + #endregion + } + + public CSharpParser () + { + CompilerArguments = new string[] { "-v", "-unsafe"}; + } + + public CSharpParser (string[] args) + { + CompilerArguments = args; + } + + static AstNode GetOuterLeft (AstNode node) + { + var outerLeft = node; + while (outerLeft.FirstChild != null) + outerLeft = outerLeft.FirstChild; + return outerLeft; + } + + static AstNode NextLeaf (AstNode node) + { + if (node == null) + return null; + var next = node.NextSibling; + if (next == null) + return node.Parent; + return GetOuterLeft(next); + } + + static void InsertComments (CompilerCompilationUnit top, ConversionVisitor conversionVisitor) + { + var leaf = GetOuterLeft(conversionVisitor.Unit); + + foreach (var special in top.SpecialsBag.Specials) { + var comment = special as SpecialsBag.Comment; + if (comment == null) + continue; + if (conversionVisitor.convertTypeSystemMode && (comment.CommentType != SpecialsBag.CommentType.Documentation)) + continue; + var type = (CommentType)comment.CommentType; + var start = new AstLocation (comment.Line, comment.Col); + var end = new AstLocation (comment.EndLine, comment.EndCol); + var domComment = new Comment (type, start, end); + domComment.StartsLine = comment.StartsLine; + domComment.Content = comment.Content; + + while (true) { + var nextLeaf = NextLeaf(leaf); + // instert comment at the end + if (nextLeaf == null) { + var node = leaf.Parent ?? conversionVisitor.Unit; + node.AddChild(domComment, AstNode.Roles.Comment); + leaf = domComment; + break; + } + + // comment is between 2 nodes + if (leaf.EndLocation <= domComment.StartLocation && domComment.StartLocation <= nextLeaf.StartLocation) { + var node = leaf.Parent ?? conversionVisitor.Unit; + node.InsertChildAfter(leaf, domComment, AstNode.Roles.Comment); + leaf = domComment; + break; + } + leaf = nextLeaf; + } + } + } + + internal static CompilationUnit Parse (bool convertTypeSystemMode, CompilerCompilationUnit top) + { + if (top == null) + return null; + CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (convertTypeSystemMode, top.LocationsBag); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); + top.UsingsBag.Global.Accept (conversionVisitor); + InsertComments (top, conversionVisitor); + return conversionVisitor.Unit; + } + + public class ErrorReportPrinter : ReportPrinter + { + readonly string fileName; + public readonly List Errors = new List (); + + public ErrorReportPrinter (string fileName) + { + this.fileName = fileName; + } + + public override void Print (AbstractMessage msg) + { + base.Print (msg); + var newError = new Error (msg.IsWarning ? ErrorType.Warning : ErrorType.Error, msg.Text, new DomRegion (fileName, msg.Location.Row, msg.Location.Column)); + Errors.Add (newError); + } + } + ErrorReportPrinter errorReportPrinter = new ErrorReportPrinter (null); + + public ErrorReportPrinter ErrorPrinter { + get { + return errorReportPrinter; + } + } + + public bool HasErrors { + get { + return errorReportPrinter.ErrorsCount + errorReportPrinter.FatalCounter > 0; + } + } + + public bool HasWarnings { + get { + return errorReportPrinter.WarningsCount > 0; + } + } + + public CompilationUnit Parse (TextReader reader, int line = 0) + { + // TODO: can we optimize this to avoid the text->stream->text roundtrip? + using (MemoryStream stream = new MemoryStream ()) { + StreamWriter w = new StreamWriter (stream, Encoding.UTF8); + char[] buffer = new char[2048]; + int read; + while ((read = reader.ReadBlock(buffer, 0, buffer.Length)) > 0) + w.Write (buffer, 0, read); + w.Flush (); // we can't close the StreamWriter because that would also close the MemoryStream + stream.Position = 0; + return Parse (stream, line); + } + } + + public static void AdjustLineLocations (AstNode node, int line) + { + if (node is IRelocatable) { + ((IRelocatable)node).SetStartLocation (new AstLocation (node.StartLocation.Line + line, node.StartLocation.Column)); + } + foreach (var child in node.Children) { + AdjustLineLocations (child, line); + } + } + + public CompilationUnit Parse (CompilerCompilationUnit top, int line) + { + if (top == null) + return null; + CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (GenerateTypeSystemMode, top.LocationsBag); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); + top.UsingsBag.Global.Accept (conversionVisitor); + InsertComments (top, conversionVisitor); + if (CompilationUnitCallback != null) + CompilationUnitCallback (top); + if (line != 0) + AdjustLineLocations (conversionVisitor.Unit, line); + if (top.LastYYValue is Mono.CSharp.Expression) + conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept (conversionVisitor) as AstNode; + return conversionVisitor.Unit; + } + + public string[] CompilerArguments { + get; + private set; + } + + public Action CompilationUnitCallback { + get; + set; + } + + public bool GenerateTypeSystemMode { + get; + set; + } + + public CompilationUnit Parse (Stream stream, int line = 0) + { + lock (CompilerCallableEntryPoint.parseLock) { + errorReportPrinter = new ErrorReportPrinter (""); + CompilerCompilationUnit top = CompilerCallableEntryPoint.ParseFile (CompilerArguments, stream, "parsed.cs", errorReportPrinter); + var unit = Parse (top, line); + unit.Errors.AddRange (errorReportPrinter.Errors); + return unit; + } + } + + public IEnumerable ParseTypeMembers (TextReader reader, int lineModifier = 0) + { + string code = "unsafe partial class MyClass { " + Environment.NewLine + reader.ReadToEnd () + "}"; + var cu = Parse (new StringReader (code), -1 + lineModifier); + if (cu == null) + return Enumerable.Empty (); + var td = cu.Children.FirstOrDefault () as TypeDeclaration; + if (td != null) + return td.Members; + return Enumerable.Empty (); + } + + public IEnumerable ParseStatements(TextReader reader, int lineModifier = 0) + { + string code = "void M() { " + Environment.NewLine + reader.ReadToEnd() + "}"; + var members = ParseTypeMembers(new StringReader(code), lineModifier - 1); + var method = members.FirstOrDefault() as MethodDeclaration; + if (method != null && method.Body != null) + return method.Body.Statements; + return Enumerable.Empty (); + } + + public AstType ParseTypeReference(TextReader reader) + { + string code = reader.ReadToEnd() + " a;"; + var members = ParseTypeMembers(new StringReader(code)); + var field = members.FirstOrDefault() as FieldDeclaration; + if (field != null) + return field.ReturnType; + return AstType.Null; + } + + public AstNode ParseExpression(TextReader reader) + { + var es = ParseStatements(new StringReader("tmp = " + Environment.NewLine + reader.ReadToEnd() + ";"), -1).FirstOrDefault() as ExpressionStatement; + if (es != null) { + AssignmentExpression ae = es.Expression as AssignmentExpression; + if (ae != null) + return ae.Right; + } + return null; + } + + /// + /// Parses a file snippet; guessing what the code snippet represents (compilation unit, type members, block, type reference, expression). + /// + public AstNode ParseSnippet(TextReader reader) + { + // TODO: add support for parsing a part of a file + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs index fd9bfab206..9545188427 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs @@ -12,18 +12,21 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Represents a file that was parsed and converted for the type system. /// - public sealed class ParsedFile : AbstractFreezable + public sealed class ParsedFile : AbstractFreezable, IParsedFile { readonly string fileName; readonly UsingScope rootUsingScope; IList topLevelTypeDefinitions = new List(); + IList assemblyAttributes = new List(); IList usingScopes = new List(); + IList errors = new List (); protected override void FreezeInternal() { base.FreezeInternal(); rootUsingScope.Freeze(); topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions); + assemblyAttributes = FreezeList(assemblyAttributes); usingScopes = FreezeList(usingScopes); } @@ -41,18 +44,38 @@ namespace ICSharpCode.NRefactory.CSharp get { return fileName; } } + DateTime parseTime = DateTime.Now; + public DateTime ParseTime { + get { + return parseTime; + } + } + public UsingScope RootUsingScope { get { return rootUsingScope; } } + public IList Errors { + get { return errors; } + internal set { errors = (List)value; } + } + public IList UsingScopes { get { return usingScopes; } } + public IProjectContent ProjectContent { + get { return rootUsingScope.ProjectContent; } + } + public IList TopLevelTypeDefinitions { get { return topLevelTypeDefinitions; } } + public IList AssemblyAttributes { + get { return assemblyAttributes; } + } + public UsingScope GetUsingScope(AstLocation location) { foreach (UsingScope scope in usingScopes) { @@ -64,9 +87,37 @@ namespace ICSharpCode.NRefactory.CSharp public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location) { - foreach (ITypeDefinition typeDef in topLevelTypeDefinitions) { - if (typeDef.Region.IsInside(location.Line, location.Column)) - return typeDef; + return FindEntity(topLevelTypeDefinitions, location); + } + + public ITypeDefinition GetTypeDefinition(AstLocation location) + { + ITypeDefinition parent = null; + ITypeDefinition type = GetTopLevelTypeDefinition(location); + while (type != null) { + parent = type; + type = FindEntity(parent.NestedTypes, location); + } + return parent; + } + + public IMember GetMember(AstLocation location) + { + ITypeDefinition type = GetTypeDefinition(location); + if (type == null) + return null; + return FindEntity(type.Methods, location) + ?? FindEntity(type.Fields, location) + ?? FindEntity(type.Properties, location) + ?? (IMember)FindEntity(type.Events, location); + } + + static T FindEntity(IList list, AstLocation location) where T : class, IEntity + { + // This could be improved using a binary search + foreach (T entity in list) { + if (entity.Region.IsInside(location.Line, location.Column)) + return entity; } return null; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs index b3dfd30b57..ccd273ba51 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using ICSharpCode.NRefactory.CSharp.Analysis; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; @@ -78,8 +80,20 @@ namespace ICSharpCode.NRefactory.CSharp node.GetChildByRole(AstNode.Roles.RBrace).EndLocation); } + #region Compilation Unit + public override IEntity VisitCompilationUnit (CompilationUnit unit, object data) + { + parsedFile.Errors = unit.Errors; + return base.VisitCompilationUnit (unit, data); + } + #endregion + #region Using Declarations - // TODO: extern aliases + public override IEntity VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + { + usingScope.ExternAliases.Add(externAliasDeclaration.Name); + return null; + } public override IEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) { @@ -114,15 +128,14 @@ namespace ICSharpCode.NRefactory.CSharp } #endregion - // TODO: assembly attributes - #region Type Definitions DefaultTypeDefinition CreateTypeDefinition(string name) { DefaultTypeDefinition newType; if (currentTypeDefinition != null) { newType = new DefaultTypeDefinition(currentTypeDefinition, name); - currentTypeDefinition.InnerClasses.Add(newType); + newType.TypeParameters.AddRange(currentTypeDefinition.TypeParameters); + currentTypeDefinition.NestedTypes.Add(newType); } else { newType = new DefaultTypeDefinition(usingScope.ProjectContent, usingScope.NamespaceName, name); parsedFile.TopLevelTypeDefinitions.Add(newType); @@ -145,7 +158,7 @@ namespace ICSharpCode.NRefactory.CSharp else if (td.ClassType == ClassType.Enum || td.ClassType == ClassType.Struct) td.IsSealed = true; // enums/structs are implicitly sealed - ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints); + ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints, EntityType.TypeDefinition); foreach (AstType baseType in typeDeclaration.BaseTypes) { td.BaseTypes.Add(ConvertType(baseType)); @@ -155,6 +168,8 @@ namespace ICSharpCode.NRefactory.CSharp member.AcceptVisitor(this, data); } + td.HasExtensionMethods = td.Methods.Any(m => m.IsExtensionMethod); + currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; return td; } @@ -166,17 +181,25 @@ namespace ICSharpCode.NRefactory.CSharp td.Region = MakeRegion(delegateDeclaration); td.BaseTypes.Add(multicastDelegateReference); - ConvertAttributes(td.Attributes, delegateDeclaration.Attributes); ApplyModifiers(td, delegateDeclaration.Modifiers); td.IsSealed = true; // delegates are implicitly sealed - ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints); + ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints, EntityType.TypeDefinition); ITypeReference returnType = ConvertType(delegateDeclaration.ReturnType); List parameters = new List(); ConvertParameters(parameters, delegateDeclaration.Parameters); AddDefaultMethodsToDelegate(td, returnType, parameters); + foreach (AttributeSection section in delegateDeclaration.Attributes) { + if (section.AttributeTarget == "return") { + ConvertAttributes(td.Methods.Single(m => m.Name == "Invoke").ReturnTypeAttributes, section); + ConvertAttributes(td.Methods.Single(m => m.Name == "EndInvoke").ReturnTypeAttributes, section); + } else { + ConvertAttributes(td.Attributes, section); + } + } + currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; return td; } @@ -249,7 +272,7 @@ namespace ICSharpCode.NRefactory.CSharp #region Fields public override IEntity VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { - bool isSingleField = fieldDeclaration.Variables.Count() == 1; + bool isSingleField = fieldDeclaration.Variables.Count == 1; Modifiers modifiers = fieldDeclaration.Modifiers; DefaultField field = null; foreach (VariableInitializer vi in fieldDeclaration.Variables) { @@ -289,7 +312,12 @@ namespace ICSharpCode.NRefactory.CSharp if (!enumMemberDeclaration.Initializer.IsNull) { field.ConstantValue = ConvertConstantValue(currentTypeDefinition, enumMemberDeclaration.Initializer); } else { - throw new NotImplementedException(); + IField prevField = currentTypeDefinition.Fields.LastOrDefault(); + if (prevField == null || prevField.ConstantValue == null) { + field.ConstantValue = ConvertConstantValue(currentTypeDefinition, new PrimitiveExpression(0)); + } else { + field.ConstantValue = new IncrementConstantValue(prevField.ConstantValue); + } } currentTypeDefinition.Fields.Add(field); @@ -306,7 +334,7 @@ namespace ICSharpCode.NRefactory.CSharp m.BodyRegion = MakeRegion(methodDeclaration.Body); - ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints); + ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints, EntityType.Method); m.ReturnType = ConvertType(methodDeclaration.ReturnType); ConvertAttributes(m.Attributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget != "return")); ConvertAttributes(m.ReturnTypeAttributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget == "return")); @@ -325,10 +353,41 @@ namespace ICSharpCode.NRefactory.CSharp return m; } - void ConvertTypeParameters(IList output, IEnumerable typeParameters, IEnumerable constraints) + void ConvertTypeParameters(IList output, AstNodeCollection typeParameters, AstNodeCollection constraints, EntityType ownerType) { - if (typeParameters.Any()) - throw new NotImplementedException(); + // output might be non-empty when type parameters were copied from an outer class + int index = output.Count; + List list = new List(); + foreach (TypeParameterDeclaration tpDecl in typeParameters) { + DefaultTypeParameter tp = new DefaultTypeParameter(ownerType, index++, tpDecl.Name); + ConvertAttributes(tp.Attributes, tpDecl.Attributes); + tp.Variance = tpDecl.Variance; + list.Add(tp); + output.Add(tp); // tp must be added to list here so that it can be referenced by constraints + } + foreach (Constraint c in constraints) { + foreach (var tp in list) { + if (tp.Name == c.TypeParameter) { + foreach (AstType type in c.BaseTypes) { + PrimitiveType primType = type as PrimitiveType; + if (primType != null) { + if (primType.Keyword == "new") { + tp.HasDefaultConstructorConstraint = true; + continue; + } else if (primType.Keyword == "class") { + tp.HasReferenceTypeConstraint = true; + continue; + } else if (primType.Keyword == "struct") { + tp.HasValueTypeConstraint = true; + continue; + } + } + tp.Constraints.Add(ConvertType(type)); + } + break; + } + } + } } DefaultExplicitInterfaceImplementation ConvertInterfaceImplementation(AstType interfaceType, string memberName) @@ -445,10 +504,18 @@ namespace ICSharpCode.NRefactory.CSharp IAccessor ConvertAccessor(Accessor accessor, Accessibility defaultAccessibility) { + if (accessor.IsNull) + return null; DefaultAccessor a = new DefaultAccessor(); a.Accessibility = GetAccessibility(accessor.Modifiers) ?? defaultAccessibility; a.Region = MakeRegion(accessor); - ConvertAttributes(a.Attributes, accessor.Attributes); + foreach (AttributeSection section in accessor.Attributes) { + if (section.AttributeTarget == "return") { + ConvertAttributes(a.ReturnTypeAttributes, section); + } else if (section.AttributeTarget != "param") { + ConvertAttributes(a.Attributes, section); + } + } return a; } #endregion @@ -456,7 +523,7 @@ namespace ICSharpCode.NRefactory.CSharp #region Events public override IEntity VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { - bool isSingleEvent = eventDeclaration.Variables.Count() == 1; + bool isSingleEvent = eventDeclaration.Variables.Count == 1; Modifiers modifiers = eventDeclaration.Modifiers; DefaultEvent ev = null; foreach (VariableInitializer vi in eventDeclaration.Variables) { @@ -464,12 +531,26 @@ namespace ICSharpCode.NRefactory.CSharp ev.Region = isSingleEvent ? MakeRegion(eventDeclaration) : MakeRegion(vi); ev.BodyRegion = MakeRegion(vi); - ConvertAttributes(ev.Attributes, eventDeclaration.Attributes); ApplyModifiers(ev, modifiers); ev.ReturnType = ConvertType(eventDeclaration.ReturnType); + if (eventDeclaration.Attributes.Any(a => a.AttributeTarget == "method")) { + ev.AddAccessor = ev.RemoveAccessor = new DefaultAccessor { Accessibility = ev.Accessibility }; + } else { + // if there's no attributes on the accessors, we can re-use the shared accessor instance + ev.AddAccessor = ev.RemoveAccessor = DefaultAccessor.GetFromAccessibility(ev.Accessibility); + } + foreach (AttributeSection section in eventDeclaration.Attributes) { + if (section.AttributeTarget == "method") { + // as we use the same instance for AddAccessor and RemoveAccessor, we only need to add the attribute once + ConvertAttributes(ev.AddAccessor.Attributes, section); + } else if (section.AttributeTarget != "field") { + ConvertAttributes(ev.Attributes, section); + } + } + currentTypeDefinition.Events.Add(ev); } return isSingleEvent ? ev : null; @@ -508,6 +589,11 @@ namespace ICSharpCode.NRefactory.CSharp static void ApplyModifiers(TypeSystem.Implementation.AbstractMember m, Modifiers modifiers) { + // members from interfaces are always Public. + if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) { + m.Accessibility = Accessibility.Public; + return; + } m.Accessibility = GetAccessibility(modifiers) ?? Accessibility.Private; m.IsAbstract = (modifiers & Modifiers.Abstract) != 0; m.IsOverride = (modifiers & Modifiers.Override) != 0; @@ -537,12 +623,68 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Attributes + public override IEntity VisitAttributeSection(AttributeSection attributeSection, object data) + { + // non-assembly attributes are handled by their parent entity + if (attributeSection.AttributeTarget == "assembly") { + ConvertAttributes(parsedFile.AssemblyAttributes, attributeSection); + } + return null; + } + void ConvertAttributes(IList outputList, IEnumerable attributes) { foreach (AttributeSection section in attributes) { - throw new NotImplementedException(); + ConvertAttributes(outputList, section); } } + + void ConvertAttributes(IList outputList, AttributeSection attributeSection) + { + foreach (CSharp.Attribute attr in attributeSection.Attributes) { + outputList.Add(ConvertAttribute(attr)); + } + } + + IAttribute ConvertAttribute(CSharp.Attribute attr) + { + DomRegion region = MakeRegion(attr); + ITypeReference type = ConvertType(attr.Type); + if (!attr.Type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) { + // Try to add "Attribute" suffix, but only if the identifier + // (=last identifier in fully qualified name) isn't a verbatim identifier. + SimpleTypeOrNamespaceReference st = type as SimpleTypeOrNamespaceReference; + MemberTypeOrNamespaceReference mt = type as MemberTypeOrNamespaceReference; + if (st != null) + type = new AttributeTypeReference(st, st.AddSuffix("Attribute")); + else if (mt != null) + type = new AttributeTypeReference(mt, mt.AddSuffix("Attribute")); + } + List positionalArguments = null; + List> namedCtorArguments = null; + List> namedArguments = null; + foreach (Expression expr in attr.Arguments) { + NamedArgumentExpression nae = expr as NamedArgumentExpression; + if (nae != null) { + if (namedCtorArguments == null) + namedCtorArguments = new List>(); + namedCtorArguments.Add(new KeyValuePair(nae.Identifier, ConvertAttributeArgument(nae.Expression))); + } else { + AssignmentExpression ae = expr as AssignmentExpression; + if (ae != null && ae.Left is IdentifierExpression && ae.Operator == AssignmentOperatorType.Assign) { + string name = ((IdentifierExpression)ae.Left).Identifier; + if (namedArguments == null) + namedArguments = new List>(); + namedArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(ae.Right))); + } else { + if (positionalArguments == null) + positionalArguments = new List(); + positionalArguments.Add(ConvertAttributeArgument(expr)); + } + } + } + return new CSharpAttribute(type, region, positionalArguments, namedCtorArguments, namedArguments); + } #endregion #region Types @@ -652,8 +794,188 @@ namespace ICSharpCode.NRefactory.CSharp #region Constant Values IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression) { - // TODO: implement ConvertConstantValue - return new SimpleConstantValue(targetType, null); + ConstantValueBuilder b = new ConstantValueBuilder(); + b.convertVisitor = this; + ConstantExpression c = expression.AcceptVisitor(b, null); + if (c == null) + return null; + PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; + if (pc != null && pc.Type == targetType) { + // Save memory by directly using a SimpleConstantValue. + return new SimpleConstantValue(targetType, pc.Value); + } + // cast to the desired type + return new CSharpConstantValue(new ConstantCast(targetType, c), usingScope, currentTypeDefinition); + } + + IConstantValue ConvertAttributeArgument(Expression expression) + { + ConstantValueBuilder b = new ConstantValueBuilder(); + b.convertVisitor = this; + b.isAttributeArgument = true; + ConstantExpression c = expression.AcceptVisitor(b, null); + if (c == null) + return null; + PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; + if (pc != null) { + // Save memory by directly using a SimpleConstantValue. + return new SimpleConstantValue(pc.Type, pc.Value); + } else { + return new CSharpConstantValue(c, usingScope, currentTypeDefinition); + } + } + + sealed class ConstantValueBuilder : DepthFirstAstVisitor + { + internal TypeSystemConvertVisitor convertVisitor; + internal bool isAttributeArgument; + + protected override ConstantExpression VisitChildren(AstNode node, object data) + { + return null; + } + + public override ConstantExpression VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + { + return new PrimitiveConstantExpression(KnownTypeReference.Object, null); + } + + public override ConstantExpression VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + TypeCode typeCode = Type.GetTypeCode(primitiveExpression.Value.GetType()); + return new PrimitiveConstantExpression(typeCode.ToTypeReference(), primitiveExpression.Value); + } + + IList ConvertTypeArguments(AstNodeCollection types) + { + int count = types.Count; + if (count == 0) + return null; + ITypeReference[] result = new ITypeReference[count]; + int pos = 0; + foreach (AstType type in types) { + result[pos++] = convertVisitor.ConvertType(type); + } + return result; + } + + public override ConstantExpression VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + return new ConstantIdentifierReference(identifierExpression.Identifier, ConvertTypeArguments(identifierExpression.TypeArguments)); + } + + public override ConstantExpression VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + TypeReferenceExpression tre = memberReferenceExpression.Target as TypeReferenceExpression; + if (tre != null) { + // handle "int.MaxValue" + return new ConstantMemberReference( + convertVisitor.ConvertType(tre.Type), + memberReferenceExpression.MemberName, + ConvertTypeArguments(memberReferenceExpression.TypeArguments)); + } + ConstantExpression v = memberReferenceExpression.Target.AcceptVisitor(this, data); + if (v == null) + return null; + return new ConstantMemberReference( + v, memberReferenceExpression.MemberName, + ConvertTypeArguments(memberReferenceExpression.TypeArguments)); + } + + public override ConstantExpression VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + return parenthesizedExpression.Expression.AcceptVisitor(this, data); + } + + public override ConstantExpression VisitCastExpression(CastExpression castExpression, object data) + { + ConstantExpression v = castExpression.Expression.AcceptVisitor(this, data); + if (v == null) + return null; + return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v); + } + + public override ConstantExpression VisitCheckedExpression(CheckedExpression checkedExpression, object data) + { + ConstantExpression v = checkedExpression.Expression.AcceptVisitor(this, data); + if (v != null) + return new ConstantCheckedExpression(true, v); + else + return null; + } + + public override ConstantExpression VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + { + ConstantExpression v = uncheckedExpression.Expression.AcceptVisitor(this, data); + if (v != null) + return new ConstantCheckedExpression(false, v); + else + return null; + } + + public override ConstantExpression VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + { + return new ConstantDefaultValue(convertVisitor.ConvertType(defaultValueExpression.Type)); + } + + public override ConstantExpression VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + ConstantExpression v = unaryOperatorExpression.Expression.AcceptVisitor(this, data); + if (v == null) + return null; + switch (unaryOperatorExpression.Operator) { + case UnaryOperatorType.Not: + case UnaryOperatorType.BitNot: + case UnaryOperatorType.Minus: + case UnaryOperatorType.Plus: + return new ConstantUnaryOperator(unaryOperatorExpression.Operator, v); + default: + return null; + } + } + + public override ConstantExpression VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + ConstantExpression left = binaryOperatorExpression.Left.AcceptVisitor(this, data); + ConstantExpression right = binaryOperatorExpression.Right.AcceptVisitor(this, data); + if (left == null || right == null) + return null; + return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right); + } + + static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0); + + public override ConstantExpression VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + { + if (isAttributeArgument) { + return new PrimitiveConstantExpression(systemType, convertVisitor.ConvertType(typeOfExpression.Type)); + } else { + return null; + } + } + + public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression, object data) + { + var initializer = arrayObjectCreateExpression.Initializer; + if (isAttributeArgument && !initializer.IsNull) { + ITypeReference type; + if (arrayObjectCreateExpression.Type.IsNull) + type = null; + else + type = convertVisitor.ConvertType(arrayObjectCreateExpression.Type); + ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count]; + int pos = 0; + foreach (Expression expr in initializer.Elements) { + ConstantExpression c = expr.AcceptVisitor(this, data); + if (c == null) + return null; + elements[pos++] = c; + } + return new ConstantArrayCreation(type, elements); + } else { + return null; + } + } } #endregion diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs new file mode 100644 index 0000000000..252e3fb1e5 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// +// AssemblyInfo.cs +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle ("Mono C# Compiler")] +[assembly: AssemblyProduct ("Mono C# Compiler")] +[assembly: AssemblyCopyright ("2001 - 2009 Novell, Inc.")] +[assembly: AssemblyCompany ("Novell, Inc.")] +[assembly: AssemblyCulture ("")] +[assembly: AssemblyConfiguration ("")] + +[assembly: AssemblyVersion ("1.0")] +[assembly: AssemblyFileVersion ("1.0")] + +[assembly: AssemblyDescription ("Mono C# Compiler")] + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog new file mode 100644 index 0000000000..bb00893065 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog @@ -0,0 +1,34100 @@ +2010-07-28 Marek Safar + + * anonymous.cs, assign.cs, attribute.cs, decl.cs, delegate.cs, + doc.cs, dynamic.cs, ecore.cs, expression.cs, generic.cs, import.cs, + iterators.cs, linq.cs, membercache.cs, method.cs, report.cs, + statement.cs, typemanager.cs: Major name lookup fixes to deal with + C# 3.0 invocable members, correctly handle accessibility hidding and + property-like different get/set base accessors. + + Also fixes bugs #624870, #618522, #616068, #444180, #333891 + +2010-07-14 Marek Safar + + * namespace.cs, import.cs: When importing nested type via type + arguments set their parent type correctly (Fixes #622051). + +2010-07-14 Marek Safar + + A fix for bug #622104 + * attribute.cs: Add default lookup flags. + +2010-07-12 Marek Safar + + * generic.cs: Don't use Report directly. + + * expression.cs, ecore.cs: UserOperatorCall uses MethodSpec without + MethodGroupExpr, will be simplified later. + +2010-07-09 Marek Safar + + * property.cs, parameters.cs: Inflated IndexerSpec parameters. + + * import.cs: Don't build unused parameters. + +2010-07-08 Marek Safar + + * expression.cs (Invocation): Don't recreate simple-name expression. + +2010-07-07 Marek Safar + + * ecore.cs: Don't report NRE warning for lifted null. + +2010-07-07 Marek Safar + + * typemanager.cs, convert.cs, expression.cs: Another reference + equality implementation attack (Fixes #620025, #579058). + +2010-07-05 Marek Safar + + * context.cs, expression.cs, ecore.cs: BaseThis is fully based on + this expression (Fixes #619904). + +2010-07-05 Marek Safar + + * membercache.cs, class.cs: Don't use base member to check for + property or indexer base implementation. + +2010-07-03 Marek Safar + + * membercache.cs: Copy Membercache member state flags for 2 stage + inflate (Fixes #619555). + + * ecore.cs: Use resolved accessors everywhere. + +2010-07-02 Marek Safar + + A fix for bug #360820 + * membercache.cs, property.cs: Check accessors of base property and + not the closest one. + +2010-07-02 Marek Safar + + * modifiers.cs, membercache.cs, import.cs, class.cs: Moved imported + override method checks into import. + + * expression.cs: Removed redundant check. + +2010-06-30 Marek Safar + + * nullable.cs, expression.cs, statement.cs, method.cs, ecore.cs, + delegate.cs, cs-parser.jay, visit.cs: Use MemberAccess to resolve + base access expression, it has all bits done correctly. + +2010-06-30 Marek Safar + + * support.cs: Removed unused code. + + * ecore.cs: Don't use memberlookup for operators. + +2010-06-30 Marek Safar + + * typemanager.cs, membercache.cs, convert.cs, expression.cs, + ecore.cs: Replace remaining MethodLookup with correct user operator + lookup (to do correct deep lookup). Clean up most of outstanding + quirks in binary operator overload resolution. + +2010-06-29 Marek Safar + + * import.cs: Operators must have between 1 and 2 parameters. + + * method.cs: Switch destructor to direct membercache lookup + +2010-06-29 Marek Safar + + * driver.cs, expression.cs: Use Membercache for StringConcat when + it got all what is needed. + +2010-06-29 Marek Safar + + * membercache.cs, expression.cs, statement.cs, doc.cs, ecore.cs: + Changed FindMembers to allocate a new list only when a filter is + used. Saves decent chunk of memory and should save even more in the + future when the filter is not used that often. + +2010-06-28 Marek Safar + + * field.cs, property.cs, assign.cs, const.cs, expression.cs, + ecore.cs, class.cs, cs-parser.jay, enum.cs: Don't use intermediate + structure for simple type fields (saves memory and makes few things + simpler). Clean up some hacks mostly for events. + +2010-06-25 Marek Safar + + * statement.cs, cs-parser.jay: Don't create expensive block for + simple statements. + +2010-06-24 Marek Safar + + * statement.cs, report.cs: Rethrow internal error when reporting is + disabled. + + * ecore.cs: Check for identical name only when simple name is set. + Fixes #616667 + +2010-06-24 Marek Safar + + A fix for bug #616809 + * generic.cs, expression.cs, ecore.cs: Added a new type expression + for open generic type to pass unbound type arguments to typeof + expression. + +2010-06-24 Marek Safar + + * statement.cs: Foreach collection implementation refactoring to + search for GetEnumerator more preciselly. Fixes #431453 and more + unreported bugs. + + * linq.cs, decl.cs, ecore.cs, delegate.cs: Update methodgroup api. + +2010-06-23 Marek Safar + + * cs-parser.jay: Track more locations. + +2010-06-22 Marek Safar + + * cs-tokenizer.cs, location.cs, cs-parser.jay: Track more locations. + +2010-06-18 Marek Safar + + * cs-tokenizer.cs, anonymous.cs, expression.cs, statement.cs, + support.cs, location.cs, cs-parser.jay: Some work on full ast mode. + +2010-06-18 Marek Safar + + * convert.cs, typespec.cs, method.cs: Fixed few more dynamic + conversion. + +2010-06-18 Marek Safar + + * typemanager.cs, namespace.cs: Report more predefined types and + imported types collision types as a warning. + Fixes #537414, #601157 + +2010-06-18 Marek Safar + + * generic.cs: Overrides base method constraint can use method type + parameter. + + * import.cs: Removed redundant cache. + +2010-06-17 Marek Safar + + * generic.cs: Propagate type only inflate downwards. + +2010-06-17 Marek Safar + + A fix for bug #614955 + * method.cs: Do not reject binary dynamic operators. + +2010-06-17 Marek Safar + + * typespec.cs: Internal types have no generic parameters. + Fixes #615022. + +2010-06-17 Marek Safar + + A fix for bug #614955 + * cs-parser.jay: Correctly set expression mode for default parameter + values. + +2010-06-17 Marek Safar + + A fix for bug #615023 + * ecore.cs: Resolve dynamic namespace and keyword collision in the + favour of the keyword. + +2010-06-17 Marek Safar + + A fix for bug #614917 + * convert.cs: Allow more undocumented 0 like values to enum type + conversions. + +2010-06-17 Marek Safar + + * generic.cs, method.cs: Inflate copied type parameters from base + class or explicit interfaces. + + * convert.cs: Fixed conversion between two type parameters. + Fixes #614471 + +2010-06-16 Marek Safar + + * membercache.cs, convert.cs: Correctly resize an array used by + GetUserOperator. + +2010-06-15 Marek Safar + + A fix for bug #599601 + * dynamic.cs, ecore.cs: A new flag for dynamic resolver to ignore + generated member access left expression. + +2010-06-16 Marek Safar + + * expression.cs: Dispatch dynamic invocation solely on left + expression type. + +2010-06-16 Marek Safar + + * expression.cs, statement.cs: Always persist explicit cast + semantic at expression level. + +2010-06-15 Marek Safar + + * expression.cs, attribute.cs: Enable generic type parameters + attribute check. + +2010-06-15 Marek Safar + + A fix for bug #612146 + * generic.cs: Don't use fixed array for inflated type parameter + interface constraints. + +2010-06-15 Marek Safar + + * typespec.cs: ElementTypeSpec has to use its own ITypeDefinition. + + * report.cs: Unwrap elements for related symbols reporting. + +2010-06-15 Marek Safar + + A fix for bug #612796 + * cs-tokenizer.cs: Offset correctly keywords the first character + comparison. + +2010-06-15 Marek Safar + + A fix for bug #613397 + * expression.cs: Removed too aggressive object initializers + optimization. + +2010-06-15 Marek Safar + + * parameter.cs, property.cs, membercache.cs, decl.cs, iterators.cs, + anonymous.cs, expression.cs, support.cs, method.cs, pending.cs, + class.cs, cs-parser.jay: Simplify parsing of accessors by removing + any intermediate steps and fake nodes, also saves few MBs of memory. + +2010-06-11 Marek Safar + + * modifiers.cs, rootcontext.cs, location.cs, cs-parser.jay: More + precise modifiers parsing. + +2010-06-09 Marek Safar + + * cs-tokenizer.cs, anonymous.cs, expression.cs, cs-parser.jay: + Fixed few shift/reduce conflicts. + +2010-06-09 Marek Safar + + * typemanager.cs, parameter.cs, dynamic.cs, typespec.cs, + expression.cs, ecore.cs, cs-parser.jay: Fully parse composed type + specifiers and stop using string in AST. + +2010-06-07 Marek Safar + + * typemanager.cs, eval.cs, iterators.cs, anonymous.cs, expression.cs + method.cs, class.cs, delegate.cs, cs-parser.jay, driver.cs, visit.cs + enum.cs: Hold location of predefined types. + +2010-06-07 Marek Safar + + A fix for bug #610878 + * pending.cs: Clone cached list before modifying. + +2010-06-04 Marek Safar + + * convert.cs, typespec.cs, expression.cs: Start using array member + kind for better conversion checks. + + * import.cs, report.cs: Report better error message for runtime + reflection bugs. + +2010-06-04 Marek Safar + + * membercache.cs, convert.cs, nullable.cs, expression.cs: Optimize + user defined conversion probing and simplify user conversion for + nullabe types. Fixes #610940. + +2010-06-03 Marek Safar + + A fix for bug #610919 + * parameter.cs, property.cs, cs-parser.jay: Use independent implicit + parameters for explicit event accessors. Anonymous method capturing + won't otherwise work for event implicit parameter. + +2010-06-02 Marek Safar + + A fix for bug #610088 + * nullable.cs, expression.cs, statement.cs, method.cs, ecore.cs: + Ignore overrides for base overload resolution as for non-base + expressions and convert the best candidate to closest override + afterwards. + +2010-06-01 Marek Safar + + A fix for bug #610139 + * generic.cs, convert.cs: Recursively check effective base interface + +2010-06-01 Marek Safar + + * statement.cs: Handle nullable types and type parameters in using + statement, avoid boxing value types. Also fixes #571010 + +2010-06-01 Marek Safar + + * convert.cs, expression.cs: Emit unbox for underlying nullable + type boxing cast. + +2010-05-29 Marek Safar + + A fix for bug #610126 + * expression.cs: Don't use branch optimization for types bigger than + int. + +2010-05-28 Marek Safar + + A fix for bug #609088 + * import.cs: Check private modifier correctly. + +2010-05-28 Marek Safar + + A fix for bug #609049 + * ecore.cs: Don't ignore override methods when looking for base + member. + +2010-05-27 Marek Safar + + A fix for bugs #608007, #572540, #566130, #476358 + + * generic.cs, linq.cs, expression.cs, statement.cs, cs-parser.jay: + More tricky refactoring of implicit linq blocks. + +2010-05-25 Marek Safar + + * linq.cs, cs-parser.jay: Keep location for all linq clauses. + +2010-05-25 Marek Safar + + * context.cs, expression.cs, cs-parser.jay: Don't store current + block in This expression (it's too early for linq blocks). + +2010-05-21 Marek Safar + + * expression.cs: Use constrained prefix more broadly to avoid boxing. + +2010-05-20 Marek Safar + + A fix for bug #591149 + * nullable.cs: Don't double wrap same expression. + +2010-05-20 Marek Safar + + A fix for bug #569827 + * anonymous.cs: Any issued error in probing mode means no match. + +2010-05-20 Marek Safar + + * expression.cs: Search for base indexer using the closest match + rule. + +2010-05-20 Marek Safar + + A fix for bug #572071 + * method.cs: Set override constraints using unexpanded interface + list. + +2010-05-20 Marek Safar + + A fix for bug #572071 + * ecore.cs: Include secondary extension method lookup in probing + mode. + +2010-05-19 Marek Safar + + A fix for bug #515801 + * typespec.cs (MayBecomeEqualGenericTypes): Recursively check + type arguments. + +2010-05-19 Marek Safar + + A fix for bug #515801 + * pending.cs: Advance counter correctly. + +2010-05-19 Marek Safar + + A fix for bug #480139 + * method.cs, pending.cs: Indexer override uses base name. + +2010-05-19 Marek Safar + + A fix for bug #424064 + * generic.cs: Replace original with inflated type parameter on + failure. + +2010-05-19 Marek Safar + + A fix for bug #359733 + * parameter.cs: Extension attribute can be defined in each assembly. + +2010-05-18 Marek Safar + + A fix for bug #446507 + * method.cs: Only one method can implement an interface. + +2010-05-18 Marek Safar + + A fix for bug #594905 + * convert.cs, constant.cs, expression.cs, literal.cs, ecore.cs: + Typed null can be used as a source for expression methods. + +2010-05-18 Marek Safar + + A fix for bug #606551 + * namespace.cs: Using directive imports only types and not nested + namespaces. + +2010-05-17 Marek Safar + + * typespec.cs, expression.cs, statement.cs, ecore.cs, complete.cs, + delegate.cs: Member instance is resolved after member overload + definitely resolves static/instance property of member expression. + Fixes #545047, #358848, #456605, #460016, #603299 + +2010-05-12 Marek Safar + + A fix for bug #604981 + * generic.cs, decl.cs, anonymous.cs: Reset more type arguments + details for nested anonymous methods stories. + +2010-05-11 Marek Safar + + A fix for bug #604735 + * namespace.cs: Don't report namespace collision. + +2010-05-11 Marek Safar + + A fix for bug #604748 + * class.cs, typespec.cs: Search full imported attribute hierarchy + for AttributeUsage. + +2010-05-11 Marek Safar + + * namespace.cs: Ignore missing dependencies failure at + initialization. + +2010-05-11 Marek Safar + + A fix for bug #604640 + * namespace.cs: Don't resolve using constraints too early. + +2010-05-11 Marek Safar + + A fix for bug #604239 + * generic.cs: Copy partial type constraints to partial container. + +2010-05-10 Marek Safar + + A fix for bug #557210 + * import.cs: Relax underlying enum field rules. + +2010-05-10 Marek Safar + + A fix for bug #603476 + * property.cs: Implement IParametersMember for indexer accessors. + +2010-05-07 Marek Safar + + A fix for bug #601141 + * class.cs: Update all partial modifiers. + +2010-05-06 Marek Safar + + A fix for bug #601708 + * method.cs, membercache.cs: Destructors cannot be hidden. + +2010-05-06 Marek Safar + + A fix for bug #602551 + * class.cs: Resursive reference of type definition is allowed. + +2010-05-06 Marek Safar + + * anonymous.cs: Mutate cached storey instance types too. + +2010-05-06 Marek Safar + + A fix for bug #602443 + * convert.cs: Explicit enum conversion cannot involve user operators + +2010-05-05 Miguel de Icaza + + * class.cs (TypeContainer.DefineBaseTypes) + (TypeContainer.CheckRecursiveDefinition): check for the iface not + being null, as we could have failed resolution and crashed; + Fixes #442144 + + * cs-parser.jay: Productions to catch common mistakes when other + punctuation operators are used instead of comma. Fixes 571702 + +2010-05-05 Marek Safar + + * anonymous.cs: Mutate correct set of constraints. + +2010-05-05 Marek Safar + + A fix for bug #602842 + * expression.cs: Resolve all array bound arguments. + +2010-05-05 Marek Safar + + * import.cs: Don't import private fields. + +2010-04-30 Marek Safar + + Partially based on patch by + + * eval.cs, ecore.cs: Fixed eval show methods. + +2010-04-30 Marek Safar + + * generic.cs, delegate.cs: Implement output type inference of + methodgroup now when the specification was cleared at least little + bit. + +2010-04-29 Marek Safar + + A fix for bug #575611 + * class.cs: Fix recursive unmanaged recursice sruct check. + +2010-04-29 Marek Safar + + A fix for bug #479776 + * expression.cs: Implement typeof unbounded nested generic types. + +2010-04-29 Marek Safar + + A fix for bug #474953 + * class.cs: Fix valid recursive base type definition. + +2010-04-29 Marek Safar + + A fix for bug #421737 + * convert.cs, expression.cs: A boxing conversion exists from a + nullable-type to a reference type, if a boxing conversion exists + from the underlying non-nullable-value-type to the reference type. + +2010-04-29 Marek Safar + + A fix for bug #376875 + * import.cs: Import volatile modifier. + +2010-04-29 Marek Safar + + A fix for bug #372412 + * typespec.cs, expression.cs, codegen.cs: Emit readonly prefix for + generic arrays. + +2010-04-29 Marek Safar + + A fix for bug #568955 + * statements.cs: Handle recursive scope initializers. + +2010-04-28 Marek Safar + + A fix for bug #566511 + * anonymous.cs: Always get inflated version of hoisted variable + on generic type definition. + +2010-04-28 Marek Safar + + * import.cs, membercache.cs: Relax rules for valid properties. + +2010-04-28 Marek Safar + + * import.cs: Intern arrays used in generic arguments. + +2010-04-28 Marek Safar + + A fix for bug #600398 + * convert.cs: Actually use effective base type for the comparison. + +2010-04-28 Marek Safar + + A fix for bug #600326 + * ecore.cs: Pass arity to base member lookup. + +2010-04-28 Marek Safar + + A fix for bug #573385 + * expression.cs: MemberAccess is of generic type based on right + arity length only. + +2010-05-28 Marek Safar + + * cs-tokenizer.cs: Made tab size configurable. + +2010-05-27 Marek Safar + + * attribute.cs: Ensure Obsolete members are defined before doing + ctor look-up. + +2010-05-27 Marek Safar + + * visit.cs: Add DOM visitor skeleton. + + * *.cs: Updated. + +2010-05-27 Marek Safar + + * attribute.cs, codegen.cs: Drop COMPILER_ACCESS hack. + +2010-05-27 Marek Safar + + * *.cs: Major rewrite of compiler internals to better work with + unmodified System.Reflection.Emit. Some of the key changes are + - TypeSpec replaces reflection specific System.Type. + - All Type(TypeSpec) operations are now done in compiler therefore + no dependency on SRE to inflate generic members and types or to + query unclosed types. + - MemberCache is now the only and full hierarchical topology. + - Generic constraints are implemented properly. + - And as a bonus compilation is on average 30% faster. + +2010-04-15 Jb Evain + + * dmcs.exe.config: update the runtime version to .net 4.0 RTM. + +2010-04-12 Marek Safar + + * expression.cs, attribute.cs, parameter.cs: More attribute type + checks. + +2010-04-12 Marek Safar + + A fix for bug #593342 + + * generic.cs, parameter.cs, argument.cs, field.cs, property.cs, + decl.cs, roottypes.cs, constant.cs, nullable.cs, expression.cs, + method.cs, ecore.cs, class.cs, delegate.cs, attribute.cs, + codegen.cs: Add custom attribute encoder to deal with unfinished + types and easier corlib bootstrap from its own types. + +2010-03-26 Marek Safar + + * cs-parser.jay: Report invalid constraint types. + +2010-03-16 Jb Evain + + * Makefile: rename the net_2_1 profile to moonlight. + +2010-03-11 Marek Safar + + * statement.cs, cs-parser.jay: Use correct location for empty + statements. + +2010-03-11 Marek Safar + + * cs-parser.jay: Disable Location from expression. + + * generic.cs: Check constraints for overrides in the parser. + +2010-03-09 Marek Safar + + * cs-parser.jay (GetLocation): Use an expression when available. + +2010-03-04 Marek Safar + + A fix for bug #582579 + * ecore.cs (FieldExpr): Don't optimize cross reference loads. + +2010-03-04 Marek Safar + + A patch by kornelpal@gmail.com + + * dynamic.cs, anonymous.cs, rootcontext.cs, class.cs: Don't make + compiler generated classes sealed by default. Emit and close top + level compiler generated classes as well. + + * support.cs: Use RuntimeHelpers.GetHashCode. + +2010-03-03 Rolf Bjarne Kvinge + + * Makefile: We need to use the internal bootstrapping gmcs for + net_2_1_bootstrap too now. + +2010-03-02 Raja R Harinath + + * expression.cs (IndexerAccess.ResolveAccessor): Add CS1540 check. + +2010-03-02 Marek Safar + + * cs-tokenizer.cs: Missed few locations in previous fix. + +2010-03-02 Marek Safar + + * cs-tokenizer.cs, argument.cs, dynamic.cs, assign.cs, anonymous.cs, + nullable.cs, expression.cs, statement.cs, cs-parser.jay, cfold.cs: + Report correct location for operator errors. + +2010-03-02 Marek Safar + + * typemanager.cs (IsDynamicType): Don't check external types when + the attribute is not external. + +2010-02-24 Marek Safar + + A fix for bug #582579 + * decl.cs (IsExposedFromAssembly): Use PartialContainer for parent + modifiers. + +2010-02-24 Marek Safar + + A fix for bug #581804 + * ecore.cs: Fixed type comparison. + +2010-02-08 Miguel de Icaza + + * namespace.cs (CompletionGetTypesStartingWith): Do not include + private types in the completion results. + + * cs-parser.jay: Bubble completions after "from x in ?" and "from x + ... let ?" + +2010-02-17 Marek Safar + + * generic.cs, field.cs, decl.cs, cs-parser.jay: Simplify special + constraint parsing. + +2010-02-14 Miguel de Icaza + + * eval.cs: Do not do the report printer dance unless the user has + set the DescribeTypes feature. + +2010-02-10 Marek Safar + + * argument.cs, dynamic.cs, expression.cs: Track RC API changes. + +2010-02-08 Marek Safar + + A fix for bug #577029 + * anonymous.cs: Fixed TypeBuilder* check. + +2010-02-06 Miguel de Icaza + + * eval.cs (CompileBlock): Also undo if there are problems during + semantic analysis, fixes various cases where invalid C# code would + be reported, but the internal changes would not be undone. + +2010-02-03 Miguel de Icaza + + * driver.cs: Change the --fatal flag to allow a number to be + passed, this ignores the first N fatal errors. Useful to debug + errors that do not happen on the first hit. + + * cs-parser.jay (invocation_expression): accept both the + CLOSE_PARENS and COMPLETE_COMPLETION, this allows completions + inside an invocation. + + * driver.cs: Expose FatalErrors. + + * eval.cs: Initialize the printer's Fatal property from the + Driver's FatalError flag, this allows csharp --fatal to work + again. + + Add support for calling Describe (typeof (TYPE)) if the expression + entered is a TYPE. + +2010-02-02 Marek Safar + + A fix for bug #574991 + * rootcontext.cs, class.cs, driver.cs: Hide enhanced warnings behind + --lint. + +2010-02-02 Marek Safar + + A fix for bug #575986 + * expression.cs: Don't mutate typeof type definitions. + +2010-01-28 Marek Safar + + * decl.cs: Use only one set of modifiers. + +2010-01-26 Marek Safar + + A fix for bug #573329 + * eval.cs: Don't disable error reporting completely on silent mode. + +2010-01-25 Marek Safar + + A fix for bug #573312 + * constant.cs, expression.cs, ecore.cs: Emit correct offset for + pointer index of unknown size types greater than 2. + +2010-01-15 Marek Safar + + * *.cs: Use only 1 member kind enum. + +2010-01-15 Marek Safar + + * *.cs: Add event specification. + +2010-01-14 Marek Safar + + * membercache.cs: Extracted from decl.cs. + + * *.cs: Put more infrastructure in place. + +2010-01-13 Marek Safar + + * *.cs: Add property specification, unused yet. + +2010-01-13 Marek Safar + + * property.cs: Move all property based declarations into a new file. + +2010-01-13 Marek Safar + + * expression.cs (Conditional): Resolve reduced expression. + +2010-01-13 Marek Safar + + * *.cs: Introduced non-generic method specification. + +2010-01-07 Marek Safar + + * method.cs: Move all method based declarations into a new file. + +2010-01-07 Marek Safar + + * *.cs: Extract field specification. + +2009-12-17 Marek Safar + + * field.cs: Extracted from class.cs + +2009-12-15 Marek Safar + + * attribute.cs (GetFixedBuffer): Work on field definition only. + +2009-12-15 Marek Safar + + * *.cs: Clean up NET_4_0 conditional where possible. + +2009-12-14 Rodrigo Kumpera + + support.cs (DynamicType): Assembly property returns the assembly builder. + This is required due to how compiler context works in corlib. + +2009-12-14 Marek Safar + + A fix for bug #564376 + * assign.cs (LocalTemporary): Removed no longer needed special + by-ref handling. + +2009-12-11 Marek Safar + + * modifiers.cs, decl.cs, iterators.cs, const.cs, anonymous.cs, + class.cs, delegate.cs, cs-parser.jay, enum.cs: Turn modifiers into + enum for easier debugging. + +2009-12-10 Marek Safar + + * decl.cs, anonymous.cs, class.cs: Sealed Define it's now main entry + point. + + * parameter.cs, delegate.cs, dynamic.cs: Don't use builder methods + directly. + +2009-12-10 Marek Safar + + * cs-parser.jay, statement.cs: Handle parser error in code + completition. + +2009-12-10 Marek Safar + + * ecore.cs: Ignore base imported methods when they are already + in method bag. + + * eval.cs: Handle non-existent keys. + + * report.cs, driver.cs: Make fatal work with console printer only. + +2009-12-08 Rodrigo Kumpera + + * typemanager.cs (MakeGenericMethod): Fix stupid mistake. + +2009-12-08 Rodrigo Kumpera + + * typemanager.cs: Add MakeGenericMethod that checks if the method + is really the generic method definition. + + ecore.cs (MethodGroupExpr:IsApplicable): Use new TypeManager function + to inflate generic methods. + +2009-12-08 Marek Safar + + A fix for bug #561149 + * anonymous.cs: Use actual type parameters when checking for generic + method host. + +2009-12-08 Marek Safar + + A fix for bug #561369 + * expression.cs (DoNumericPromotion): Fixed typo. + +2009-12-08 Marek Safar + + *.cs: Moving to generics world. + + cs-parser.jay: Removed current_array_type. + +2009-12-07 Marek Safar + + *.cs: Moving to generics world. + +2009-12-04 Marek Safar + + *.cs: Moving to generics world (day 2). + +2009-12-03 Marek Safar + + *.cs: Moving to generics world. + +2009-12-02 Marek Safar + + * typemanager.cs, parameter.cs, class.cs, delegate.cs, attribute.cs: + Encode dynamic type attribute for elements where attributes cannot + be used. + +2009-12-01 Marek Safar + + argument.cs, assign.cs, expression.cs, cs-parser.jay: Named + arguments by ref. + +2009-12-01 Marek Safar + + A fix for bug #360455 + * class.cs: Never report a unused warning for generic events to + workaround wrong expression type. + +2009-11-30 Marek Safar + + A fix for bug #558305 + * decl.cs, class.cs: Check partial method definitions using correct + flag. + +2009-11-30 Marek Safar + + * argument.cs: Don't cache rarely used dynamic flag. + +2009-11-27 Marek Safar + + * cs-parser.jay: Use jay global stacks (saves over 3MB for corlib). + +2009-11-27 Marek Safar + + * ecore.cs (SimpleName): Removed no longer needed in_transit as + Resolve is now non-reentrant (saves ~0.6MB for corlib). + +2009-11-26 Marek Safar + + A fix for bug #545081 + * decl.cs: Check private nested types of nested types recursively. + +2009-11-26 Marek Safar + + A fix for bug #558305 + * location.cs: Ignore self referencing #line directive + +2009-11-26 Marek Safar + + A fix for bug #558292 + * class.cs: Allow single unsafe fixed buffer fields. + +2009-11-26 Marek Safar + + * expression: Optimize few more zero-based operations. + +2009-11-26 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Simplify literal parsing, also + avoids boxing of literal values. + +2009-11-26 Marek Safar + + * cs-tokenizer.cs, argument.cs, eval.cs, linq.cs, decl.cs, + expression.cs, ecore.cs, location.cs, cs-parser.jay, attribute.cs, + codegen.cs: LocatedToken redesing to avoid excessive allocation and + boxing (saves ~7MB for corlib). Also fixes presise token location. + +2009-11-25 Marek Safar + + * ecore.cs, cs-parser.jay: Keep parser structures local. Share + common data buckers. + +2009-11-24 Marek Safar + + * expression.cs: Lower static array initializer barrier. + + * support.cs, driver.cs: Share reader buffer. + +2009-11-23 Marek Safar + + * cs-tokenizer.cs, support.cs: Some tokenizer optimizations. + +2009-11-23 Marek Safar + + * cs-tokenizer.cs, support.cs: Use Dictionary instead of Hashtable, + cleanup some obsolete code. + +2009-11-20 Marek Safar + + * context.cs, expression.cs, ecore.cs, complete.cs: Cleaned up + Expression.Resolve. + +2009-11-20 Marek Safar + + * *.cs: Resolved expressions are never resolved again, this helps to + uncover some not easy to find bugs and improve the performance. + +2009-11-19 Marek Safar + + * *.cs: Made constant expressions fully compatible with any other + expression. + +2009-11-19 Marek Safar + + * *.cs: DoResolve is a worker method and has to be protected. + +2009-11-18 Marek Safar + + * *.cs: More context specific handling. + +2009-11-17 Marek Safar + + * *.cs: More context specific handling. + +2009-11-16 Marek Safar + + * dynamic.cs, class.cs: Removed few fixed user types conversions. + + * symbolwriter.cs: Uses public ILOffset. + +2009-11-13 Marek Safar + + A fix for bug #553650 + * generic.cs: Another missing TypeToCoreType, still too many to fix. + +2009-11-13 Marek Safar + + A fix for bug #555170 + + * class.cs, delegate.cs, enum.cs: Constants have to be available + for parameters resolve. + +2009-11-12 Marek Safar + + * typemanager.cs, argument.cs, support.cs, delegate.cs: Dynamic + arrays. + +2009-11-12 Marek Safar + + * argument.cs, context.cs, expression.cs, ecore.cs: Dynamic binding + with a statically known candidate set. + +2009-11-11 Scott Peterson + + * generic.cs: Made type inflation for generic constraint checks + recursive. This fixes BGO #553655. + +2009-11-11 Marek Safar + + * dynamic.cs, decl.cs, expression.cs, ecore.cs: More dynamic type + checks. + +2009-11-10 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, argument.cs, dynamic.cs, + linq.cs, rootcontext.cs, ecore.cs, class.cs, delegate.cs, + attribute.cs: Add some dynamic error checking. + +2009-11-07 Marek Safar + + A fix for bug #553465 + + * expression.cs: Fixed mixed version of expression tree anonymous + type. + +2009-11-06 Marek Safar + + A fix for bug #553031 + + * linq.cs, expression.cs, class.cs, cs-parser.jay: Initialize + expression tree version of anonymous type with members declaration. + +2009-11-05 Marek Safar + + * parameter.cs: Handle nullable parameter default expression. + + * argument.cs, dynamic.cs, expression.cs, support.cs, ecore.cs, + class.cs, attribute.cs: Check for wrong dynamic arguments. + +2009-11-05 Marek Safar + + * statement.cs: Dynamic statements. + +2009-11-04 Marek Safar + + * dynamic.cs, assign.cs, context.cs, expression.cs, ecore.cs: + Compound assignments over dynamic type. + +2009-11-03 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, delegate.cs: Dynamic + constructor arguments. + +2009-10-30 Marek Safar + + * dynamic.cs, convert.cs, assign.cs, constant.cs, expression.cs, + codegen.cs: Unary mutator on dynamic member access expression. + +2009-10-29 Marek Safar + + A fix for bug #550580 + * convert.cs: Don't eliminate explicit precission casts. + +2009-10-28 Marek Safar + + A fix for bug #550404 + + * parameter.cs, iterators.cs, context.cs, anonymous.cs, + expression.cs, statement.cs, ecore.cs: Quote any nested expression + tree. + +2009-10-27 Marek Safar + + * constant.cs, nullable.cs: Create nullable-null as LiftedNull + constant. + + * class.cs: Allow nullable binary user operators. + +2009-10-26 Marek Safar + + * expression.cs: Move binary expression optimization at the end of + resolve. + +2009-10-23 Marek Safar + + * constant.cs, nullable.cs, expression.cs, literal.cs, cfold.cs: + Separate NullConstant from NullLiteral. + +2009-10-23 Marek Safar + + * typemanager.cs, eval.cs, decl.cs, roottypes.cs, context.cs, + anonymous.cs, expression.cs, rootcontext.cs, ecore.cs, class.cs, + flowanalysis.cs, cs-parser.jay, driver.cs, codegen.cs: Split + ModuleContainer. Add common unclosed member check routine. + +2009-10-22 Marek Safar + + * argument.cs: Use literal flag for real literals only. + + * dynamic.cs: Use correct return type for custom delegates. + +2009-10-22 Marek Safar + + * dynamic.cs, expression.cs: Pass logical binary flag to dynamic + resolver. + +2009-10-22 Marek Safar + + * dynamic.cs, ecore.cs: Dynamic invocation with void return type. + +2009-10-21 Marek Safar + + * dynamic.cs, convert.cs, expression.cs, ecore.cs: Wrap array index + conversion. + +2009-10-21 Marek Safar + + * typemanager.cs, dynamic.cs, expression.cs: Don't resolve runtime + binder flags. + +2009-10-20 Marek Safar + + * argument.cs, dynamic.cs, expression.cs: Latest API update. + +2009-10-19 Marek Safar + + * typemanager.cs, expression.cs: Dynamic array initializer. + +2009-10-16 Marek Safar + + * typemanager.cs, rootcontext.cs: Clear -nostdlib flag when object + is imported. + +2009-10-16 Marek Safar + + A fix for bug #493523, #507067 + * convert.cs, nullable.cs, expression.cs: Do implicit and explicit + standard nullable conversion using underlying standard conversion + and not full conversion. + +2009-10-15 Marek Safar + + * dynamic.cs, expression.cs, ecore.cs, delegate.cs: Check return + type in VerifyArgumentsCompat. + +2009-10-15 Marek Safar + + * nullable.cs, expression.cs, statement.cs, namespace.cs, ecore.cs: + Reject variable used with type arguments. + +2009-10-14 Marek Safar + + * argument.cs, dynamic.cs, assign.cs, expression.cs, ecore.cs: + Implement dynamic expressions assignment. + +2009-10-14 Marek Safar + + * expression.cs: Build underlying expression when resolving unary + mutators. + +2009-10-14 Marek Safar + + * expression.cs: Emit enum array initializer using binary blob. + +2009-10-08 Marek Safar + + * typemanager.cs, constant.cs: Optimize decimal constants which fit + to long range. + +2009-10-07 Marek Safar + + * typemanager.cs: Reset object_type. + + * assign: Made SimpleAssign public. + +2009-10-06 Marek Safar + + * typemanager.cs, decl.cs, namespace.cs, ecore.cs, class.cs: Pass + invocation assembly to IsThisOrFriendAssembly. + +2009-10-05 Marek Safar + + * expression.cs: Equality comparison of generic parameter with + class constraint. + +2009-10-05 Marek Safar + + A fix for bug #543570 + * generic.cs: Import predefined constraints correctly. + +2009-10-02 Marek Safar + + * ecore.cs: Don't crash on overloads with optional paremeters where + arguments count overflows. + + * parameter.cs: Import optional parameter constants using optional + value type. + +2009-10-01 Marek Safar + + * Makefile: Default is gmcs compiler. + +2009-10-01 Marek Safar + + * cs-parser.jay: Fixed few NRE. + +2009-10-01 Marek Safar + + * cs-parser.jay, driver.cs: Expose parser exception in verbose mode. + +2009-09-30 Marek Safar + + * linq.cs, convert.cs, assign.cs, expression.cs, ecore.cs: Add + ShimExpression, ImplicitCast. + +2009-09-30 Marek Safar + + A fix for bug #542959 + * delegate.cs: Emit correct delegate instance variable when there + are static and non-static overloads. + +2009-09-29 Marek Safar + + * dynamic.cs, linq.cs, anonymous.cs, expression.cs, statement.cs, + ecore.cs, cs-parser.jay: Unary expression dynamic compiler. + +2009-09-28 Marek Safar + + A fix for bug #542487 + * ecore.cs: Resolve extension methods hidden by properties. + +2009-09-25 Marek Safar + + * expression.cs, ecore.cs: More dynamic binary expressions. + +2009-09-22 Marek Safar + + * nullable.cs, expression.cs: Fixed null lifted conversion for + bitwise enum operations. + +2009-09-22 Marek Safar + + * convert.cs, ecore.cs: Fixed explicit unsafe coversion of long + values in checked context. + +2009-09-22 Marek Safar + + * expression.cs, ecore.cs: Fixed array index constant conversion. + +2009-09-20 Miguel de Icaza + + * expression.cs: Do not crash when MemberLookup returns something + that is not a MemberExpr here. Report error 582 instead. + + Fixes #499988. + +2009-09-18 Marek Safar + + * decl.cs, class.cs: Check protected property accessors. + +2009-09-18 Marek Safar + + * dynamic.cs, assign.cs: Dynamic compound assignment. + +2009-09-17 Marek Safar + + * expression.cs: Fixed compound assignment explicit conversion. + +2009-09-17 Marek Safar + + * expression.cs, ecore.cs: Cannot infer variables from method group. + +2009-09-16 Marek Safar + + * argument.cs, dynamic.cs, convert.cs, context.cs, anonymous.cs, + constant.cs, nullable.cs, expression.cs, literal.cs, ecore.cs, + codegen.cs: Dynamic binary operations scaffolding. + +2009-09-15 Marek Safar + + * expression.cs: Fixes nullable promotion for enum type variables. + +2009-09-11 Marek Safar + + * driver.cs, dynamic.cs: Reset more static variables. + +2009-09-11 Marek Safar + + * dynamic.cs, expression.cs, rootcontext.cs, namespace.cs, ecore.cs, + driver.cs: Introduced Expression::MakeExpression. + +2009-09-11 Marek Safar + + * eval.cs: Exposed MessageOutput instead of cleaning up eval API. + +2009-09-09 Marek Safar + + * eval.cs, report.cs: Use Console.Out for all eval error or warning + output. + +2009-09-09 Marek Safar + + A fix for bug #518707 + * expression.cs (Is): Optimize only generic parameter type + expression probing value type generic parameter. + +2009-09-09 Marek Safar + + A fix for bug #532571 + * ecore.cs: Check for simple name type arguments used with + non-generic type. + +2009-09-08 Marek Safar + + A fix for bug #497421 + * generic.cs (CheckConstraint): Don't use buildin types to check for + parameterless constructor. + +2009-09-08 Marek Safar + + A fix for bug #537402 + * generic.cs (CheckConstraint): Correctly inflate generic type + arguments when checking generic method. + +2009-09-08 Marek Safar + + A fix for bug #536463 + * decl.cs (AddToContainer): Don't report collision between explicit + and parameterless non-explicit members. + +2009-09-08 Marek Safar + + * eval.cs: Reset more static stuff. + +2009-09-07 Marek Safar + + A fix for bug #324625 + * expression.cs, ecore.cs: Create nested generic type expression + using declaring and not current type. + +2009-09-07 Marek Safar + + * *.cs: Changed Report class to accept various output printers and + be an instance class. An expression resolver can now use different + message reporter for each call and Report.Error can safely throw + an exception. Part of ongoing work to turn mcs into proper library. + +2009-09-04 Marek Safar + + * statement.cs, ecore.cs: Removed error reporting from emit code. + +2009-09-04 Marek Safar + + * cs-parser.jay, parameter.cs: Moved parser check out of constructor + +2009-09-03 Marek Safar + + * anonymous.cs, expression.cs, statement.cs, cs-parser.jay: Moved + parser checks out of constructors. + +2009-09-02 Marek Safar + + * expression.cs, statement.cs, ecore.cs: Use common Report.Error. + +2009-09-02 Marek Safar + + A fix for bug #535448 + * anonymous.cs, class.cs: Copy return label between all contexts. + +2009-09-02 Marek Safar + + A fix for bug #535395 + * namespace.cs: Resolve context can be null. + +2009-08-25 Marek Safar + + A fix for bug #533912 + * generic.cs: Use correct context for constraints resolving. + +2009-08-25 Marek Safar + + A fix for bug #532630 + * driver.cs: Trim conditional symbols. + +2009-08-25 Marek Safar + + * context.cs: New file. + + * *.exe.sources, *.csproj: Updated. + +2009-08-25 Marek Safar + + * generic.cs, parameter.cs, decl.cs, statement.cs, namespace.cs, + class.cs, generic-mcs.cs, codegen.cs: Add GetSignatureForError to + IMembercontext, some small cleanups. + +2009-08-24 Marek Safar + + * *.cs: Split ResolveContext and EmitContext. + +2009-08-24 Marek Safar + + * *.cs: Only ResolveContext implements IMemberContext. + +2009-08-21 Marek Safar + + * *.cs: Renamed IResolveContext to IMemberContext. + +2009-08-21 Marek Safar + + * *.cs: Detached ResolveContext from EmitContext. + +2009-08-21 Marek Safar + + * codegen.cs: Moved flow-analysis to BlockContext. + +2009-08-21 Marek Safar + + * *.cs: Detached BlockContext from EmitContext. + +2009-08-20 Gonzalo Paniagua Javier + + * statement.cs: avoid nullref when the return value of GetEnumerator() + does not contain any MoveNext() method. + +2009-08-19 Marek Safar + + * *.cs: Removed IResolveContext::GenericDeclContainer. + +2009-08-19 Marek Safar + + * class.cs, delegate.cs: Changed Delegate to be TypeContainer based. + +2009-08-19 Marek Safar + + * generic.cs, iterators.cs, expression.cs, statement.cs, ecore.cs, + cs-parser.jay, attribute.cs, codegen.cs: Better error reports. + +2009-08-18 Marek Safar + + * *.cs: Removed boolean fields from EmitContext. + +2009-08-18 Marek Safar + + * *.cs: Add IResolveContext::IsStatic. + +2009-08-18 Marek Safar + + * *.cs: Moved TopBlock's methods from EmitContext to TopBlock. + +2009-08-17 Marek Safar + + * *.cs: Removed DeclContainer from EmitContext. + +2009-08-17 Marek Safar + + * *.cs: Add IResolveContext::CurrentTypeParameters. + +2009-08-14 Marek Safar + + * *.cs: Removed TypeContainer and ContainerType from EmitContext. + +2009-08-14 Marek Safar + + * decl.cs, expression.cs, namespace.cs, ecore.cs, class.cs, + codegen.cs: Add IResolveContext::LookupExtensionMethod. + +2009-08-13 Marek Safar + + * decl.cs: Look in PartialContainer for parent type parameters. + +2009-08-13 Marek Safar + + * decl.cs, namespace.cs, ecore.cs, class.cs, attribute.cs, + codegen.cs: Add IResolveContext::LookupTypeParameter. + +2009-08-13 Marek Safar + + * lambda.cs, expression.cs, statement.cs, namespace.cs, ecore.cs: + Moved resolved logic from Emit to Resolve. + +2009-08-13 Marek Safar + + * parameter.cs, decl.cs, roottypes.cs, class.cs, attribute.cs, + codegen.cs: Reworked atttributes handling of ResolveContext. + +2009-08-12 Marek Safar + + * decl.cs, ecore.cs, class.cs, attribute.cs, codegen.cs: Pushed + LookupNamespaceOrType to ResolveContext. + +2009-08-12 Marek Safar + + * typemanager.cs, decl.cs, expression.cs, namespace.cs, ecore.cs, + class.cs: Removed unused parameters and methods. + +2009-08-11 Marek Safar + + * generic.cs, lambda.cs, anonymous.cs, statement.cs, generic-mcs.cs, + codegen.cs: Finding the best common type of a set of expressions for + lambda statements. + +2009-08-07 Marek Safar + + * dynamic.cs, expression.cs: More dynamic conversions. + +2009-08-06 Miguel de Icaza + + * generic.cs: This loop was incorrect, it was increment ii, but + checking for `i'. This was a change introduced to fix #327497, + now we fix #424012. + + * class.cs: Catch another case for cs0533 error, fixes #324782. + +2009-08-06 Rodrigo Kumpera + + * typemanager.cs (GetGenericArguments): SRE returns null for + generic methods on type builder instances if they are not generic + themselves. For example, for Foo::Bar() it returns null, but + not for Foo::Bar<>() or Foo::Bar(). + +2009-08-05 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, ecore.cs, class.cs, + delegate.cs: Work on dynamic binding. + +2009-08-04 Marek Safar + + A second fix for bug #525342 + * class.cs: Attach partial method attributes to method + implementation. + +2009-08-03 Marek Safar + + * typemanager.cs, parameter.cs, support.cs, class.cs: Dynamic type + restrictions. + + * rootcontext.cs: Default to langversion v4. + +2009-08-03 Marek Safar + + * pending.cs: Check return type before member info is set. + +2009-08-03 Marek Safar + + * anonymous.cs: Fully initialize generic hoisted field expression. + +2009-08-02 Miguel de Icaza + + * cs-parser.jay: Flag variables declared on the interactive shell + as used to prevent the 168 warning about local variable not being + used. + +2009-07-31 Marek Safar + + * parameter.cs, dynamic.cs, support.cs, class.cs, delegate.cs, + attribute.cs: Emit dynamic export attribute. + +2009-07-30 Marek Safar + + * expression.cs: More verifier work. + +2009-07-29 Marek Safar + + * nullable.cs: Fixed SRE crash during corlib compilation. + +2009-07-29 Marek Safar + + * generic.cs, typemanager.cs, decl.cs, iterators.cs, convert.cs, + nullable.cs, expression.cs, ecore.cs, class.cs, attribute.cs: + More TypeManager.TypeToCoreType needed. + +2009-07-29 Marek Safar + + * anonymous.cs: Update after recent SRE fixes. + +2009-07-28 Marek Safar + + * typemanager.cs, expression.cs, ecore.cs, delegate.cs: Use correct + version of GetFieldHandle for fields of generic types. + +2009-07-27 Marek Safar + + * typemanager.cs, argument.cs, convert.cs, assign.cs, expression.cs, + ecore.cs: Add TypeManager.IsDynamicType, + PredefinedAttributes.Dynamic. + +2009-07-27 Marek Safar + + A fix for bug #415375 + * expression.cs: Fixed object and reference type parameter + comparison. + +2009-07-27 Marek Safar + + A fix for bug #525342 + * class.cs: Attach partial method attributes to method + implementation. + +2009-07-24 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, class.cs, attribute.cs: + Dynamic arguments. + +2009-07-24 Marek Safar + + * anonymous.cs (MutateField): Add imported types handling. + +2009-07-23 Marek Safar + + * expression.cs, delegate.cs: Moved arguments resolve into their + counterparts expressions. Removed argument resolve from + CollectionElementInitializer. + +2009-07-23 Marek Safar + + A fix for bug #523683 + * convert.cs, delegate.cs: Use common overload mechanism for method + group conversion check. + +2009-07-22 Marek Safar + + A fix for bug #523899 + * generics.cs: Exact type inference with other bound types. + +2009-07-22 Raja R Harinath + + Don't complain when the same type is implemented by the output + assembly as well as multiple referenced assemblies + * namespace.cs (RootNamespace.LookupTypeReflection): Add + 'must_be_unique' flag. + (GlobalRootNamespace): Update to changes. + (Namespace.LookupType): Pass 'must_be_unique' only when we don't + already have a type in hand. + +2009-07-22 Marek Safar + + * expression.cs: More verifier instrumentation. + + * statement.cs: Do proper throw expression conversion. + +2009-07-22 Marek Safar + + A fix for bug #522789 + * expression.cs: Mutate invocation return type. + +2009-07-16 Marek Safar + + * anonymous.cs: Split assignable and readonly generated variable + references. + +2009-07-16 Marek Safar + + A fix for bug #521671 + * statement.cs: Fixed crash when checking missing type. + +2009-07-16 Marek Safar + + * typemanager.cs, generic.cs, argument.cs, linq.cs, convert.cs, + assign.cs, expression.cs, statement.cs, support.cs, ecore.cs, + class.cs, driver.cs: Work on dynamic binding. + + * dynamic.cs: New file. + + * *.sources, *.proj: Updated. + +2009-07-15 Marek Safar + + * expression.cs (Conditional): Avoid double Resolve. + +2009-07-13 Marcus Griep + + * ecore.cs: Fix obscure bug with resolving members of interfaces + that hide parent interface members. Fixes bug #444388 and corrects + bug #323096 + +2009-07-13 Marek Safar + + * expression.cs (LocalVariableReference): Bounce resolve. + +2009-07-10 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, convert.cs, anonymous.cs, + expression.cs, literal.cs, ecore.cs, complete.cs: Moved internal + types to new class. + + * support.cs: New dynamic type wrapper. + +2009-07-08 Marek Safar + + * ecore.cs, cs-parser.jay: Better error reporting for implicitly + typed local variable. + +2009-07-06 Marek Safar + + A fix for bug #519005 + * anonymous.cs: Use null_type as no return type placeholder. + +2009-07-02 Marek Safar + + * generic.cs: Handle type inference of identical type parameters + with different bounds. + +2009-07-01 Marek Safar + + * expression.cs, class.cs: Events variance. + + * cs-parser.jay: Interface events error messages. + +2009-07-01 Marek Safar + + * generic.cs, argument.cs: Updated type inference logic to C# 4.0. + +2009-06-29 Marek Safar + + * parameter.cs, convert.cs, expression.cs, class.cs: Default + parameter expression can be value-type New. + + * cs-parser.jay: Clean up too many parameter modifier boolean flags. + +2009-06-26 Marek Safar + + * generic.cs, argument.cs, expression.cs, ecore.cs, cs-parser.jay: + Implemented C# 4.0 named arguments. + +2009-06-24 Marek Safar + + * typemanager.cs, parameter.cs, iterators.cs, convert.cs, + expression.cs, ecore.cs, delegate.cs: Removed unnecessary ArgList + parameter modifier. Also fixes bug #515497. + +2009-06-24 Marek Safar + + * *.cs: Replaced ArrayList with Arguments in need of a nonsequential + arguments expression to be implemented. + + *.sources: Add argument.cs + +2009-06-23 Marek Safar + + * parameter.cs: Moved GetParameterIndexByName to base class. + + * expression.cs, statement.cs, ecore.cs, delegate.cs: Removed + unused AType. Use argument's version of GetExpressionTree. + +2009-06-22 Marek Safar + + * expression.cs, cs-parser.jay, attribute.cs, codegen.cs: Named + arguments grammar. + +2009-06-17 Marek Safar + + A fix for bug #514096 + * class.cs: Allow IntPtr/UIntPtr fields to be volatile. + +2009-06-17 Marek Safar + + * expression.cs: The first multi-dimensional array nested array + initializers was not checked. + + * statement.cs (Switch): Fixed error message to reflect 2.0 changes. + +2009-06-17 Marek Safar + + A fix for bug #513400 + * nullable.cs (EmitEquality): Operands emit could be simplified for + built-in types when we now emit user operators differently. + +2009-06-16 Marek Safar + + * ecore.cs: Report inaccessible delegate methods correctly. + +2009-06-16 Marek Safar + + * parameter.cs, expression.cs, ecore.cs, class.cs, delegate.cs, + cs-parser.jay: Implemented C# 4.0 optional parameters. + +2009-06-16 Marek Safar + + * driver.cs: Removed broken DefineManifestResource. + +2009-06-16 Raja R Harinath + + * Makefile [net_2_0_bootstrap]: Don't explicitly mention net_1_1. + Use $(BOOTSTRAP_PROFILE) instead. + +2009-06-12 Jb Evain + + * rootcontext.cs: add a Platform field. + * driver.cs: handle /platform. + * codegen.cs: pass the proper flags according to + the platform when saving the assembly. + +2009-06-11 Marek Safar + + * parameter.cs, const.cs, report.cs, cs-parser.jay, attribute.cs: + Add optional parameters grammar. + +2009-06-10 Marek Safar + + * eval.cs, anonymous.cs, report.cs, rootcontext.cs, cs-parser.jay, + driver.cs: Split lang version and metadata version. + +2009-06-10 Marek Safar + + * decl.cs: Better overload ctor collision error message. + +2009-06-05 Jb Evain + + * driver.cs (EmbededResource): avoid using an internal method + in gmcs to embed manifest resources. + +2009-06-04 Sebastien Pouliot + + * generic.cs, parameter.cs: Avoid using 'var' so we can bootstrap + the compiler from older mono versions (like moon's bots) + +2009-06-04 Marek Safar + + * namespace.cs (LookupTypeReflection): Ignore collisions between + forwarded types. + +2009-06-04 Marek Safar + + * codegen.cs: Enabled generic type forwarders. + +2009-06-04 Marek Safar + + * dmcs.*: Add another version of SRE compiler. + +2009-06-03 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, convert.cs, + generic-mcs.cs: Fixed variant type conversions. + +2009-06-02 Marek Safar + + A fix for bug #507863 + * codegen.cs: Fixes a crash on invalid string value attribute. + +2009-06-01 Marek Safar + + A fix for bug #508334 + * typemanager.cs, parameter.cs, convert.cs, expression.cs, ecore.cs, + cs-parser.jay: Fully import __arglist modifier. + +2009-05-29 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, ecore.cs, class.cs, + delegate.cs, generic-mcs.cs: Rewrote type variance checks to + actually work with closed generic types. + +2009-05-27 Alan McGovern + + * class.cs, decl.cs, delegate.cs, parameter.cs: + Fix the build by replacing the use of 'var' with the actual type. + +2009-05-27 Marek Safar + + * generic.cs, parameter.cs, decl.cs, ecore.cs, class.cs, delegate.cs + cs-parser.jay, generic-mcs.cs: Report wrong variant types + declarations. + + * driver.cs, rootcontext.cs, report.cs: Add 3.0 language version + filter. + +2009-05-26 Rodrigo Kumpera + Marek Safar + + A fix for bug #377509 + * parameter.cs: Use predefined and not empty name for implicit + setters. + +2009-05-21 Marek Safar + + * class.cs: Don't report wrong warnings for event fields. + +2009-05-21 Marek Safar + + A fix for bug #504667 + * class.cs: Check for static class using parent container instead of + parent type. + +2009-05-08 Marek Safar + + A fix for bug #496922 + * expression.cs: Always use temporary variable when using object + initializer. + +2009-04-28 Marek Safar + + A fix for bug #495112 + * class.cs (IsUnmanagedType): Handle recursive unmanaged types using + local cache. + +2009-04-27 Miguel de Icaza + + * driver.cs: Add a flag to work as a replacement for CSC in VS. + +2009-04-24 Miguel de Icaza + + * complete.cs: No idea how gonzalo got a null in the list, but + avoid crashing. + +2009-04-24 Miguel de Icaza + + * complete.cs (CompletionElementInitializer): New completion class + to support completing inside a C# 3 element initializer, so this + allows completion for Silverlight situations where it is very + common to do: + + new TextBlock () { Fo + + (CompletionSimpleName): Expose the prefix that was + passed to the simple name. + + * cs-parser.jay (object_or_collection_initializer): Add support + for element_initializers. + + * expression.cs (CollectionOrObjectInitializers.DoResolve): + special case completion expressions as this method aggressively + collects data before it operates, and errors were being thrown + earlier than we were able to complete. + +2009-04-23 Miguel de Icaza + + * eval.cs: Make getcompletions silent and enable debugging output + if the -v option is passed. + + * namespace.cs (NamespaceEntry.CompletionGetTypesStartingWith): + Consider looking up the namespace that matches the prefix being + used. + + This is part of the support for allowing completions like: + `System.Co' to complete to System.Console. + + * complete.cs (CompletionSimpleName.AppendResults): Make this + routine reusable. + +2009-04-21 Raja R Harinath + + * cs-parser.jay (GetTokenName): Mark GENERATE_COMPLETION and + COMPLETE_COMPLETION as internal. + +2009-04-17 Miguel de Icaza + + * complete.cs: Include namespace resolution in simple names as + well as global types and types in the using scope in the + resolution. + + * namespace.cs: Supporting infrastrcture to provide completions + based on the current using scope. + + * eval.cs: Introduce an entry point that allows for initialization + to return a list of the files passed on the command line. + +2009-04-14 Marek Safar + + A fix for bug #494243 + * report.cs (SymbolRelatedToPreviousError): Fixed NRE. + +2009-04-13 Marek Safar + + A fix for bug #493887 + * statement.cs: Don't skip string multi-section with default or + null label when populating string hashtable. + +2009-04-06 Marek Safar + + A fix for bug #492329 + * expression.cs (New): Load variable when assigning type parameter + to ref variable. + +2009-04-06 Marek Safar + + A fix for bug #488960 + * decl.cs: Compare MVAR types using non-null values. + +2009-03-27 Marek Safar + + * typemanager.cs, expression.cs: Removed unused nullable checks. + +2009-03-27 Marek Safar + + * *.cs: Removed some gmcs conditionals. + +2009-03-26 Marek Safar + + * generic.cs, support.cs: Moved generics stuff out of support.cs + +2009-03-24 Marek Safar + + * ecore.cs, expression.cs: Use queried type for MethodGroupExpr + DeclaringType. + +2009-03-23 Marek Safar + + * attribute.cs: Consider all members for error reporting when + checking named arguments. + +2009-03-23 Marek Safar + + A fix for bug #487625 + * namespace.cs: Use a warning for all predefined type conflicts. + +2009-03-23 Marek Safar + + A fix for bug #485706 + * statement.cs: Explicitly type catch type argument to pass verifier + check. + +2009-03-22 Miguel de Icaza + + Initial support to provide code completion facilities to consumers + of the evaluator API. + + * cs-tokenizer.cs (CompleteOnEOF): this new property is used to + support the completion engine. When we reach the end of the + input stream instead of returning EOF, when this flag is true the + tokenizer instead produces: + + One GENERATE_COMPLETION token: this token then must be + handled in the grammar at every point where the user + would likely request a completion. + + As many COMPLETE_COMPLETION tokens as necessary. These + tokens are generated to assist the parser in unwinding and + producing a valid parse tree. + + The parser rules do not have to be perfect, the parser needs to be + augmented with judicious use of GENERATE_COMPLETION tokens to + improve the areas where we can provide completion and the parser + needs to add support for COMPLETE_COMPLETION tokens in productions + to make them work. + + It is common to not have enough support for COMPLETE_COMPLETION + under certain rules and that even if we generated the + GENERATE_COMPLETION token that the resulting tree will be invalid + due to the missing rules that support COMPLETE_COMPLETION. + + The final EOF token is produced by having the parser notify the + tokenizer when it reaches the root production that the next token + should be EOF. + + * support.cs (CompletionResult): New Exception. This exception + is thrown to return the completion results when one of the special + completion expressions is reached. + + This exception is thrown by the completing ExpressionStatements + classes that live in complete.cs + + * complete.cs (CompletingExpression): a new base class for + completing expressions. This derives from the + ExpressionStatement class and not from Expression as it allows + completion to happen not only where expressions are expected in + the grammar, but also where statements are expected. + + (CompletionSimpleName): A new class used to provide completions + for SimpleNames. This currently only resolves to local + variables from the evaluator context (GetVars call). + + (CompletionMemberAccess): Implements support for completing member + access patterns. + + * cs-parser.jay: Add support for completion in a few places. + + * eval.cs (GetCompletions): New public API for the evaluator that + returns a list of possible completions given the input. The + return value is an array of completions + + * anonymous.cs (Compatible): If the exception thrown from the + resolved expression is a CompletionResult exception let that one + through instead of printing a diagnostic error in the try/catch. +< +2009-03-22 Miguel de Icaza + + * + + * driver.cs (Main): Use Environment.Exit to quit quickly and + prevent the compiler from doing the usual wait for helper thread + to terminate. + + This is to prevent a slowdown that was reported by Gonzalo on + ASP.NET + +2009-03-19 Marek Safar + + * ecore.cs: Load build-in types directly instead of accessing + an internal field. + +2009-03-18 Marek Safar + + * ecore.cs: Always use unbox.any when available. + +2009-03-18 Marek Safar + + * class.cs: Always set TypeAttributes.BeforeFieldInit conditionally. + +2009-03-17 Marek Safar + + * generic.cs: Removed obsolete version of type inference. + +2009-03-16 Marek Safar + + * typemanager.cs, decl.cs, roottypes.cs, anonymous.cs, nullable.cs, + expression.cs, rootcontext.cs, namespace.cs, ecore.cs, class.cs, + delegate.cs, flowanalysis.cs, cs-parser.jay, driver.cs, + attribute.cs, codegen.cs: Changed RootTypes to be ModuleContainer. + +2009-03-11 Marek Safar + + A fix for bug #482996 + * anonymous.cs: Make sure we are not infering return type when + checking type compatibility. + +2009-03-11 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, decl.cs, const.cs, + rootcontext.cs, namespace.cs, class.cs, delegate.cs, driver.cs, + generic-mcs.cs, attribute.cs, codegen.cs: Maintain predefined + attributes in their own structure. Needed when accessing their + properties before they are resolved. + +2009-03-09 Marek Safar + + * cs-tokenizer.cs: Optimized GetKeyword using an array instead of + hashtable (~10x faster). + + * driver.cs: Removed wrong Reset. + +2009-03-08 Marek Safar + + * class.cs: Use correct common base type for unmanaged delayed + check. + + * rootcontext.cs: Wrap unhandled exception. + +2009-03-06 Raja R Harinath + + Make SeekableStreamReader self-tuning and arbitrarily seekable + * support.cs (SeekableStreamReader.ResetStream): New. Allocates + the buffer. + (SeekableStreamReader.Position.set): Use it. Simplify logic + which, as a side-effect, makes it arbitrarily-seekable. Tune the + buffer size when the stream needs to be re-read from the beginning. + +2009-03-05 Marek Safar + + A fix for bug #480100 + * parameter.cs: A parameter is not hoisted when used directly as ET. + +2009-03-04 Marek Safar + + * statement.cs: Fixed an issue when using variable is of interface + type. + +2009-03-03 Marek Safar + + A fix for bug #480319 + * report.cs, driver.cs: Support -warnaserror-: option. + +2009-03-03 Marek Safar + + A fix for bug #480867 + * typemanager.cs, expression.cs, ecore.cs: Changed method group + expression to have no valid type. + +2009-03-03 Marek Safar + + A fix for bug #481258 + * class.cs: Set extension method flag in partial container. + +2009-03-03 Marek Safar + + * statement.cs, typemanager.cs: Use expression for StringEmitter. + + * attribute.cs: Add sanity check. + +2009-02-27 Marek Safar + + * class.cs: Add external constructor error. + +2009-02-26 Marek Safar + + A fix for bug #475354 + * convert.cs, nullable.cs, expression.cs, statement.cs: Emit + correctly user defined nullable equality operators. + +2009-02-25 Marek Safar + + A fix for bug #479532 + * expression.cs: Implement NewInitialize::AddressOf. + +2009-02-25 Marek Safar + + A fix for bug #413633 + * expression.cs: Iterate all base class-constraint types. + +2009-02-24 Marek Safar + + A fix for bug #479209 + * literal.cs: Mutate null underlying type. + +2009-02-24 Marek Safar + + A fix for bug #476295 + * convert.cs: Avoid wrapping implicitly convertible reference type. + +2009-02-23 Marek Safar + + * iterators.cs: Create MemberName correctly. + +2009-02-23 Marek Safar + + A fix for bug #478655 + * literal.cs: Check also underlying null type conversion. + +2009-02-21 Marek Safar + + * generic.cs, ecore.cs, class.cs: Removed redundant AsAccessible. + +2009-02-20 Marek Safar + + A fix for bug #477447 + * statement.cs: Add reference to correct parent storey when this + is accessible from deep children storey (more than 1 level). + +2009-02-19 Marek Safar + + A fix for bug #475860 by David Mitchell + * class.cs: Define base type members before setting up member cache. + +2009-02-18 Marek Safar + + A fix for bug #477378 + * nullable.cs, expression.cs, statement.cs: More precise null type + sanity checks. + +2009-02-18 Marek Safar + + A fix for bug #472805 + * typemanager.cs, namespace.cs: Import only visible extension method + types. + +2009-02-18 Marek Safar + + A fix for bug #476895 + * attribute.cs: Use correct resolve context for attribute type. + +2009-02-18 Marek Safar + + A fix for bug #476266 + * anonymous.cs: Mutate multi-dimensional arrays. + +2009-02-18 Marek Safar + + A fix for bug #476400 + * statement.cs, expression.cs: Removed wrong Dispose optimization. + +2009-02-18 Marek Safar + + A fix for bug #476811 + * generics.cs: Fixed null-literal check. + +2009-02-17 Marek Safar + + * typemanager.cs, convert.cs, flowanalysis.cs, driver.cs, + expression.cs, ecore.cs, rootcontext.cs, eval.cs, class.cs: More + messing with static variables. + +2009-02-16 Marek Safar + + A fix for bug #475965 + * generics.cs: Check generic parameter type after extracting from + Expression. + +2009-02-16 Marek Safar + + A fix for bug #475823 + * convert.cs, expression.cs, literal.cs, ecore.cs, cfold.cs: Add + typed-null support. + +2009-02-14 Marek Safar + + * modifiers.cs, decl.cs, ecore.cs, class.cs, flowanalysis.cs: + Simplified event field definition using backing field and not + field builder directly. + + * expression.cs (EmitLdArg): Optimize fast paths. + +2009-02-13 Marek Safar + + A fix for bug #475327 + * expression.cs (ArrayCreation): Don't mutate values optimized away. + +2009-02-13 Marek Safar + + A fix for bug #475342 + * cs-parser.jay: Using 'super' instead of 'base' to call base + constructor crashes compiler. + +2009-02-13 Marek Safar + + A fix for bug #475354 + * expression.cs (Constantify): Add nullable types. + + * const.cs (EmitDecimalConstant): Avoid explicit cast. + +2009-02-12 Marek Safar + + A fix for bug #475246 + * expression.cs: More broken flowanalysis hacking needed. + +2009-02-12 Marek Safar + + * attribute.cs: Compare only ref/out array modifiers. + +2009-02-11 Marek Safar + + * statement.cs: Use member cache when looking for foreach members. + +2009-02-11 Marek Safar + + * expression.cs: Don't expose internal initializer types. + + * statement.cs: Check also explicit conversions for goto case. + +2009-02-11 Marek Safar + + * convert.cs, statement.cs: Removed usage of IsAssignableFrom. + +2009-02-10 Marek Safar + + * *.cs: Replace null-type with NullLiteral where appropriate. + +2009-02-09 Marek Safar + + * expression.cs: Initializer of reference argument use temporary + variable to be verifiable. + + * parameter.cs: Share EmitLdArg. + +2009-02-09 Marek Safar + + A fix for bug #473559 + * class.cs: Fixed: Not reporting error about nested class with the + same name. + +2009-02-06 Scott Peterson + + Contributed under the MIT/X11 license. + + * generic.cs: Added VerifyVariantTypeParameters which performs new + variance verification logic. The old logic, based on the spec, was + wrong because the spec is full of LIES! + + * generic-mcs.cs: Stubbed out the VerifyVariantTypeParameters method. + + *typemanager.cs: Moved variance verification logic to GenericTypeExpr. + + * class.cs: + * ecore.cs: Added calls to the new variance verification logic. + + * parameter.cs: + * delegate.cs: Removed calls to the old variance verification logic. + +2009-02-06 Marek Safar + + * delegate.cs: Use cached Invoke method directly. + +2009-02-06 Marek Safar + + * expression.cs: Emit expression tree for hoisted variable access. + +2009-02-04 Marek Safar + + * namespace.cs: Add better extension class check. + +2009-02-05 Scott Peterson + + * generic.cs: Fixed typeo (TypeParameter.Variacne). + +2009-02-04 Scott Peterson + + This patch adds initial generic variance support to the compiler. + It is contributed under the MIT/X11 license. + + * typemanager.cs: Modified ImplementsInterface to check variance. + Added VerifyVariantTypeParameters which checks the specified type to see + if it uses a variant type parameter as a type argument (which is not + allowed). Added IsVariantOf which determins if the first type is a + variant of the second. NOTE: This only supports reference types at + the moment to conform with the current level of VM support. When the + VM supports value types, this will follow step. + + * generic.cs: Added the Variance enum. Added a Variance property to + TypeParameter and added variance support to definition phase. Added a + Variance property to TypeParameterName. Also check to make sure that + no variant types appear in generic method parameters. + + * cs-tokenizer.cs: Modified parse_less_than to tokenize the variance + keywords if the langversion supports it. + + * parameter.cs: Added Parameter.VerifyNoVariantTypeParameters to ensure + that variant types are only used in legal positions. Also added + ParametersCompiled.VerifyNoVariantTypeParameters to check all of its + parameters. + + * decl.cs: Construct TypeParameter with the variance information. + + * convert.cs: Checks variance in ImplicitReferenceConversionExists + and ImplicitConversionStandard. + + * rootcontext.cs: Added new "Future" language version. + + * class.cs: In TypeContainer.DoDefineMembers, ensure that contravariant + type parameters are not used as type arguments in interface inheritance. + In MemberBase.DoMemberDependentChecks, ensure that contravariant type + parameters are not used as method return types. In MemberBase. + ResolveMemberType, ensure that variant type parameters are not used + as type arguments. Also call VerifyNoVariantTypeParameters on every + set of parameters which are resolved. + + * delegate.cs: Modified Delegate.Define to ensure that variant + parameters are not used as type arguments and that a contravariant + parameter is not used as the return type. Also call + VerifyNoVariantTypeParameters on the delegate parameters. + + * cs-parser.jay: Modified grammar to support "in" and "out" keywords + to specify generic variance. + + * driver.cs: Added support for LanguageVersion.Future in the form of + "-langversion:future". + + * generic-mcs.cs: Stubbed out new members in generic.cs. + +2009-02-03 Marek Safar + + * class.cs, generic.cs: Emit type parameter constraints for nested + types. + +2009-02-02 Marek Safar + + A fix for bug #471213 + * class.cs: Avoid emitting backing field for abstract event fields. + +2009-02-01 Marek Safar + + A fix for bug #359731 + * cs-tokenizer.cs, cs-parser.jay: Correctly parse nested query + expressions. + +2009-01-30 Marek Safar + + A fix for bug #470767 + * statement.cs: Introduced BlockScopeExpression, needed when + expression tree conversion has to emit scope variables. + +2009-01-29 Marek Safar + + * class.cs: Remove duplicate CallingConvention. + +2009-01-29 Marek Safar + + *.cs: Rename Parameters to ParametersCompiled and ParametersImported + when I finally found the right naming convention. + +2009-01-29 Marek Safar + + * cs-tokenizer.cs: Put back different open parens optimization. + +2009-01-28 Marek Safar + + A fix for bug #470227 + * cs-tokenizer.cs: Remove too agressive parser optimization. + +2009-01-28 Marek Safar + + A fix for bug #324319 + * class.cs: Remove too early base type resolve. + +2009-01-27 Marek Safar + + A fix for bug #324319 + * ecore.cs: Explicitly type null when assigning to type argument to + make pass verifier check. + +2009-01-27 Marek Safar + + * anonymous.cs: Fixed recent regression when initializing captured + this. + +2009-01-26 Marek Safar + + A fix for bug #469019 + * anonymous.cs: Use all parent type parameters when instantiating + nested generic storey. + +2009-01-26 Marek Safar + + * expression.cs: Check for null instance methodgroup expression. + +2009-01-26 Marek Safar + + A fix for bug #469244 + * cs-tokenizer.cs, cs-parser.jay: Fixed parsing of nullable type + instance inside a conditional expression. + +2009-01-23 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, decl.cs, anonymous.cs, + expression.cs, report.cs, ecore.cs, attribute.cs: Use common + GetElementType and HasElementType. IsValueType clean up. + +2009-01-23 Marek Safar + + * nullable.cs: Use common EmitCall. + + * expression.cs: Emit constraint. for virtual calls only. + +2009-01-23 Marek Safar + + * typemanager.cs, generic.cs, eval.cs, convert.cs, const.cs, + expression.cs, statement.cs, rootcontext.cs, ecore.cs, class.cs, + driver.cs, attribute.cs, enum.cs: Split IsValueType and IsStruct + checks. + +2009-01-22 Jb Evain + + * anonymous.cs: make anonymous types' ToString implementation + match what csc outputs. + +2009-01-21 Marek Safar + + * typemanager.cs, ecore.cs, iterator.cs: TypeLookupExpression clean + up. + +2009-01-17 Marek Safar + + * convert.cs, ecore.cs: Explicitly casts type arguments to pass + verifier checks. + +2009-01-16 Marek Safar + + * nullable.cs (LiftedBinaryOperator): Check for all possible null + expressions. + +2009-01-15 Marek Safar + + A fix for bug #466634 + * statement.cs: Add reference for nested storey when only this + is captured. + +2009-01-15 Marek Safar + + A fix for bug #466474 + * codegen.cs: Emit SecurityPermissionAttribute when -unsafe option + was specified. + +2009-01-15 Marek Safar + + * iterators.cs, anonymous.cs, expression.cs, statement.cs, ecore.cs: + Fixed nested stories parent referencing process. Also fixes #463985. + +2009-01-06 Marek Safar + + * decl.cs, iterators.cs, expression.cs, statement.cs, doc.cs, + class.cs, cs-parser.jay, codegen.cs: Clean up destructor + implementation. Also fixes #463108. + +2009-01-05 Marek Safar + + A fix for bug #416109 + * decl.cs: Issue correct CLSAttribute warning location. + +2009-01-05 Marek Safar + + A fix for bug #456775 + * attribute.cs: Use attribute owner scope when resolving attribute + arguments. + +2009-01-05 Marek Safar + + A fix for bug #457257 + * decl.cs: Fixed incorrect member declaring type comparison. + +2009-01-05 Marek Safar + + A fix for bug #460896 + * driver.cs: Handle /RES resources as embeddable. + +2009-01-05 Marek Safar + + A fix for bug #462515 + * ecore.cs: Report inacessible members upwards. + +2009-01-05 Marek Safar + + A fix for bug #463190, #463192 + * decl.cs, namespace.cs: Also import internal extension classes. + +2009-01-04 Marek Safar + + A fix for bug #463415 + * generic.cs: Use right index for RemoveDependentTypes. + +2009-01-02 Marek Safar + + A fix for bug #463196 + * expression.cs: Fixed enum to null comparison. + +2009-01-02 Marek Safar + + A fix for bug #463121 + * nullable.cs: Fixed nullable user equality operator comparison. + +2009-01-02 Marek Safar + + A fix for bug #462950 + * class.cs, decl.cs: Use full explicit name when defining automatic + property backing field. + +2009-01-02 Marek Safar + + A fix for bug #462592 + * pending.cs: Emit type arguments for generic proxy method. + +2008-12-30 Marek Safar + + * expression.cs (As): Mutate all type arguments. + +2008-12-29 Marek Safar + + A fix for bug #462622 + * anonymous.cs: Resolve anonymous type GetHashCode in unchecked + context. + +2008-12-29 Marek Safar + + A fix for bug #450782 + * ecore.cs: Consider more variables of form V.I to be fixed. + +2008-12-29 Marek Safar + + A fix for bug #460712 + * typemanager.cs: Core types could be imported. + +2008-12-28 Marek Safar + + A fix for bugs #460847, #460772, #458049, #457339, #447807 + * generic.cs, parameter.cs, lambda.cs, linq.cs, anonymous.cs + statement.cs, ecore.cs, class.cs, delegate.cs, flowanalysis.cs + cs-parser.jay, driver.cs: LINQ implementation upgrade to deal with + user lambdas used inside query clauses. + +2008-12-18 Marek Safar + + A fix for bug #460229 + * cs-tokenizer.cs: Ignore wrongly placed BOM markers. + +2008-12-18 Marek Safar + + A fix for bug #459952 + * decl.cs, namespace.cs: Use common CheckAccessLevel. + +2008-12-18 Marek Safar + + A fix for bug #459630 + * convert.cs: Enum to valuetype conversion is not allowed. + +2008-12-18 Marek Safar + + A fix for bug #457087 + * generic.cs: Don't crash when constraint comes from type + declaration. + +2008-12-16 Marek Safar + + A fix for bug #459221 + * anonymous.cs, statement.cs: Delay only captured this + initialization. + +2008-12-12 Marek Safar + + A fix for bug #457489 + * anonymous.cs, statement.cs: Split anonymous storey instantiation + and initialization to capture scope initializers correctly. + +2008-12-11 Marek Safar + + * generic.cs, parameter.cs, expression.cs, statement.cs, doc.cs: + ParameterReference refactoring. + +2008-12-03 Marek Safar + + * typemanager.cs, namespace.cs, driver.cs: Allow ExtensionAttribute + to be imported from any assembly. + +2008-12-03 Marek Safar + + * parameter.cs, lambda.cs, linq.cs, iterators.cs, anonymous.cs + statement.cs, class.cs, cs-parser.jay: Removed duplicate parameters + from anonymous method and lambda expression. + +2008-12-01 Marek Safar + + A fix for bug #448560 + * expression.cs (As): Box any generic type arguments to be + verifiable. + +2008-11-29 Raja R Harinath + + Add tripwire for implicit conversion bugs + * ecore.cs (MethodGroupExpr.Error_ArgumentCountWrong): New helper + for CS1501 error. + (MethodGroupExpr.OverloadResolve): Add sanity check between + IsApplicable and VerifyArgumentsCompat. + (VerifyArgumentsCompat): Report CS1501 where appropriate. + +2008-11-29 Raja R Harinath + + Fix build break in System.Data_test + * convert.cs (ImplicitConversionExists): Move NullLiteral + conversions ... + (ImplicitStandardConversionExists): ... here. + +2008-11-28 Marek Safar + + * literal.cs: Emit correctly explicit null to nullable cast. + +2008-11-28 Marek Safar + + * ecore.cs, generics.cs: Fixed crash when type arguments fail to + resolve. + +2008-11-28 Marek Safar + + A fix for bug #449005 + * convert.cs, nullable.cs: Use only one implicit nullable + conversion. + +2008-11-27 Marek Safar + + * convert.cs, literal.cs: More Convert cleanup is needed. + +2008-11-27 Marek Safar + + * decl.cs, class.cs: Fixed misleading error message. + +2008-11-26 Marek Safar + + A fix for bug #449005 + * nullable.cs (EmitEquality): Disable optimization for user operator + operands. + +2008-11-25 Marek Safar + + A fix for bug #447027 + * anonymous.cs (HoistedVariable): Cache also outer access to deal + with context variables stored as expression instances. + +2008-11-25 Marek Safar + + A fix for bug #447027 + * delegate.cs: Fixed delegate VerifyMethod logic. + +2008-11-24 Marek Safar + + * ecore.cs, delegate.cs: MethodGroup expressions can be applicable + but not verifiable. + +2008-11-21 Marek Safar + + * typemanager.cs, decl.cs, anonymous.cs, class.cs, enum.cs: Rewrote + member type resolve to follow normal flow, instead of random + property access. + +2008-11-21 Marek Safar + + * iterators.cs (GetEnumeratorStatement): Re-use already resolved + type. + +2008-11-21 Marek Safar + + * const.cs: Emit decimal array constant as literal. + +2008-11-20 Marek Safar + + * iterators.cs, ecore.cs: Removed CurrentBlock statement. + +2008-11-19 Marek Safar + + * eval.cs, location.cs, driver.cs (Location.SourceFiles): Turned + into real property (saves 8 MB for corlib compilation). + +2008-11-19 Marek Safar + + * generic.cs, lambda.cs, linq.cs, iterators.cs, anonymous.cs, + nullable.cs, expression.cs, statement.cs, ecore.cs, cs-parser.jay + generic-mcs.cs: Small cleanup of TypeArguments. + +2008-11-18 Marek Safar + + * generic.cs, iterators.cs, anonymous.cs, nullable.cs, ecore.cs, + expression.cs, namespace.cs, generic-mcs.cs, class.cs: Small cleanup + of ConstructedType expression, renamed to GenericTypeExpr. + +2008-11-17 Marek Safar + + A fix for bug #445303 + * location.cs (IsConditionalDefined): Handle undefined global + defines. + +2008-11-17 Marek Safar + + A fix for bug #444678 + * expression.cs (TryReduceConstant): Always create new constant + instance. + +2008-11-17 Marek Safar + + A fix for bug #444673 + * ecore.cs: Ignore open generic types when used as generic type + instance fields. + +2008-11-17 Marek Safar + + A fix for bug #445458 + * expression.cs, cs-parser.jay: Don't crash when an expression + statement is null. + +2008-11-17 Marek Safar + + A fix for bug #445464 + * expression.cs, cs-parser.jay: Fixed typeof of non-generic type + inside unbound type. + +2008-11-14 Jb Evain + + * driver.cs: ignore empty -nowarn argument such as + the one in -nowarn:12,13,,. + +2008-11-13 Marek Safar + + A fix for bug #444271 + * anonymous.cs: Rescan parent storeys when best candidate was + undone. + +2008-11-13 Marek Safar + + * generic.cs, expression.cs, ecore.cs, cs-parser.jay: Removed + useless UnboundTypeExpression. + + * attribute.cs: Do check obsolete attribute on generic types. + +2008-11-12 Marek Safar + + A fix for bugs #425680, #400139 + * ecore.cs, expression.cs: Trying to do some almost_matched_members + refactoring. + +2008-11-11 Marek Safar + + A fix for bug #435747 + * assign.cs, expression.cs: Cleanup New assignment to emit correcly + compound value types assignment. Few micro optimizations added. + +2008-11-10 Marek Safar + + A fix for bug #442610 + * anonymous.cs (MutateConstructor): More SRE hacking. + +2008-11-10 Marek Safar + + A fix for bug #442579 + * ecore.cs: Also initialize expanded form of a method with 1 params + parameter. + +2008-11-06 Marek Safar + + * expression.cs (UnaryMutator): Do early l-side check. + +2008-11-05 Miguel de Icaza + + * codegen.cs (InitDynamic): also setup Assembly.Name like we do in + Init, otherwise we would crash later on when checking for friend + assemblies. + + * eval.cs: Do not hide errors from invalid calls to LoadAssembly. + Otherwise we never get any meaningful information as to what + failed. + +2008-11-05 Marek Safar + + A fix for bug #436318 + * driver.cs, report.cs: Add -warnaserror:Wn to command line options. + +2008-11-05 Miguel de Icaza + + * namespace.cs: Turns out that it was a really bad idea to hide + the errors for namespaces not found here in eval mode. + + * eval.cs: When we process using clauses, only enter those into + the list of valid using clauses after they have been validated. + + The above change gives the proper semantics: it does not + senselessly report the same errors with broken using statements by + never storing them in the first place when they are invalid. + +2008-11-05 Marek Safar + + A fix for bug #421839 + * cs-parser.jay: Remove expression from coalesce rule to force lower + priority than the assignment operator. + +2008-11-05 Marek Safar + + A fix for bug #437875 + * nullable.cs: Compile correctly method group operand used with null + coalescing operator. + +2008-11-04 Marek Safar + + A fix for bug #434589 + * expression.cs (Binary): Ignore lifted conversions when at least + one operand is of reference type. + +2008-11-04 Marek Safar + + * cs-parser.jay: Better syntax error report. + +2008-11-03 Marek Safar + + A fix for bug #436792 + * cs-parser.jay: Use GetLocation to access location. + +2008-11-03 Marek Safar + + A fix for bug #440774 + * cs-parser.jay: Also set current_array_type when parsing local + variables types. + +2008-11-03 Marek Safar + + A fix for bug #440785 + * expression.cs (As): Don't resolve self modifing expression + multiple times. + +2008-11-03 Marek Safar + + A fix for bug #439447 + * cs-tokenizer.cs: Tokenize surrogates only where allowed. + +2008-11-03 Marek Safar + + A fix for bug #437571 + * cs-parser.jay: Fixes internal error for invalid expression + statements. + +2008-10-17 Marek Safar + + * ecore.cs: Resolve correctly ambiguous params delegate methods. + +2008-10-17 Marek Safar + + * generic.cs, anonymous.cs: Simplified GetDeclarations. + +2008-10-17 Marek Safar + + * cs-tokenizer.cs: More precise cast parsing. + +2008-10-16 Martin Baulig + + * anonymous.cs (AnonymousMethodStorey): Put back the + `hoisted_locals' hashtable and use it in EmitType(). + +2008-10-15 Marek Safar + + * cs-tokenizer.cs, nullable.cs, expression.cs, statement.cs, + cs-parser.jay: Tokenizer optimizations and memory reduction, saves + ~5MB for corlib. + +2008-10-14 Marek Safar + + * cs-tokenizer.cs: Add bool type to the list of valid cast tokens. + +2008-10-14 Marek Safar + + * statement.cs: Mutate scope initializers. + +2008-10-14 Marek Safar + + * expression.cs: Use typeless value for This constant. + + * ecore.cs: Access FieldInfo via GetConstructedFieldInfo. + +2008-10-14 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Unify context sensite keyword + tokenizer. + +2008-10-13 Marek Safar + + * cs-tokenizer.cs: Add missing alias qualifier and dotted generic + type to type cast. + +2008-10-13 Marek Safar + + * cs-tokenizer.cs, expression.cs, cs-parser.jay: Reworked parens + parser and tokenizer. Fixes many ambiguities including #433258. + +2008-10-10 Marek Safar + + * cs-parser.jay: Fixed missing accessor recovery. + +2008-10-10 Marek Safar + + A fix for bug #433701 + * expression.cs: Better error message. + +2008-10-10 Marek Safar + + * cs-parser.jay, expression.cs: Start reporting real parser errors. + + * Makefile: Disabled unused debug symbols. + + Also fixes: #320556, #321097, #321656, #321876, #351316 + +2008-10-09 Miguel de Icaza + + * eval.cs: rename "" to "{interactive}", to work + around a requirement in the compiler that this be a valid + filename, and in Windows it is not (433886). + +2008-10-09 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Fixed more subtle parser problems + +2008-10-08 Marek Safar + + * cs-tokenizer.cs, eval.cs, anonymous.cs, statement.cs, class.cs + cs-parser.jay: Generic type declaration and type arguments cleanup. + +2008-10-05 Marek Safar + + * cs-parser.jay: Allow parsing weird array creation construct. + +2008-10-05 Marek Safar + + * cs-parser.jay: Conflicts reduction. + +2008-10-04 Marek Safar + + * cs-parser.jay: Conflicts reduction. + +2008-10-04 Raja R Harinath + + Fix #398325 + * flowanalysis.cs (MyBitvector.MakeShared): Rename from 'Shared' + property. Add a 'count' hint about the use of the shared vector. + Ensure that we don't leak out dirty bits. + (UsageVector.MergeChild): Throw away information about variables + in child vectors. + Based on patch and analysis by Moritz Kroll . + +2008-10-03 Marek Safar + + A fix for bug #431746 + * iterators.cs, anonymous.cs: Re-initialize hoisted iterator + parameters when iterator is created. + +2008-10-03 Marek Safar + + A fix for bug #431827 + * expression.cs: Fixed right based pointer arithmetic operations + emit. + +2008-10-03 Marek Safar + + A fix for bug #353779 + * assign.cs, expression.cs: Fixed compound assignment conversions. + +2008-10-02 Marek Safar + + A fix for bug #375262 + * statement.cs: Refactor ArrayForeach to be usable with string + indexer. Optimized single dimentional arrays foreach. + +2008-10-02 Marek Safar + + A fix for bug #431255 + * anonymous.cs, expression.cs: Removed broken optimization. + +2008-10-01 Marek Safar + + * anonymous.cs: Use full type parameters of parent generic + containers. Removed unnecessary AddParentStoreyReference call. + +2008-10-01 Marek Safar + + A fix for bug #324702 + * class.cs: Use better shorter names for explicit interface member + implementations. + + * ecore.cs, typemanager.cs: Convert only mscorlib predefined names. + +2008-10-01 Marek Safar + + * expression.cs: Use new interface to check fixed expression. + +2008-10-01 Marek Safar + + A fix for bug #421101 + * expression.cs, statement.cs, ecore.cs: Use IFixedExpression + interface to check for fixed fixed-buffers. + +2008-10-01 Marek Safar + + A fix for bug #429264 + * assign.cs, anonymous.cs, ecore.cs: More type mutators added. + + * delegate.cs: Removed unnecessary casts. + +2008-09-30 Marek Safar + + A fix for bug #352151 + * decl.cs, iterators.cs, anonymous.cs, report.cs, namespace.cs, + class.cs: Fixed already defined explicit interface members check. + +2008-09-29 Rodrigo Kumpera + + cs-tokenizer.cs: Fix typo. + +2008-09-28 Miguel de Icaza + + * eval.cs (InteractiveBase): The quit command now just sets a + flag, instead of calling Environment.Exit(), it is milder on + embedded hosts. + + CompiledMethod is now in Mono.CSharp, not nested inside + the Evaluator, it was inconvenient to use. + +2008-09-27 Miguel de Icaza + + * eval.cs (Evaluator): Introduce Compile method, to allow compiled + code to be invoked without having to reparse. + +2008-09-27 Miguel de Icaza + + * ecore.cs: The recent changes to FieldExpr broke this as well. + Fixes LINQ queries in the interactive shell. + + * Multiple files: indentation fixing for the Mono coding + guidelines for the switch statement. + + * eval.cs: Make the Evaluator API thread safe. + +2008-09-26 Marek Safar + + * anonymous.cs, statement.cs, class.cs, cs-parser.jay: Simplified + constructor parsing. + +2008-09-26 Marek Safar + + A fix for bug #325326 + * statement.cs: Check possible mistaken empty statement using + explicit blocks only. + +2008-09-25 Miguel de Icaza + + * eval.cs (LoadAssembly, ReferenceAssembly): Call + RootNamespace.ComputeNamespaces to update the internal list of + namespaces, this is no longer done for us. + + (InteractiveBase): Use the Evaluator APIs instead of calling into + Driver directly + +2008-09-25 Marek Safar + + A fix for bug #429264 + * expression.cs: Missing mutator for access to multidimensional + arrays. + +2008-09-25 Marek Safar + + * class.cs, statement: Emit DebuggerHidden attribute for iterator + entry wrapper. + + * driver.cs: Missing input argument check. + +2008-09-25 Marek Safar + + * typemanager.cs, generic.cs, eval.cs, decl.cs, anonymous.cs, + expression.cs, statement.cs, rootcontext.cs, class.cs, + cs-parser.jay, driver.cs, generic-mcs.cs, enum.cs: Removed obsolete + DefineMembers. + +2008-09-24 Miguel de Icaza + + * ecore.cs (FieldExpr): Only initialize eclass when we return a + fully constructed FieldExpr, fixes the regression introduced in + the last commit. + + * ecore.cs, expression.cs: Plug back the eclass initialization as + otherwise it regresses `csharp'. + +2008-09-24 Marek Safar + + * typemanager.cs, decl.cs, convert.cs, assign.cs, expression.cs, + ecore.cs, attribute.cs: Moved obsolete method checks from emit + phase to resolve phase. It resolves problems with expression trees + and fixes bugs #323796, #325156. + +2008-09-23 Marek Safar + + * codegen.cs: Report better error when symbol writer is missing. + +2008-09-23 Marek Safar + + * codegen.cs: Set .NET symbol writer. + + * decl.cs: Guard against null generic arguments. + + * report.cs: Don't report exactly same additional details. + +2008-09-22 Marek Safar + + A fix for bug #324917 + * cs-parser.jay: Add missing multidimensional non-expression type + ranks. + +2008-09-22 Marek Safar + + A fix for bug #428191 + * anonymous.cs: Create an outer generic fields also for non-storey + anonymous methods. + +2008-09-22 Marek Safar + + A fix for bug #378294 + * class.cs: Make fixed size buffers gmcs feature only. + +2008-09-22 Marek Safar + + A fix for bug #355622, #324993 + * assign.cs, const.cs, class.cs: Create new EmitContext for each + field initializer. + +2008-09-19 Marek Safar + + * nullable.cs, expression.cs, namespace.cs, delegate.cs: Duplicate + error reporting. + +2008-09-19 Marek Safar + + A fix for bug #416110 + * generic.cs: Struct constraint results in default ctor and + ValueType base type constraint to be set. + +2008-09-19 Marek Safar + + A fix for bug #423791 + * generic.cs: Fixed params output type type-inference. + +2008-09-19 Marek Safar + + * cs-parser.jay, expression.cs: Fixed few expression crashes. + +2008-09-19 Marek Safar + + * cs-tokenizer.cs: Don't break on extra partial modifier. + +2008-09-19 Marek Safar + + A fix for bug #427592 + * generic.cs: Use common parameter resolve method. + +2008-09-18 Marek Safar + + A fix for bug #414758 + * expression.cs, ecore.cs: Fixed crash when accessing non-static + property. + +2008-09-18 Marek Safar + + * driver.cs, namespace.cs: Read types and namespaces after all + requested assemblies are loaded, fixes issues with System.Core + auto-reference, and #419888. + +2008-09-18 Marek Safar + + A fix for bug #417705 + * cs-parser.jay: Fixed as/is operator expression split. + +2008-09-18 Marek Safar + + * const.cs, expression.cs, statement.cs, ecore.cs, cs-parser.jay: + Fixed expression tree representation of empty new expression and + new initializer expression. + +2008-09-18 Miguel de Icaza + + * eval.cs: Remove warning, keep reference to driver around. + + * Hide fields that do not need to be public. + +2008-09-17 Marek Safar + + A fix for bug #426385 + * expression.cs (ImplicitlyTypedArrayCreation): Use full implicit + conversion for array elements. + +2008-09-17 Marek Safar + + * expression.cs, statement.cs, class.cs, cs-parser.jay: Fixed + void parsing conflicts. + +2008-09-15 Marek Safar + + A fix for bug #425601 + * driver.cs, typemanager.cs, namespace.cs: Automatically reference + System.Core only when there is no custom ExtensionAttribute + implementation. + +2008-09-15 Miguel de Icaza + + * namespace.cs: Do not report CS0246 (name + +2008-09-12 Marek Safar + + A fix for bug #425669 + * generic.cs: Don't cache generic static anonymous method + containers. + +2008-09-12 Marek Safar + + * generic.cs, class.cs, delegate.cs: Check recursive inherited + conflicting constraints. + +2008-09-12 Raja R Harinath + + * cs-tokenizer.cs (consume_identifier): Allow partial methods in + mcs too. + +2008-09-12 Marek Safar + + * literal.cs, convert.cs, expression.cs, statement.cs: More null + to null pointer conversion fixes. + +2008-09-11 Marek Safar + + * cs-parser.jay, expression.cs: An implicitly typed local variable + declarator cannot use an array initializer. + +2008-09-11 Marek Safar + + * cs-parser.jay: Reduced number of printed tokens, add sorting. + +2008-09-11 Marek Safar + + * generic.cs (InflatedConstraints): Don't crash when constraints + are different. + + * cs-parser.jay: const_declarator is a block. + + * constant.cs: Check for not allowed NaN conversions. + +2008-09-10 Miguel de Icaza + + * driver.cs: Drop --shell argument, the compiler is no longer a + REPL. + + * eval.cs: Move most of the code that deals with evaluation into + this file and document the public API from repl.cs + + * repl.cs: Remove from here. + +2008-09-10 Marek Safar + + A fix for bug #424684 + * generic.cs: Generic class constraints must come first. + +2008-09-09 Miguel de Icaza + + * cs-parser.jay: Improve error reporting for syntax errors in + statements and expressions, we now report the expected tokens + instead of reporting the useless "; expected". + + Drop the strings from the token declaration, it turns out that + they did not do what I thought they did. Instead they were adding + two sets of tokens to the tables. + +2008-09-09 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, expression.cs, class.cs, + delegate.cs: Share special type check. + +2008-09-09 Marek Safar + + A fix for bug #423981 + * expression.cs (EmitBranchable): Correctly emit inverted float conditions. + +2008-09-09 Marek Safar + + * ecore.cs (ReducedConstantExpression): Implemented ConvertExplicitly and + ConvertImplicitly. + +2008-09-09 Marek Safar + + A fix for bugs: #324750, #335946 + * cs-tokenizer.cs, cs-parser.jay, expression.cs: Use a custom + lookup rule to determine ?-based tokens. + +2008-09-08 Miguel de Icaza + + * repl.cs (OptionalAssign.EmitStatement): It is possible that some + expressions (like event adding or removing) end up here, so we + need to treat those as statements. + + Add LoadAssembly method. + +2008-09-04 Miguel de Icaza + + * repl.cs: Add Time method. + +2008-09-05 Marek Safar + + * cs-tokenizer.cs: Fixed swaped UTF-16 surrogates parsing. + +2008-09-05 Miguel de Icaza + + * repl.cs: Add workaround for old compilers. + +2008-09-04 Jb Evain + + * repl.cs (PrettyPrint): pretty print everything that + implements IDictionary, as well as IEnumerables. Also, + add a quit helper property. + +2008-09-04 Marek Safar + + * constant.cs: Better error reporting for decimal literals. + + * class.cs, attribute.cs, typemanager.cs: Emit more fixed buffer + field attributes. + +2008-09-04 Marek Safar + Miguel de Icaza + + A fix for bug #422951 + * assign.cs (Assign.DoResolve): Perform the type conversions + checks before we attempt to initialize `New' initializers. + +2008-09-04 Marek Safar + + A fix for bug #422853 + * delegate.cs (DelegateCreation): Add special handling for + EmptyExpression.Null instance expression which is just another + hack for undecided member instance exression. + +2008-09-04 Marek Safar + + * expression.cs, ecore.cs: Emit full expression tree for reduced + binary expressions. + +2008-09-04 Marek Safar + + * expression.cs (This): Guard against multi-resolving. + + * ecore.cs, statement.cs (Throw): Simplified. + + * flowanalysis.cs: Also verify event fields. + +2008-09-04 Miguel de Icaza + + * assign.cs (Assign.DoResolve): Perform the type conversions + checks before we attempt to initialize `New' initializers. + + * repl.cs (PrettyPrint): Add Hashtable prettyprint + + * anonymous.cs (AnonymousTypeClass): On EvalMode make the class + public. + + * repl.cs: Update help. + +2008-09-03 Miguel de Icaza + + * driver.cs (ProcessDefaultConfig): Now it encapsulates all the + handling of the default config handling, including the special + treatment of System.Core assembly. + + Fixes the REPL processing for LINQ. + +2008-09-03 Marek Safar + + A fix for bug #422507 + * expression.cs (UnboxCast): Add missing child expression mutator. + +2008-09-03 Marek Safar + + * driver.cs: Don't self reference System.Core assembly. + +2008-09-03 Marek Safar + + A fix for bug #422507 + * expression.cs (StringConcat): Add missing type mutator. + +2008-09-03 Marek Safar + + * generic.cs (TypeInferenceContext): Follow equality rule for + constructed type lower bound type inference. + +2008-09-02 Miguel de Icaza + + * getline.cs (CmdRefresh): Apply patch from Douglas S. Blank + which updates the cursor position on + refresh. + +2008-09-02 Marek Safar + + A fix for bug #367145 + * driver.cs: Fixed import of extension methods when using -noconfig + option. + +2008-09-02 Marek Safar + + * iterator.cs: Don't emit GetEnumerator method twice but call a generic + version from non-generic implementation instead. + +2008-09-01 Marek Safar + + A fix for bug #418908 + * class.cs: Use AddScopeStatement for field initializers. + +2008-09-01 Marek Safar + + A fix for bug #415385 + * ecore.cs, convert.cs: Do method group conversion for equal group types. + +2008-09-01 Marek Safar + + A fix for bug #421736 + * iterators.cs: Don't crash on unreachable iterators. + +2008-09-01 Marek Safar + + A fix for bug #421628 + * parameter.cs, attribute.cs: Clone also parameter attributes. + +2008-08-30 Miguel de Icaza + + * namespace.cs (LookupType): In EvalMode, try to replace + the TypeBuilder from our cache with a Type as Reflection.Emit does + not like to mix code from older assemblies emitted and new + assemblies emitted. + + This sounds like a serious Mono bug that prevents multiple + assemblies to be generated and consumed at the same time. + + * cs-parser.jay (push_current_class): Do not make interactive + classes internal or private, make them public as we currently + generate each new class in a new assembly. + +2008-08-29 Miguel de Icaza + + * decl.cs, roottypes.cs, class.cs:: Add an infrastructure to + remove types that are entered into the global namespace during + parsing so that we can remove them on failure. + + * cs-parser.jay: Parsing: we now keep track of types that are + entered into global variables and queue those in case the parsing + or resolution fail. + + This happens in a few situations: during partial-input, we invoke + the parser repeatedly for example with the string "class X", this + would cause X to be registed, and we need to remove this + registration so that another parse attempt later with say "class X {" + would actually work. + + Additionally, if there is an error in the resolution phase, for + example: "class X : NonExistant {}" th + + * cs-parser.jay: Be more precise with the errors being raised, + instead of flagging all exceptions during parsing to be attributed + to the parsing process, distinguish those from errors happening in + the actions and hint that using -v would produce the actual + exception. + + * repl.cs: Do not load all compiler references on each reset, + doing the partial reset takes care of this. + +2008-08-28 Miguel de Icaza + + * repl.cs: Add support for loading all the files from + ~/.config/csharp/*cs as startup scripts and ~/.config/csharp/*.dll + as shell libraries. + + Introduce a micro-parser that is able to deambiguate on its input + whether we are dealing with a compilation unit (namespace, class, + interface, struct, delegate) declaration or a statement. This + allows both declarations and statements to be entered. + + Set history size by default to 300 lines. + + Instead of distinguishing based on the parser.InteractiveResult, + have only two cases: statements were parsed, or a compilation unit + was. Always pull the Using statement additions from the + compilation unit parse. + + * cs-tokenizer.cs: Rename tokens to better describe their intent + (EvalStatementParserCharacter and EvalCompilationUnitParserCharacter). + + * rootcontext.cs: Split EvalMode into EvalMode and StatementMode. + EvalMode is used to trigger the lookup of global variables while + StatementMode is used turn variable declarations into static + fields. + + * getline.cs: Allow history size to be set. + +2008-08-29 Marek Safar + + A fix for bug #360755 + * ecore.cs (SimpleName): Exclude indexers from simple name resolve. + +2008-08-29 Marek Safar + + * generic.cs, iterators.cs, codegen.cs: Removed unused variable. + + * typemanager.cs, statement.cs, ecore.cs, enum.cs: Don't reconstruct enum + member name, it is too confusing + + * decl.cs, class.cs: Don't report unused fields with attached attribute. + + * rootcontext.cs: Finally default to warning level 4. + +2008-08-28 Marek Safar + + * class.cs (CheckBase): Ignore overloaded operators. + +2008-08-28 Marek Safar + + A fix for bug #420830 + * expression.cs, cs-parser.jay: Put back InvocationOrCast expression. + +2008-08-28 Marek Safar + + A fix for bug #420832 + * anonymous.cs, iterators.cs: Also clone hoisted this iterator variable. + +2008-08-28 Marek Safar + + A fix for bug #420386 + * nullables.cs: Fixed logic of nullable user comparison operators involving + null values. + +2008-08-28 Marek Safar + + * attribute (IsClsCompliant): Use FALSE value for pointer types. + +2008-08-27 Miguel de Icaza + + * repl.cs: Add support for aborting the running code with C-c. + +2008-08-27 Raja R Harinath + + * cs-parser.jay (CS1002): Dump 'yyToken' with Report.ExtraInformation. + +2008-08-27 Miguel de Icaza + + * cs-parser.jay (interactive_statement_list): A new set of rules + for hosting statements that uses the "interactive_" prefix. + + * repl.cs: Add support for parsing `using' as a statement or as a + directive. Deambiguating before passing this to the parser. + + We need to distinguish statement_expressions that occur at the + toplevel vs those that occur embedded into expressions. + + * getline.cs: Applied patch from Stuart Carnie + that fixes the cursor key handling, and a history bug. + +2008-08-26 Miguel de Icaza + + * Makefile: Drop BOOTSTRAP_COMPILER as that was masking the + limitations in Console, instead the 2.0 bootstrap libraries now + include the Console bits. + + Also, remove the use of Nullables from getline.cs + + ------------ + + Interactive support for the C# compiler. Use gmcs --shell to + enter a read-eval-print loop shell. + + Docs: http://www.mono-project.com/CsharpRepl + + * sources: include repl.cs here and getline.cs for gmcs.exe, + everything else is getline.cs impaired. + + * Makefile: when bootstrapping pass a special flag + BOOTSTRAP_COMPILER which we use to prevent failures in compilation + as we use NET_2_0 define to pull 2.0 APIs from System.Console. + This distinguishes those two cases. + + * repl.cs: Support for a read-eval-print loop. Will be soon + refactored into eval support and then REPL on top of it. + + * ecore.cs: If a simplename lookup fails, before erroring out, + if we are in EvalMode to resolve the name to a declaration in the + Eval-land. + + This means that variable declarations that happened in previous + classes (as repl puts every statement in a separate class) are + made visible in this way. + + * cs-parser.jay: UnexpectedEOF, a new flag that is set if we + triggered an error due to the end of file being reached. This is + used to do multi-line input, and notify the caller that the user + needs to provide more text before a successful parse. + + Add new grammar rules after the INTERACTIVE_PARSER token is seen + to drive the evaluation with a custom wrapper. + + * driver.cs: Add support for --shell, and refactor some code to be + reused from repl.cs + + * namespace.cs: Add support for serializing the contents of the + namespaces and reloading them. + + * getline.cs: A managed implementation of ReadLine under + X11/Apache2 license terms. Easy to embed in other applications as + well. + + * namespace.cs: Add some functions to save and restore the + namespace state. + + * rootcontext.cs: New public field. + + * cs-tokenizer.cs: Add support for one of the possible characters + we introduce into the token stream. + + This patch does not affect the regular tokenization process, the + only performance hit would happen if there is an invalid character + on the input string. + + * support.cs: Move isatty helper routine here. + + * codegen.cs: Small cleanup, and add a mechanism to initialize the + code generator for in-memory assemblies. + +2008-08-26 Marek Safar + + * generic.cs, ecore.cs, delegate.cs, cs-parser.jay, expression.cs: A type + parameter cannot be always used as a type. + +2008-08-21 Marek Safar + + * convert.cs, expression.cs: Use single ExplicitReferenceConversion routine. + +2008-08-21 Marek Safar + + * convert.cs: Implement explicit array to IList conversion. + +2008-08-20 Marek Safar + + A fix for bug #362740 + * cs-tokenizer.cs: Handle UTF-16 surrogates. + +2008-08-20 Marek Safar + + * generic.cs, support.cs, typemanager.cs, lambda.cs, parameter.cs, + pending.cs, ecore.cs, linq.cs, class.cs, decl.cs, delegate.cs, + flowanalysis.cs, iterators.cs, cs-parser.jay, convert.cs, anonymous.cs, + expression.cs, attribute.cs, statement.cs, doc.cs: Refactored parameters + handling to use just one type of infrastructure and deal with generics + more effectivelly. + +2008-07-23 Martin Baulig + + *** Merged this from trunk revision 108527 *** + + * statement.cs + (ExplicitBlock.EmitSymbolInfo): Moved to `ToplevelBlock'. + (ToplevelBlock.EmitSymbolInfo): Tell the symbol writer about the + scope variable. + +2008-08-15 Marek Safar + + * ecore.cs, linq.cs, const.cs, expression.cs, statement.cs: More robust + error checks. + +2008-08-15 Marek Safar + + * delegate.cs: Fixed compiler crash when creating delegate using partial + method. + + * typemanager.cs: MulticastDelegate is not a delegate. + +2008-08-14 Marek Safar + + * expression.cs, ecore.cs, anonymous.cs, class.cs: Fixed missing error + checks. + +2008-08-14 Raja R Harinath + + * cs-parser.jay (type): Allow 'var' in mcs too. + (local_variable_type): Likewise. + +2008-08-14 Marek Safar + + * driver.cs: Removed broken -noconfig variants. + +2008-08-14 Marek Safar + + A fix for bug #417078 + * expression.cs: Emit correctly left side pointer operators. + +2008-08-13 Marek Safar + + * generic.cs, lambda.cs: Inflate method generic arguments only. + +2008-08-12 Marek Safar + + * class.cs: Fixed struct layout check regression. + +2008-08-12 Marek Safar + + * cs-parser.jay, enum.cs: Simplified enum parsing. + + * decl.cs: Check all type parameters conflicts. + + * expression.cs, statement.cs, attribute.cs: More expression checks. + +2008-08-11 Marek Safar + + * generic.cs: Add type inference types restriction. + + * parameter.cs, class.cs, delegate.cs, iterators.cs, cs-parser.jay, + anonymous.cs, expression.cs: Allocate less accessor parameters. + +2008-08-08 Marek Safar + + * typemanager.cs, ecore.cs: Ambiguous operators can come from different + classes. + +2008-08-08 Marek Safar + + * convert.cs, delegate.cs: Fixed delegate compatibility conversion. + +2008-08-07 Marek Safar + + * class.cs, decl.cs, iterator.cs, ecore.cs: Refactor base type resolving. + Also fixes #362146 and #381592. + +2008-08-07 Marek Safar + + * ecore.cs: Reduced constant cannot be used as an attribute value. + + * cs-parser.jay: Base expression has to be a type. + + * expression.cs (Conditional): Uses ReducedExpression. + +2008-08-06 Marek Safar + + A fix for bug #376826 + * parameter.cs, ecore.cs, anonymous.cs, expression.cs, statement.cs: An + address of hoisted local variable or parameter cannot be taken. + +2008-08-05 Marek Safar + + * ecore.cs, constant.cs, expression.cs, statement.cs: Resolve correctly + anonymous method inside checked/unchecked expression. + +2008-08-05 Marek Safar + + * typemanager.cs (IsEqual): Guard against null. + + * ecore.cs, class.cs, convert.cs, const.cs, constant.cs, expression.cs, + attribute.cs, enum.cs, statement.cs: Pass EmitContext to constant conversion + routine. Fixed few misleading conversion errors. + +2008-08-04 Marek Safar + + * class.cs: Consider generics when checking cycles in struct layout. + +2008-08-04 Raja R Harinath + + * cs-tokenizer.cs (get_cmd_arg): Simplify. Don't be too pedantic. + +2008-08-04 Marek Safar + + A fix for bug #414165 + * anonymous.cs: Use same anonymous implementation method for all anonymous + method emits. + +2008-08-04 Marek Safar + + * generic.cs, anonymous.cs, statement.cs: Emit inherited anonymous method + constraints. + +2008-08-04 Marek Safar + + * cs-parser.jay: Typeof argument has to be a type expression. + + * namespace.cs: Check alias and namespace definitions collisions. + + * class.cs, pending.cs: Moved explicit interface accessor implementation + check. + + * delegate.cs, expression.cs: Verify special name invocations. + +2008-08-01 Marek Safar + + * cs-parser.jay: Don't choke on empty generic type arguments. + + * cs-tokenizer.cs: Handle escaped preprocessor directives. + + * expression.cs, ecore.cs: Minor expressions bugs. + +2008-08-01 Marek Safar + + * cs-parser.jay: Removed duplicate interface declaration (fixes 2 conflicts) + and added more error handling. + + * class.cs, iterators.cs, anonymous.cs: Removed useless interface parameter. + + * modifiers.cs, enum.cs: Fixed. + +2008-07-31 Jb Evain + + * driver.cs: remove -pkg ability of smcs. + +2008-07-30 Marek Safar + + * statement.cs (Switch): Correctly set empty default target for single + blocks. + +2008-07-30 Marek Safar + + * typemanager.cs, assign.cs, driver.cs, expression.cs, statement.cs: Rewrote + string switch statement implementation to use string dictionary which + significantly (2-8x) improves performance of generated code. + +2008-07-29 Marek Safar + + A fix for bug #412880 by Atsushi Enomoto + * modifiers.cs (GetDescription): Fixed FamANDAssem case. + +2008-07-29 Marek Safar + + A fix for bug #412595 + * typemanager.cs, convert.cs, expression.cs: Some types are never + convertible to each other. + +2008-07-29 Marek Safar + + * nullable.cs (CreateNullConstant): An error messages update. + +2008-07-29 Marek Safar + + A fix for bug #412595 + * cfold.cs: Don't cast undefined bool constant. + +2008-07-29 Martin Baulig + + * symbolwriter.cs + (SymbolWriter.Reset): New public static method. + + * driver.cs + (CompilerCallableEntryPoint.Reset): Call SymbolWriter.Reset(). + +2008-07-28 Marek Safar + + * cs-tokenizer.cs (IsLambdaOpenParens): Optimized using more stop tokens. + + * expression.cs (ElementAccess): Exact size allocation. + +2008-07-26 Marek Safar + + * driver.cs: Replaced outdated UnixParseOption with CSCParseOption. + +2008-07-25 Marek Safar + + * flowanalysis.cs (StructInfo): Fixed detection of dynamic types. + + * class.cs: Removed $PRIVATE$ field hack which caused problems during + flow analysis. + +2008-07-25 Marek Safar + + A fix for bug #412217 + * assign.cs: Mutate also assignment type. + +2008-07-25 Marek Safar + + A fix for bug #323644 + * typemanager.cs (IsValidProperty): Verify DefaultMemberName when checking + indexers. + +2008-07-25 Marek Safar + + A fix for bug #412134 + * expression.cs (ResolveOperatorEnum): Do implicit conversion of + non-enumerable operands when overloading equality or bitwise operators. + +2008-07-25 Marek Safar + + * anonymous.cs: Cache closed generic anonymous method delegates. + +2008-07-24 Marek Safar + + * lambda.cs, linq.cs, class.cs, iterators.cs, cs-parser.jay, assign.cs, + anonymous.cs, statement.cs: Always emit anonymous method as static method + when is instance free. Use nesting for nested anynomous methods blocks. + +2008-07-23 Marek Safar + + * anonymous.cs (MutateGenericMethod): Added extra code path for imported + types. + +2008-07-23 Marek Safar + + * expression.cs: Removed MakeSimpleCall. + +2008-07-23 Marek Safar + + A fix for bug #323012 + * class.cs, pending.cs: Emit proxy for indexers when they differ in name. + Base method implementing interface has to be public. + +2008-07-23 Marek Safar + + * cs-parser.jay: Don't break on missing argument. + +2008-07-22 Marek Safar + + A fix for bug #320993 + * report.cs, parameter.cs, class.cs, decl.cs, delegate.cs, attribute.cs, + enum.cs, codegen.cs: Report CLS compliance errors as warnings. + +2008-07-22 Marek Safar + + A fix for bug #320748 + * convert.cs: Implicit user operators cannot convert to interfaces + +2008-07-22 Marek Safar + + A fix for bug #312686 + * driver.cs: Ignore empty assembly references. + +2008-07-22 Marek Safar + + A fix for bug #387040 + * ecore.cs: Skip constrains check for an explicit implementation. + +2008-07-21 Marek Safar + + A fix for bug #409045 + * cs-tokenizer.cs, rootcontext.cs, class.cs, location.cs, delegate.cs, + cs-parser.jay, driver.cs, expression.cs, attribute.cs: Conditional + identifiers are file specific unless passed as input arguments. + +2008-07-21 Marek Safar + + * typemanager.cs, parameter.cs, class.cs, attribute.cs: Use an attribute + to emit UnmanagedMarshal data under 2.0 profile. + +2008-07-21 Marek Safar + + A fix for bug #410369 + * parameter.cs: Clone correctly ParamsParameter. + +2008-07-21 Marek Safar + + * expression.cs (Argument): Always report type for type based expressions + errors. + +2008-07-18 Marek Safar + + A fix for bug #410666 + * anonymous.cs: Correctly initialize generic storey reference. + +2008-07-18 Marek Safar + + * convert.cs: Don't box same type arguments. + +2008-07-18 Marek Safar + + * ecore.cs, linq.cs, delegate.cs, constant.cs, nullable.cs, expression.cs: + Finished missing generic type mutators. + +2008-07-18 Marek Safar + + * iterators.cs, statement.cs: Finished statements CloneTo. + +2008-07-18 Marek Safar + + * anonymous.cs: ExpressionTreeProxy is of Value type expression. + + * expression.cs: Emit optimized default value expressions in expression tree + array initializer. + +2008-07-18 Marek Safar + + * ecore.cs, cs-parser.jay, statement.cs: Error reporting fixes. + +2008-07-17 Marek Safar + + A fix for bug #367536 + * cs-parser.jay: Check static constructor of generic types for an access + modifier. + +2008-07-17 Marek Safar + + A fix for bug #353800 + * lambda.cs: Emit ret for contextual statements. + + * codegen.cs: Keep both resolved and unreachable flags, otherwise we end + up emitting redundant ret for all anonymous methods with return. + +2008-07-17 Marek Safar + + A fix for bug #365188 + * ecore.cs, anonymous.cs, expression.cs, codegen.cs, statement.cs: Don't + create anonymous method storey in unreachable block. + +2008-07-17 Marek Safar + + * generic.cs, typemanager.cs, cs-tokenizer.cs, parameter.cs, namespace.cs, + class.cs, delegate.cs, flowanalysis.cs, iterators.cs, anonymous.cs, + driver.cs, nullable.cs, expression.cs, attribute.cs, codegen.cs, + statement.cs: Fixed relevant defects found by Gendarme. + +2008-07-17 Marek Safar + + A fix for bug #325291 + * modifiers.cs, class.cs, cs-parser.jay, anonymous.cs, codegen.cs, + statement.cs: Replaced IAnonymousHost with top level block flag. + +2008-07-17 Marek Safar + + * cs-parser.jay: Clean up unused open_parens. + +2008-07-17 Marek Safar + + * ecore.cs: Custom error message for a range variable assignment. + +2008-07-16 Marek Safar + + * constant.cs, typemanager.cs: Emit empty string ("") as string.Empty field + load. + +2008-07-16 Marek Safar + + * literal.cs: Null literal is of object type. + +2008-07-16 Marek Safar + + * nullable.cs (LiftedBinaryOperator): Always lift unwrapped nullable + expression of nullable equality comparison. + +2008-07-15 Marek Safar + + * expression.cs(PointerArithmetic): Removed redundant assignment. + +2008-07-15 Marek Safar + + * decl.cs (GetSignatureForError): Report full namespace name for containers. + +2008-07-14 Marek Safar + + A fix for bug #408361 + * anonymous.cs (MutateGenericMethod): Store generic type arguments before + they are replaced by GetMethod. + +2008-07-14 Marek Safar + + A fix for bug #408721 by jeremie.laval@gmail.com + * expression.cs (Indirection): Implemented CloneTo. + +2008-07-14 Marek Safar + + * statement.cs (AssignableSlots): Temporary disabled variable initialization + assert check. + +2008-07-14 Marek Safar + + * report.cs (EnableReporting): Don't reinitialize 0-based values. + +2008-07-11 Marek Safar + + * linq.cs: Reset tranparent parameter counter in probing mode. + +2008-07-11 Marek Safar + + * anonymous.cs: Mutate anonymous method type. + +2008-07-11 Marek Safar + + * ecore.cs, anonymous.cs: Mutate field expressions. + +2008-07-10 Marek Safar + + A fix for bug #369670 + * linq.cs, statement.cs: Use explicit block for query expressions variables. + +2008-07-10 Marek Safar + + * report.cs, ecore.cs: Flush recorder only when silent mode is off. + +2008-07-10 Raja R Harinath + + Fix bug #314902 + * cs-tokenizer.cs (is_punct): If a generic lookahead is looking + only one '>', and finds a '>>', abort the generic lookahead. + +2008-07-10 Marek Safar + + A fix for bug #319902 + * cs-tokenizer.cs: Always look-ahed for `>=' when tokenizing `>'. + +2008-07-10 Marek Safar + + A fix for bug #406371 + * statement.cs: Moved EmitSymbolInfo to Block. + +2008-07-09 Marek Safar + + * ecore.cs: Report better error for extension method overload failures. + +2008-07-09 Marek Safar + + * expression.cs (Is): No need to box reference values. + +2008-07-09 Marek Safar + + * class.cs: Use event resolve context when initializing CreateEmitContext. + +2008-07-09 Marek Safar + + A fix for bug #394436 + * anonymous.cs, class.cs, expression.cs, lambda.cs: Emit correctly extension + method used inside expression trees. Added more LINQ to expression tree + conversions. + +2008-07-08 Marek Safar + + A fix for bug #378189, #370577 + * lambda.cs, ecore.cs: Implemented 3.0 enhancement to better conversion + from expression. + +2008-07-08 Marek Safar + + * anonymous.cs, class.cs, decl.cs: Emit CompilerGenerated attribute + hierarchically. + +2008-07-08 Marek Safar + + A fix for bug #406702 + * anonymous.cs: Always park anonymous method in the nearest parent storey. + +2008-07-07 Marek Safar + + A fix for bug #406648 + * cs-parser.jay: Report nullable use in mcs for some cases. + +2008-07-07 Marek Safar + + * ecore.cs: Improved argument mismatch error messages. + +2008-07-07 Marek Safar + + * anonymous.cs: Don't cache generic delegates when reference MVAR argument. + +2008-07-07 Marek Safar + + * expression.cs (TypeOf): Mutate type argument. + +2008-07-04 Marek Safar + + * class.cs: Report missing partial modifier for correct type. + +2008-07-04 Marek Safar + + * ecore.cs, expression.cs (VariableReference): Variable property is + protected. + +2008-07-04 Marek Safar + + * ecore.cs, convert.cs: Made OpcodeCast more memory efficient. + +2008-07-04 Marek Safar + + * anonymous.cs, class.cs, lambda.cs, iterator.cs: Cache static anonymous + method delegates. + +2008-07-04 Marek Safar + + * anonymous.cs, class.cs, expression.cs, iterator.cs, statement.cs: Reduce + anonymous method storey to an instance method when only "this" is hoisted. + +2008-07-03 Marek Safar + + A fix for bug #321615 + * expression.cs: Pointer comparisons use unsigned operator. + +2008-07-03 Marek Safar + + * expression.cs: Fixed native pointer conversions. Also fixes #321615. + +2008-07-02 Marek Safar + + A fix for bug #404905 + * class.cs: Always initialize local unsafe variables. + +2008-06-30 Marek Safar + + A fix for bug #396987 + * expression.cs (NewInitialize): Clear local temporary variable for next run + +2008-06-27 Marek Safar + + A fix for bug #401020 + * ecore.cs: Both types and modifiers have to match for ref and out arguments + +2008-06-27 Marek Safar + + A fix for bug #398319 + * cs-parser.jay: Implemented undocumented base access expression inside + anonymous types. + +2008-06-26 Marek Safar + + A fix for bug #404227 + * cs-parser.jay: Parse namespace declaration using qualified identifier. + +2008-06-26 Marek Safar + + A fix for bug #404227 + * convert.cs: Fixed explicit array to interface cast. + +2008-06-26 Marek Safar + + A fix for bug #403894 + * delegate.cs: Mutate DelegateInvocation type. + +2008-06-26 Marek Safar + + A fix for bug #379348 + * delegate.cs: Box a load of generic parameters. + +2008-06-26 Marek Safar + + * expression.cs: Add an array creation arguments mutate. + +2008-06-26 Marek Safar + + A fix for bug #386068 + * anonymous.cs, expression.cs: Emit correctly hoisted expression tree + parameter. + +2008-06-25 Marek Safar + + * ecore.cs, expression.cs: Fixed broken TypeCast clone, implemented few more + CloneTo. + +2008-06-25 Marek Safar + + A fix for bug #403518 + * delegate.cs: Type correctly anonymous method new invocation. + +2008-06-24 Marek Safar + + A fix for bug #394826 + * anonymous.cs: Fully qualify members when resolving anonymous type internal + calls. + +2008-06-24 Marek Safar + + A fix for bug #394826 + * anonymous.cs, iterators.cs: Construct generic storey only when is really + needed. + +2008-06-24 Marek Safar + + * class.cs: Clone indexer parameters for localized capturing. + +2008-06-24 Marek Safar + + A fix for bug #402379 + * expression.cs: Don't crash when an object initializer resolve fails. + +2008-06-24 Marek Safar + + A fix for bug #402888 + * expression.cs: Mutate conditional expression. + +2008-06-24 Marek Safar + + A fix for bug #401012 + * class.cs: Keep StructLayout in shared container. + +2008-06-24 Marek Safar + + A fix for bug #400438 + * decl.cs, class.cs: Only properties can be automatically implemented. + +2008-06-24 Marek Safar + + * statement.cs (ChangeToIterator): Copy also labels. + +2008-06-23 Marek Safar + + * ecore.cs: Pass type argument details to parent extension method. + +2008-06-23 Marek Safar + + A fix for bug #375966 + * delegate.cs: Fixed IsTypeCovariant generic type conversions. + +2008-06-23 Raja R Harinath + + * Makefile (bootstrap-libs): Pass NO_DIR_CHECK to sub-make. + +2008-06-22 Marek Safar + + A fix for bug #394347 + * anonymous.cs: Cache compatible delegates as compatibility check produces + a new method every time. + +2008-06-20 Marek Safar + + * anonymous.cs: Propagate storey reference for single references. + +2008-06-20 Marek Safar + + A fix for bug #387615 + * assign.cs, expression.cs: Correctly clone compound assignment. + +2008-06-19 Marek Safar + + A fix for bug #359611, #359604 + * anonymous.cs: Mutate all types of hoisted parameters. + +2008-06-19 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, ecore.cs, linq.cs, class.cs + delegate.cs, iterators.cs, cs-parser.jay, assign.cs, anonymous.cs, driver.cs + expression.cs, codegen.cs, statement.cs + + Fixes bugs: #318652, #323223, #234779, #325069, #325476, #332532, #334465, + #345907, #349190, #353276, #355256, #359617, #378542, #384584, #396530 + + ** Anonymous methods, lambda expressions rewrite ** + + Anonymous expressions are now resolved when an explicit block is resolved + and they don't require any registration procedure anymore. Further, + anonymous methods are defined when explicit block is emitted which allows + better control of whole process and opens possibilities for more + optimizations as well as alternative to reverse whole process. + + A concept of `MutateHoistedGenericType' was introduced to keep the resolve + process consistent and to correctly emit hoisted generic methods when they + have at least 1 hoisted variable. + +2008-06-17 Martin Baulig + + * class.cs: Also emit the `[DebuggerHidden]' attribute on the main + iterator method. + (AbstractPropertyEventMethod.IsDebuggerHidden): New protected + virtual property; check it in Emit(). + (PropertyMethod.IsDebuggerHidden): Override, check whether we're + an iterator. + (MethodOrOperator.ResolveMethods): Set `DEBUGGER_HIDDEN' if we're + an iterator. + (Indexer.Define): Likewise. + +2008-06-17 Marek Safar + + * convert.cs: Don't use IsInterface on type arguments. + + * delegate.cs: DelegateInvocation uses MethodInfo. + + * parameter.cs: Removed IsTypeParameter. + + * generic-mcs.cs: More missing stuff. + +2008-06-16 Martin Baulig + + * modifiers.cs + (Modifiers.DEBUGGER_HIDDEN): New public const. + + * typemanager.cs + (TypeManager.GetDebuggerHiddenAttribute): New public static method. + + * class.cs + (MethodOrOperator.Emit): Check `Modifiers.DEBUGGER_HIDDEN'. + (AbstractPropertyEventMethod): Likewise. + (Constructor.Emit): Likewise. + (SourceMethod.SetCompilerGenerated): Removed. + + * iterator.cs: Set `Modifiers.DEBUGGER_HIDDEN' everywhere except + on MoveNext(). + + * anonymous.cs + (RootScopeInfo.DoDefineMembers): Set `Modifiers.DEBUGGER_HIDDEN' + if we're an `IteratorHost'. + (AnonymousMethodMethod..ctor): Don't set + `Modifiers.COMPILER_GENERATED'; csc only sets this on the class, + not on the method. + +2008-06-16 Marek Safar + + * statement.cs: Clean-up foreach statements. + +2008-06-12 Marek Safar + + * class.cs: Stop using public method which should not exist + (MethodBuilder.SetGenericMethodSignature). + +2008-06-11 Martin Baulig + + * location.cs + (Location.LookupFile): Add `CompilationUnit' argument; when given + a relative file name, make it relative to the directory the .cs + file is located in instead of using the current directory. + +2008-06-11 Martin Baulig + + * class.cs + (IMethodData.EmitExtraSymbolInfo): Added `SourceMethod' argument. + (MethodOrOperator.EmitExtraSymbolInfo): Likewise. + (SourceMethod.SetRealMethodName): Moved here from the symbol writer. + (SourceMethod.SetCompilerGenerated): Likewise. + +2008-06-11 Marek Safar + + * codegen.cs, driver: Only write symbol file when it's asked for. + +2008-06-11 Marek Safar + + * codegen.cs: Don't use assembly writer error handling for symbol writer. + +2008-06-10 Martin Baulig + + * symbolwriter.cs: Reflect latest MarkSequencePoint() API changes. + +2008-06-09 Marek Safar + + A fix for bug #316290 + * expression.cs: Include decimal operators in predefined table. + + * parameters.cs: More readonlyness. + +2008-06-09 Marek Safar + + A fix for bug #397213 + * cs-parser.jay: One more missing current_local_parameters reset. + +2008-06-09 Marek Safar + + A fix for bug #396633 + * class.cs: Host backing field in partial container. + +2008-06-09 Marek Safar + + A fix for bug #397068 + * expression.cs: Check both operand types when predefined operator is used. + +2008-06-05 Martin Baulig + + Merged the `debugger-kahalo' branch. + + * class.cs + (MethodData.Emit): Call SymbolWriter.SetCompilerGenerated() if + we're an iterator method. + (SourceMethod): Reflect latest symbol writer changes; + SymbolWriter.OpenMethod() now takes a `ICompileUnit' argument and + now `start_row' and `end_row'. + (Constructor.Emit): Fix the logic whether to emit symbol information. + + * iterator.cs: Call SymbolWriter.SetCompilerGenerated() on all the + generated methods. + + * location.cs + (CompilationUnit): New public class; derives from `SourceFile'. + (SourceFileEntry.DefineSymbolInfo): New public method. + (SourceFileEntry.SetChecksum): New public method. + (Location): Encode hidden line numbers by using `column == 255'; + the .ctor now accepts `column == -1' to mark a hidden line number. + (Location.Hidden): New public property. + (Location.CheckPoint): Add `CompilationUnit'. + (Location.SourceFiles): Change return type to `CompilationUnit[]'. + (Location.Push): Add `CompilationUnit compile_unit' argument. + (Location.CompilationUnit): New public property. + + * statement.cs + (ToplevelBlock.Emit): Add `ec.Mark (EndLocation)'. + + * cs-parser.jay: `SourceFile' -> `CompilationUnit'. + + * driver.cs: `SourceFile' -> `CompilationUnit'. + + * cs-tokenizer.cs: `SourceFile' -> `CompilationUnit'. + + * namespace.cs: `SourceFile' -> `CompilationUnit'. + + * cs-tokenizer.cs: Add support for `#pragma checksum' and + `#line hidden'. + + * symbolwriter.cs + (SymbolWriter.MarkSequencePoint): Take a `Location' and use the + new symbol writer API to also pass the file. + +2008-06-05 Marek Safar + + * statement.cs: Emit catch variable assignment using variable expression. + +2008-06-05 Marek Safar + + * ecore.cs, expression.cs, statement.cs: Make TemporaryVariable compatible + with other variable types. + +2008-06-04 Marek Safar + + * ecore.cs, expression.cs, statement.cs, typemanager.cs: Removed custom + GetLength method emit, it breaks resolve rules. + +2008-06-02 Atsushi Enomoto + Marek Safar + + A fix for bug #395542 + * cs-parser.jay: The trailing comma is allowed in anonymous type member + declaration. + +2008-06-02 Marek Safar + + A fix for bug #395287 + * class.cs, modifiers.cs: Automatic properties method base modifiers checks. + +2008-05-31 Marek Safar + + A fix for bug #395845 + * class.cs, nullable.cs: User unary operator is allowed to have nullable and + non-nullable parameter type. + +2008-05-31 Marek Safar + + * class.cs: Handle contructor initializer as a statement in top-level block. + +2008-05-30 Marek Safar + + * attribute.cs: Don't mix old and new corlib types when emitting corlib + security attributes. + +2008-05-24 Marek Safar + + * ecore.cs, expression.cs: Small IVariable refactoring. + +2008-05-22 Marek Safar + + * assign.cs (LocalTemporary): Implemented CreateExpressionTree. + +2008-05-21 Marek Safar + + * cs-parser.jay: Removed redundant catch type check. + +2008-05-21 Marek Safar + + A fix for bug #390372 + * nullable.cs: Set correct return type. + +2008-05-21 Marek Safar + + A fix for bug #391062 + * typemanager.cs: Fixed crash when comparing null types. + +2008-05-21 Marek Safar + + A fix for bug #391871 + * cs-parser.jay: Better error handling for invalid catch type. + +2008-05-20 Marek Safar + + A fix for bug #392155 + * cs-tokenizer.cs: Fixed casting of byte and decimal expression. + +2008-05-15 Marek Safar + + A fix for bug #390666 + * ecore.cs (BetterExpressionConversion): Unwrap each Expression + expressions. + +2008-05-15 Marek Safar + + * class.cs, expression.cs, statement.cs: Removed a hack, setting block flag + in getter. + +2008-05-13 Marek Safar + + A fix for bug #389625 + * delegate.cs, generic.cs: Some progress on method group return type + inference. + +2008-05-13 Marek Safar + + A fix for bug #378419 + * namespace.cs: Inspect also parent namespaces not only namespace entries. + +2008-05-12 Marek Safar + + * class.cs (Constructor): Added IsCompilerGenerated. + +2008-05-12 Marek Safar + + * expression.cs: Enum binary operators can accept non-enum operand only when + is implicitly convertible to underlying type. + +2008-05-12 Marek Safar + + A fix for bug #389272 + * support.cs: Workaround System.InvalidOperationException for enums. + +2008-05-12 Marek Safar + + A fix for bug #389073 + * convert.cs: More undocumented explicit IntPtr/UIntPtr conversions. + +2008-05-10 Marek Safar + + * driver.cs: Split Parse. + + * location.cs (LookupFile): Uses string.Empty. + +2008-05-07 Marek Safar + + * expression.cs, parameter.cs: Small ParameterReference clean up. + +2008-05-07 Marek Safar + + * anonymous.cs, codegen.cs, convert.cs, ecore.cs: Removed uber ugly TempEc + hack. Fixes #387502. + +2008-05-06 Martin Baulig + + * class.cs (Constructor.Emit): Fix the logic whether to emit + symbol information. + +2008-05-06 Raja R Harinath + + Fix #385503 + * iterators.cs (Iterator.CurrentBlock.DoEmit): Don't emit + InvalidOperationException when the iterator is before the start or + after the end. + +2008-05-06 Marek Safar + + * nullable.cs (NullCoalescingOperator): Result is underlying type of left, + when left is nullable type. + +2008-05-06 Marek Safar + + A fix for bug #386628 + * expression.cs (LocalVariableReference): Continue in resolving when + variable is not assigned. + +2008-05-05 Marek Safar + + * nullable.cs, statement.cs (Unwrap): Store non-variable expression in all + nullable operations. + +2008-05-04 Marek Safar + + * nullable.cs, statement.cs (Unwrap): Don't duplicate variable expressions, + it saves many redundant temporary variables for nullable operations. + +2008-05-03 Marek Safar + + * assign.cs: EventAddOrRemove is a statement and cannot have a type. + + * cfold.cs, constant.cs, expression.cs: Share Error_OperatorCannotBeApplied + method. + + * nullable.cs: Constant coalescing operator optimizations. + +2008-05-03 Marek Safar + + * constant.cs: Use unsigned conversion for values which are unsigned only. + +2008-05-03 Marek Safar + + * convert.cs, literal.cs, nullabel.cs, typemanager.cs: Implemeted null + coalescing operator as it should be. + +2008-05-02 Marek Safar + + A fix for bug #371016 + * expression.cs: All predefined delegate operators require implicit method + group conversion. + +2008-05-02 Marek Safar + + * constant.cs: Emit long constant as uint when fits the range. + + * convert.cs, expression.cs: Fixed few unsafe conversions. + +2008-05-02 Marek Safar + + * convert.cs, literal.cs: Don't wrap implicit reference conversion to object + +2008-05-02 Raja R Harinath + + Fix #385758 + * convert.cs (ImplicitNumericConversion): Don't modify the type of + 'expr'. + * ecore.cs (EmptyCast.Create): Flatten nested EmptyCasts. + +2008-05-01 Marek Safar + + * constant.cs, literal.cs: IsLiteral property for error reporting. + + * ecore.cs, expression.cs: Implemented Property expression. + +2008-05-01 Marek Safar + + * class.cs, modifiers.cs, flowanalysis.cs: New BACKING_FIELD flag. + + * nullable.cs: Implemented nullable coalescing null operator. + + * ecore.cs, expression.cs: Expression trees work. + +2008-05-01 Marek Safar + + * ecore.cs: CreateExpressionTree is finally abstract. + + * expression.cs, linq.cs: Updated. + +2008-05-01 Marek Safar + + * expression.cs, ecore.cs: Block base access expression inside expression + tree. + +2008-05-01 Marek Safar + + A fix for bug #385058 + * expression.cs: User-defined operator implementations always take + precedence over predefined operator implementations. + +2008-04-30 Marek Safar + + * assign.cs, anonymous.cs, lambda.cs, nullable.cs, ecore.cs, linq.cs, + class.cs, iterators.cs, expression.cs, attribute.cs: Filled a few more + expression tree conversions. + +2008-04-30 Marek Safar + + * typemanager.cs, ecore.cs, class.cs, expression.cs, doc.cs: Merged all + operators method details to Operator class. + +2008-04-30 Marek Safar + + * anonymous.cs: Pass unsafe flags to anonymous container. + + * ecore.cs, expression.cs, statement.cs: Block unsafe pointer operations + inside expression tree. + +2008-04-29 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.Position): Added `line'. + (Tokenizer.PopPosition): Also restore the `line'. + +2008-04-29 Marek Safar + + * delegate.cs: Implemented Invoke expression. + +2008-04-29 Marek Safar + + * expression.cs: Fixed equality reference comparison regression. + +2008-04-29 Marek Safar + + * ecore.cs: Clean up EmptyCast hack. + + * expression.cs, nullable.cs: Implemented enum binary and unary operations + using correct conversion rules. Also fixes #383993. + +2008-04-28 Martin Baulig + + * class.cs (Constructor.Emit): Don't emit debugging information + for generated default .ctor's. + +2008-04-28 Marek Safar + + * convert.cs: Empty-cast ushort to int conversion. + +2008-04-28 Marek Safar + + A fix for bug #384191 + * ecore.cs, expression.cs: Fixed expression cloning. + +2008-04-28 Marek Safar + + * ecore.cs, delegate.cs, assign.cs: Few tweaks for recent changes. + +2008-04-28 Raja R Harinath + + Fix #381559, test-638.cs, test-639.cs + * assign.cs (CompoundAssign.Helper): New wrapper. + (CompoundAssign.DoResolve): Use it to wrap the nested 'target' + access. + * ecore.cs (MethodGroupExpr.VerifyArgumentsCompat) : + Pass unconverted expressions to the params array creation expression. + (FieldExpr.EmitAssign): Don't special-case StringConcat. + (PropertyExpr.EmitAssign): Likewise. + * expression.cs (ArrayCreation.ResolveArrayElement): Keep track of the + element if it is of kind CompoundAssign.Helper. + (ArrayCreation.Emit): If we saw a CompoundAssign.Helper, emit it + first before anything else. + (ArrayAccess.EmitAssign): Don't special-case StringConcat. + (ArrayAccess.LoadArrayAndArguments): Simplify. + +2008-04-27 Marek Safar + + * expression.cs: Fixed cloning of typeof(void). + +2008-04-27 Raja R Harinath + + * assign.cs (Assign.DoResolve): Remove support for EventExprs. + (Assign.Emit): Likewise. Move it to ... + (CompoundAssign.DoResolve): ... here and ... + (CompoundAssign.Emit): ... here. + (EventAddOrRemove): New helper to handle += and -= on events, and + avoid the use of BinaryDelegates. + * ecore.cs (EventExpr.DoResolveLValue): Emit CS0070 unconditionally. + (EventExpr.EmitAddOrRemove): Improve. + * delegate.cs (DelegateInvocation.DoResolve): Simplify slightly. + + * cs-parser.jay (type) : Don't + create VarExprs for 'foo.bar.var'. + * ecore.cs (VarExpr.InferType): Rename from DoResolveLValue, which + is a highly inappropriate name for its functionality. + +2008-04-26 Raja R Harinath + + Simplify handling of multiple assignments + * assign.cs (Assign): Clear out all 'embedded assign' gunk. Make + inheritable-only. + (SimpleAssign): New. Class to be used for normal assignments. + * anonymous.cs, class.cs, cs-parser.jay: Update to changes. + * expression.cs, parameter.cs, statement.cs: Likewise. + +2008-04-25 Marek Safar + + * ecore.cs, expression.cs, nullable.cs: Implemeted enum binary add operation + for incompatible underlying types, more to come, uff. + +2008-04-26 Raja R Harinath + + Fix gtest-388.cs + * expression.cs (VariableReference.EmitAssign) : + Handle 'leave_copy'. + +2008-04-25 Marek Safar + + * expression.cs, nullable.cs: Implemented UnaryPlus expression. + +2008-04-24 Raja R Harinath + + Fix test-636.cs. Sprinkle a few more 'EmitSideEffect's around + * expression.cs (Unary.TryReduceConstant): Unwrap SideEffectConstant. + * statement.cs (While, Do, For): Allow test to have side effects. + (For.DoEmit): Always emit InitStatement. + + Fix test-635.cs + * expression.cs (Binary.DoResolve) : + Always create SideEffectConstant. + (Binary.EnumLiftUp): Don't assume that the enumeration constant is + of type EnumConstant. + + * expression.cs (Binary.EmitBranchable) : + Handle 'right' being SideEffectConstant of type 'bool'. + + * expression.cs (Binary.EmitBranchable) : + Use left.EmitBranchable instead of open coding it, so as to + improve optimization opportunities. + + * constant.cs (SideEffectConstant.EmitSideEffect): Simplify slightly. + + * ecore.cs (Expression.EmitBranchable): Document some non-obvious + assumptions. + (Expression.EmitSideEffect): Document. + +2008-04-23 Marek Safar + + * expression.cs: Implemented NewArrayBounds, TypeIs, and TypeAs expressions. + +2008-04-23 Marek Safar + + * constant.cs, statement.cs: Use EmitSideEffect for constant if statement. + +2008-04-23 Marek Safar + + * ecore.cs, expression.cs, delegate.cs: Implemeted delegate instantiation + conversion to expression tree. + +2008-04-23 Marek Safar + + * ecore.cs: Removed unused expression. + +2008-04-22 Marek Safar + + * expression.cs: Implemented NegateChecked and New expressions. + +2008-04-22 Marek Safar + + * convert.cs, nullable.cs, expression.cs: Implemented Negate expression. + +2008-04-22 Raja R Harinath + + Fix #351102 + * anonymous.cs (AnonymousMethodExpression.DoResolve): Mark as + needing final 'ret' instruction. + +2008-04-22 Marek Safar + + * expression.cs: Disabled lifted binary conversion on ISO-1 profiles. + +2008-04-21 Marek Safar + + * expression.cs: Emit ldnull and not null expression as an instance argument + of static method expression calls. + +2008-04-21 Marek Safar + + A fix for bug #378200 + * expression.cs: Fixed crash when creating parameterless expression tree + method call. + +2008-04-21 Marek Safar + + A fix for bug #375297 + * anonymous.cs: Fixed crash when inferring from null argument anonymous + method. + +2008-04-21 Marek Safar + + A fix for bug #377596 + * decl.cs, class.cs: Emit delegate type argument attributes. + +2008-04-21 Marek Safar + + A fix for bug #365314 + * generic.cs, ecore.cs: Type parameter declaration cannot be of generic type + +2008-04-21 Marek Safar + + * cs-parser.jay, expression.cs: ComposedCast can work with type expressions + only. + +2008-04-21 Marek Safar + + * generic.cs (TypeParameter): Removed redundant location. + +2008-04-19 Marek Safar + + * generic.cs, parameter.cs, namespace.cs, ecore.cs, class.cs, decl.cs, + delegate.cs, iterators.cs, cs-parser.jay, const.cs, enum.cs: Use + FullNamedExpression in all declaration type expression, statements will come + later. + +2008-04-18 Marek Safar + + * generic.cs, namespace.cs, ecore.cs, class.cs, decl.cs, generic-mcs.cs, + nullable.cs, expression.cs, enum.cs, doc.cs: Cleaning up type expressions. + +2008-04-18 Marek Safar + + * parameter.cs, delegate.cs, cs-parser.jay, expression.cs: Removed unused + code. + +2008-04-17 Marek Safar + + * decl.cs, class.cs, generic.cs: Verify partial parts type parameters and + constraints. + +2008-04-17 Marek Safar + + * decl.cs, class.cs, cs-parser.jay, ecore.cs, expression.cs: Unify all type + name expressions. + Also fixes #340463. + +2008-04-17 Raja R Harinath + + Hook up 'EmitSideEffect' + * constant.cs (Constant.EmitSideEffect): New. + (SideEffectConstant.Emit): Simplify. Use EmitSideEffect. + (SideEffectConstant.EmitSideEffect): New. + * ecore.cs (BoxedCast.EmitBranchable): Remove. We can't use an + unconditional branch in EmitBranchable. + (FieldExpr.EmitBranchable): New. + * expression.cs (Unary.EmitSideEffect): New. + (Binary.EmitSideEffect): New. + (VariableReference.EmitSideEffect): New. Do nothing. + +2008-04-16 Raja R Harinath + + Introduce 'EmitSideEffect' + * ecore.cs (Expression.EmitSideEffect): New. + (TypeCast): Rename from EmptyCast. + (EmptyCast): New. + (EmptyCast.EmitBranchable, EmptyCast.EmitSideEffect): Implement. + (BoxedCast.EmitBranchable, BoxedCast.EmitSideEffect): Implement. + * convert.cs, nullable.cs: Update to changes. + +2008-04-16 Marek Safar + + * class.cs, cs-parser.jay: Early check for base types expression. + +2008-04-16 Marek Safar + + * decl.cs (MemberName): Declare PrettyName as obsolete. + +2008-04-16 Marek Safar + + * namespace.cs: Use MemberName comparison. + +2008-04-16 Raja R Harinath + + Fix build break + * decl.cs (MemberName.PrettyName): New. Replaces the misnamed + FullName. + (MemberName.MethodName, MemberName.GetSignatureForError): Improve. + (MemberName.FullyQualifiedName): New. Provides the functionality + that users assume FullName would have. + * ecore.cs, namespace.cs: Update to changes. + + * statement.cs (Using.assign): Make into ExpressionStatement. + (Using.EmitPreTryBody): Simplify. + +2008-04-16 Marek Safar + + * report.cs: ColorFormat is protected. + + * rootcontext.cs: Unused fields clean-up. + + * namespace.cs: Made UsingEntry name private. + +2008-04-16 Marek Safar + + * cs-tokenizer.cs, location.cs: Removed unused field. + +2008-04-16 Jan Oravec + Raja R Harinath + + Fix #379822 + * constant.cs (SideEffectConstant.value): Rename from 'left'. + (SideEffectConstant.side_effect): Rename from 'right'. + (SideEffectConstant..ctor): Normalize 'side_effect'. + (SideEffectConstant.Emit): Emit 'value', not 'side_effect' as the + value of this constant. + * cfold.cs: Update to changes. + +2008-04-15 Marek Safar + + * cs-paser.jay: Removed unused variable. + + * driver.cs: Made Compile instance method. + +2008-04-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.MergeChild): Simplify. + +2008-04-15 Marek Safar + + * cs-paser.jay, namespace.cs: Simplified handling of namespace imports. + +2008-04-13 Jb Evain + + * namespace.cs: update the System.Core fullname for 2.1 + * driver.cs: update the list of required assemblies for 2.1. + Merged from the Moonlight 2 branch. + +2008-04-11 Marek Safar + + * assign.cs, ecore.cs, expression.cs, nullable.cs: More work on nullable + types and user defined operators. User operators arguments has to be checked + for null value before invocation, which also means no operator is called + when any argument is not convertible to unwrapped nullable type. + +2008-04-09 Marek Safar + + * convert.cs, ecore.cs, expression.cs, nullable.cs: Initial refactoring + of Unary expressions to follow operator overloading rules precisely. + Also fixes #321794, #323794 + +2008-04-08 Marek Safar + + * cs-parser.jay, expression.cs: Don't wrap Indirection expression in Unary + expression. + +2008-04-08 Marek Safar + + * expression.cs, ecore.cs: Implemented MemberInit expression. + +2008-04-08 Raja R Harinath + + Fix mono/tests/exception4.cs + * statement.cs (ExceptionStatement, TryCatch): Revert to using + ec.NeedReturnLabel () rather emitting a 'nop'. + + * statement.cs (ExceptionStatement.SomeCodeFollows): A hook for a + simple heuristic. + (TryCatch.SomeCodeFollows): Likewise. + * flowanalysis.cs (FlowBranchingException): Call 'SomeCodeFollows' + for 'break', 'continue' and 'return' statements inside a try. + We're fairly sure that the generated IL stream will have more + instructions textually following the try. + (FlowBranchingTryCatch): Likewise. + + * statement.cs (Throw.Resolve): Move CS0156 and CS0724 testing ... + * flowanalysis.cs (FlowBranching.CheckRethrow): ... here and to its + overrides. + + * statement.cs (CollectionForeach.DisposableWrapper): Make a true + wrapper -- forward everything to CollectionForeach. + (CollectionForeach.NonDisposableWrapper): New. + (CollectionForeach.EmitFinallyBody): Use 'endfinally' instruction + instead of a pop + branch to end. + +2008-04-07 Marek Safar + + A fix for bug #377485 + * assign.cs, expression.cs, decl.cs, class.cs, ecore.cs, namespace.cs: + Propagate location for extension method groups. Report conversion failure at + right place. + +2008-04-07 Marek Safar + + * anonymous.cs, expression.cs, ecore.cs, typemanager.cs: Implemented + ListInit and Field expressions. + +2008-04-06 Raja R Harinath + + * iterators.cs (Iterator.EmitMoveNext): Remove try/fault wrapper. + Since $PC is always -1 inside the body of MoveNext, the fault + handler is a no-op. + * flowanalysis.cs (FlowBranchingException.EmitFinally): Kill. + * statement.cs (ExceptionStatement.emit_finally): Likewise. + (ExceptionStatement.ResolveFinally): Drop 'branching' argument. + + The denouement! Fix #324708 + * iterators.cs (Iterator.EmitMoveNext): Reset $PC to -1 on entry. + (Iterator.EmitYieldBreak): We no longer need to reset $PC. + * statement.cs (ExceptionStatement.DoEmit): Actually emit the + 'finally' inside the finally clause. + + * statement.cs (ExceptionStatement.DoEmit): Emit try/finally block + inside an iterator. Don't emit the body of the 'finally' inside + the finally clause yet. + + Use the ResumableStatement infrastructure for MoveNext () + * iterators.cs (Iterator.EmitMoveNext_NoResumePoints): New. + (Iterator.EmitMoveNext): Use 'resume_points'. Get rid of + 'old_resume_points'. Move dispatcher upfront. + (Iterator.MarkYield): Mark the 'resume_point' of a Yield. + * statement.cs (ExceptionStatement.DoEmit): Emit a dispatcher if + in an enumerator. This encodes the main fix in this patch series + -- we can only jump into the first instruction of a try from the + outside, but we want to emit try/finally regions in iterators and + resume in the middle of them. + +2008-04-05 Raja R Harinath + + * statement.cs (ExceptionStatement.ResolveFinally): Move setting + of NeedReturnLabel here. + + Introduce a common point for emitting try/finally to IL + * statement.cs (ExceptionStatement.DoEmit): New. Combines all the + features of the various subclasses, which are now driven by ... + (ExceptionStatement.EmitPreTryBody): ... this and ... + (ExceptionStatement.EmitTryBody): ... this and the original + EmitFinallyBody. + (TryFinally, Lock, Using, UsingTemporary, DisposableWrapper): + Remove DoEmit and update to follow above protocol. + + * statement.cs (ExceptionStatement.EmitForDispose): If all labels + of the dispatcher are the same, skip emitting the 'switch'. + * iterator.cs (Iterator.EmitDispose): Update to changes. + + Clean up handling of 'using' statement + * statement.cs (UsingTemporary): New. Carved out of ... + (Using): ... this. Simplify drastically. Handle exactly + one variable. + * cs-parser.jay (using_statement): Split. Create UsingTemporary + or Using as appropriate. If there are multiple variable declared, + create nested Using statements. + (resource_acquisition): Kill. + + * statement.cs (ExceptionStatement.EmitForDispose): Use + EmitFinallyBody, not EmitFinally. + + * flowanalysis.cs (FlowBranching.StealFinallyClauses): Remove. + * iterator.cs: Update to changes. + + Start using the ResumableStatement infrastructure + * statement.cs (ResumeableStatement.PrepareForDispose): New. + (ResumableStatement.EmitForDispose): New. + (ExceptionStatement): Override them. + * iterators.cs (Iterator.EmitDispose): Use PrepareForDispose and + EmitForDispose to create the body of the Dispose method. Don't + use OldResumePoint. + + * iterator.cs (Iterator.AddResumePoint): Move here from ... + * statement.cs (Toplevel.AddResumePoint): ... here. + (Toplevel.MoveNextStatement.Resolve): Create FlowBranchingIterator. + * flowanalysis.cs (FlowBranchingIterator): New. + * codegen.cs (EmitContext): Update to changes. + + * iterators.cs (Iterator.OldResumePoint): Rename from ResumePoint. + (Iterator.old_resume_points): Rename from 'resume_points'. + (Iterator.MoveNextStatement): Remove unused class. + + New infrastructure for try/finally in iterators (still unused) + * flowanalysis.cs (FlowBranching.AddResumePoint): New. + (FlowBranchingToplevel.AddResumePoint): Hook into + ToplevelBlock.AddResumePoint. + (FlowBranchingTryCatch): Move CS01626 and CS01631 checks here. + (FlowBranchingException): Hook into ExceptionBlock.AddResumePoint. + * statement.cs (ToplevelBlock.AddResumePoint): New. Collect + resume points and assign program-counter values. + (ExceptionBlock.AddResumePoint): Collect resume points for + de-muxer at the top of try block. + * iterators.cs (Yield.CheckContext): Simplify. + (Yield.Resolve): Use FlowBranching.AddResumePoint. + +2008-04-04 Raja R Harinath + + * flowanalysis.cs (FlowBranching.AddReturnOrigin): Change Location + argument to an ExitStatement. + (FlowBranchingException): Refactor saved origins code. + * statement.cs (ExitStatement): Update to cahges. + * iterator.cs (YieldBreak): Likewise. + + * statement.cs (ResumableStatement): New. Common base class for + YieldReturn and ExceptionStatement. + (ExitStatement): New. Common base class for Return and YieldBreak. + (Return): Update to changes. + * iterator.cs (YieldBreak): Likewise. + * lambda.cs (ContextualReturn): Likewise. + + Fix #377028 + * ecore.cs (Expression.ResolveAsTypeStep): If '!silent' attempt to + emit a meaningful error message. + + Fix #324765, #319508 + * flowanalysis.cs (VariableInfo.IsEverAssigned): New. + (VariableInfo.SetAssigned): Set it. + * statement.cs (Block.UsageWarning): Use 'IsEverAssigned' to + determine if CS0219 or CS0168 is appropriate. Don't use + flow-analysis information. + (Block.Resolve): Use ec.EndFlowBranching, not ec.DoEndFlowBranching. + * codegen.cs (EmitContext.DoEndFlowBranching): Kill. Inline into ... + (EmitContext.EndFlowBranching): ... this. + +2008-04-03 Marek Safar + + * class.cs, typemanager.cs: Emit volatile field with IsVolatile modifier. + +2008-04-03 Marek Safar + + A fix for bug #376508 + * convert.cs, expression.cs: Fixed difference between ImplicitConversion and + ImplicitConversionExists. + +2008-04-03 Marek Safar + + * expression.cs (Binary): Added remaining binary operators to expression + tree builder. + + * nullable.cs: Optimize shift with null argument. + +2008-04-03 Raja R Harinath + + Fix minor IL regression + * statement.cs (TryCatch..ctor): Add 'inside_try_finally' argument. + (TryCatch.DoEmit): Use it to avoid creating another ExceptionBlock. + * cs-parser.jay (try_statement): Update to changes. + + * statement.cs (TryFinally.need_exc_block): Delete. + (TryFinally): Update to changes. + + Now all ExceptionStatements are unconditional + * statement.cs (CollectionForeach.DisposableWrapper): New. + Extract out the try/finally code into a new wrapper. + (CollectionForeach.Resolve): Use it to simplify the code. + +2008-04-02 Raja R Harinath + + Start at simplifying ExceptionStatement semantics a bit + * statement.cs (TryCatch, TryFinally): Split 'Try' into two pieces. + * cs-parser.jay (try_statement): Update to changes. + (opt_catch_clauses): Remove. + * flowanalysis.cs: Update to changes. + (FlowBranching.BranchingType.TryCatch): New. + (FlowBranchingTryCatch): New. + + * flowanalysis.cs (FlowBranching.BranchingType.SwitchSection): Kill. + (FlowBranching.CreateBranching): Update to changes. + (FlowBranchingBlock.AddSibling): Add sanity check. + * codegen.cs (EmitContext.StartFlowBranching) : + Update to changes. + + * iterators.cs (Iterator.MarkFinally): Remove. + * statement.cs (ExceptionStatement): Update to changes. + + Add support for skipping over finally blocks at runtime. First + in a series to fix #324708 + * iterators.cs (Iterator.SkipFinally): New LocalBuilder. + (Iterator.EmitMoveNext): Initialize it. + * statement.cs (ExceptionStatement.EmitFinally): Use it to emit a + branch over the body of the 'finally' clause. + +2008-03-31 Raja R Harinath + + Avoid lopsided use of Foo/DoFoo names + * statement.cs (ExpressionStatement.EmitFinallyBody): + Rename from EmitFinally. + (ExpressionStatement.EmitFinally): Rename from DoEmitFinally. + * iterator.cs: Update to changes. + +2008-04-02 Marek Safar + + * ecore.cs, expression.cs, nullable.cs: ConditionalLogicalOperator is now + based on UserOperatorCall. More binary nullable operators clean up. + +2008-04-02 Martin Baulig + + * symbolwriter.cs: Remove the `#if !DISABLE_TERRANIA_CHANGES' conditionals. + +2008-04-02 Marek Safar + + * nullable.cs: Merge user and empty conversions when lifting expression + trees. + + * expression.cs (StringConcat): Implemented expression tree representation. + +2008-04-01 Marek Safar + + * nullable.cs: When lifting null literal and a user operator exists, no call + is made. + +2008-04-01 Marek Safar + + * nullable.cs, ecore.cs, expression.cs: Convert null arithmetic to lifted + null. + +2008-04-01 Marek Safar + + * nullable.cs, expression.cs: Use namespace instead heavily nested + monster abstract class. + +2008-04-01 Marek Safar + + * ecore.cs, convert.cs, constant.cs, nullable.cs, expression.cs: Implemented + lifting of null literal and user operators. Clean up of some temporary + nullable hacks. + +2008-03-30 Raja R Harinath + + Fix #368224, test-629.cs + * flowanalysis.cs (FlowBranching.StealFinallyClauses): Return true + if it crossed an unwind-protect boundary. + * iterators.cs (Yield.CheckContext): Relax check for 'yield break'. + (Yield.Resolve, Yield.DoEmit): Track whether the yield occurs + inside an unwind-protected region. + (YieldBreak.Resolve, YieldBreak.DoEmit): Likewise. + (Iterator.MarkYield): Add 'unwind_protect' parameter. Emit a + 'leave' instead of a 'br' if unwind-protected. + (Iterator.EmitYieldBreak): Likewise. + +2008-03-29 Gert Driesen + + * driver.cs: Only define versioninfo resources if no win32 resource + file was specified. + +2008-03-28 Marek Safar + + A fix for bug #372375 + * convert.cs: Fixed boxing of nullable types. + +2008-03-28 Marek Safar + + * typemanager.cs: Initialize InternalsVisibleTo as the very first optional + type. + +2008-03-28 Marek Safar + + A fix for bug #374619 + * nullable.cs: Fixed guarding of EmitBitwiseBoolean. + +2008-03-27 Marek Safar + + * lambda.cs: Check return type only for invocation. + +2008-03-27 Marek Safar + + A fix for bug #374214 + * ecore.cs: Correctly report argument type mismatch. + +2008-03-27 Marek Safar + + * convert.cs (ImplicitReferenceConversionCore): Correctly compare enum type + and not rely on broken IsEnum. + +2008-03-27 Marek Safar + + * nullable.cs: New file, extracted from generic.cs. + + * generic.cs, generic-mcs.cs, *.csproj, *.sources: Updated. + +2008-03-27 Marek Safar + + * generic.cs, convert.cs, generic-mcs.cs, expression.cs: Added lifting of + predefined comparison operators and null literals. + + * report.cs: New warning ID. + +2008-03-25 Marek Safar + + A fix for bug #370577 + * lambda.cs: Check return type too. + +2008-03-25 Marek Safar + + A fix for bug #372846 + * class.cs: Automatic properties can be declared as unsafe. + +2008-03-20 Marek Safar + + * location.cs: Use string based concatenation. + + * expression.cs: LiftedBinaryOperator is gmcs only. + +2008-03-20 Marek Safar + + * generic.cs, literal.cs, ecore.cs, expression.cs: Ongoing work on nullable + conversions rules and expression trees. + +2008-03-19 Marek Safar + + * delegate.cs: Use extension method source as delegate target. + +2008-03-19 Marek Safar + + * generic.cs, generic-mcs.cs, expression.cs, ecore.cs: Rewrote nullable + binary operations to be purely based on binary operations and optimized + emitted code (30% less in some cases). Introduced ReducedExpression for ETs + and other ET refactoring. + + * typemanager.cs: Fixed warning. + +2008-03-17 Marek Safar + + * class.cs, decl.cs, delegate.cs: Do protected modifier check on each member + + * symbolwriter.cs: Fixed. + +2008-03-17 Marek Safar + + * anonymous.cs, driver.cs: Reset anonymous types counters. + +2008-03-17 Marek Safar + + * ecore.cs (MethodGroupExpr): Skip first candidate, it's already the best. + + * class.cs: Use fullname for all type member definitions. + +2008-02-19 Martin Baulig + + * class.cs + (IMethodData.EmitExtraSymbolInfo): New interface method. + (MethodData.Emit): Call method.EmitExtraSymbolInfo(). + (MethodOrOperator.EmitExtraSymbolInfo): Implement this new + interface method here as an empty public virtual method. + + * anonymous.cs + (AnonymousMethodMethod.ctor): Added `string real_name' argument. + (AnonymousMethodMethod.EmitExtraSymbolInfo): Override and call + CodeGen.SymbolWriter.SetRealMethodName(). + +2008-02-18 Martin Baulig + + * anonymous.cs + (ScopeInfo.EmitType): Override this and emit debugging + information for captured variables. + (RootScopeInfo.EmitType): Override this and emit symbol + information for a captured `this'. + +2008-02-15 Martin Baulig + + * iterators.cs: Emit debugging info. + + * codegen.cs + (EmitContext.Flags): Add `OmitDebuggingInfo'. + (EmitContext.OmitDebuggingInfo): New public property. + + * statement.cs + (While): Override Emit() and don't emit symbol info there; do it + inside DoEmit() instead. + (Block.Emit): Omit symbol information while emitting the scope + initializers; don't ec.Mark() the `EndLocation'. Fix the lexical + block logic. + (ExplicitBlock.IsIterator): Moved here from `ToplevelBlock'. + (ToplevelBlock.MakeIterator): Pass the `flags' to `ExplicitBlock's + .ctor to make `IsIterator' work. + +2008-03-14 Martin Baulig + + * symbolwriter.cs: Added the new symbol writer function from the + debugger's `terrania' branch; temporarily enclose them inside + `#if !DISABLE_TERRANIA_CHANGES' conditionals until I'm back from + my vacations. + +2008-03-14 Martin Baulig + + * symbolwriter.cs + (SymbolWriter): Make this a public static class. + + * codegen.cs + (CodeGen.SymbolWriter): Removed; use the new static `SymbolWriter' + class instead of using `if (CodeGen.SymbolWriter != null)' everywhere. + +2008-03-14 Marek Safar + + A fix for bug #370577 + * statement.cs, lambda.cs: Added extra limitations when dealing with void + return type. + +2008-03-14 Marek Safar + + * typemanager.cs (CSharpName): Made 250 times faster. + +2008-03-13 Marek Safar + + * ecore.cs, expression.cs: Emit conversion for ET shift argument. + +2008-03-12 Marek Safar + + * generic.cs, typemanager.cs, enum.cs, codegen.cs, statement.cs: Try not to + crash when predefined field does not exist. + +2008-03-12 Marek Safar + + * ecore.cs (PropertyExpr): Fixed IsSingleDimensionalArrayLength regression. + +2008-03-12 Marek Safar + + * class.cs (FixedField): Don't crash when contructors are missing. + +2008-03-11 Marek Safar + + * typemanager.cs, namespace.cs, literal.cs, ecore.cs, class.cs, decl.cs, + convert.cs, constant.cs, expression.cs, statement.cs: Use same method to + check internal types accessibility for internal and external types. + Replaced EnumToUnderlying by GetEnumUnderlyingType. + +2008-03-11 Marek Safar + + * support.cs, typemanager.cs, pending.cs, ecore.cs, class.cs, delegate.cs + convert.cs, const.cs, anonymous.cs, constant.cs, expression.cs, + attribute.cs, statement: Use corect instance of predefined types (work + related to #364674). + +2008-03-07 Marek Safar + + * expression.cs (TypeOfVoid): Fixed predefined method initialization. + +2008-03-07 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, rootcontext.cs, ecore.cs, + class.cs, delegate.cs, iterators.cs, const.cs, constant.cs, driver.cs, + expression.cs, attribute.cs, codegen.cs, statement.cs: TypeManager optional + predefined types clean up, delayed predefined types members initialization + (work related to #364674). + +2008-03-05 Marek Safar + + * typemanager.cs (IsFriendAssembly): InternalsVisibleTo is not mandatory. + +2008-03-05 Marek Safar + + * typemanager.cs, parameter.cs, rootcontext.cs, ecore.cs, class.cs, decl.cs, + delegate.cs, convert.cs, driver.cs, attribute.cs, codegen.cs: TypeManager + predefined types clean up (work related to #364674). + +2008-03-04 Marek Safar + + * ecore.cs: Print an error message instead of throwing exception. + +2008-03-04 Marek Safar + + * generic.cs, typemanager.cs, literal.cs, convert.cs, cfold.cs, constant.cs, + expression.cs, statement.cs: Unififed null literal representation. + +2008-03-03 Marek Safar + + * anonymous.cs, cfold.cs, convert.cs, delegate.cs, doc.cs, ecore.cs, + expression.cs: Refactored binary operators resolve phase and improved speed. + The nullable code is still missing and won't work correctly, more fixes + required. + + It also fixes #323726, #324312, #324248, and many other unreported issues. + +2008-02-29 Zoltan Varga + + * report.cs (FeatureIsNotAvailable): Use 'mcs1' instead of 'mcs', and 'mcs' + instead of 'gmcs'. + +2008-02-27 Marek Safar + + * ecore.cs: Clean-up and split BetterConversion. + +2008-02-25 Raja R Harinath + + Fix #363791 + * enum.cs (EnumMember.Value): Only access 'value' if + ResolveValue says it's ok. + (EnumMember.DoResolveValue): Don't set prev_member.value. + (Enum.GetDefinition): Reverse arguments of Equals -- + EnumMember.Value can return 'null'. + + * statement.cs (Switch.Error_AlreadyOccurs): Fix typo in name. + +2008-02-22 Marek Safar + + * generic.cs, expression.cs: More ongoing work on expression trees. + +2008-02-21 Marek Safar + + * class.cs, typemanager.cs: Rewrote operator matching logic to correctly + handle missing matches when mutiple operators exist. + +2008-02-20 Marek Safar + + A fix for bug #363218 + * expression.cs (ArrayCreation.Clone): Deal with multi-dimensional + initializers. + +2008-02-20 Marek Safar + + * expression.cs, constant.cs, cfold.cs: Yet another side-effect constant + update. This time to deal correctly with SideEffectConstant expression used + as an argument for another constant folding. + +2008-02-20 Raja R Harinath + + * typemanager.cs (DropGenericMethodArguments): Ensure we get an underlying + MethodBuilder. + +2008-02-19 Marek Safar + + * constant.cs, cfold.cs: SideEffectConstant results can apply for folding. + +2008-02-19 Marek Safar + + A fix for bug #328136 + * expression.cs: Do not fold immediately LogicalAnd operators when the left + side is a false constant, because we still need to evaluate the right-hand + side. + + * statement.cs (If): Emit two types of boolean constants (simple constant, + side-effect constant). + +2008-02-19 Marek Safar + + * constant.cs (SideEffectConstant): Don't emit boolean constant. + + * expression.cs: Fold immediately LogicalAnd operators when both sides are + constants. + +2008-02-18 Marek Safar + + A fix for bug #361457 + * ecore.cs (IsApplicable): Params methods have lower priority. + + * support.cs: Return correct parameter modifier for params types. + +2008-02-18 Marek Safar + + * generic.cs (TypeParameter): Cache attribute target name. + + * support.cs: Removed unused variable. + + * typemanager.cs: Removed debugging leftover. + + * ecore.cs: Use local type instead of a property; + + * class.cs (VerifyMembers): Consider also parent to test whether type member + is local or public. + + * expression.cs (FullMethodDesc): Removed. + + * attribute.cs (IsValidArgumentType): Made static. + +2008-02-17 Raja R Harinath + + Cleanup to be more readable. + * Makefile (GMCS_PROFILE): Remove. + (COMPILER_NAME): New helper. + +2008-02-15 Miguel de Icaza + + * cs-tokenizer.cs: if a conditional expression happens inside a + (...) this also means that we do not need to de-ambiguate between + an parenthesized expression and a cast. + + Fixes 346484. + + * constant.cs (SideEffectConstant): a constant value that happens + to have a side effect. + + Fixes the build regressions introduced by the fix for #359789 + +2008-02-14 Rodrigo Kumpera + + * expression.cs (Conditional.Emit): when emitting the ternary + operator, use local variables to generate code verifiable code. + + The verifier cannot infer that the type on stack before the + stloc.0 is executed is of type ParentB. This happens because the + stack merge algorithm uses only parent types when deciding which + is the common type. This is described in Part III 1.8.1.3 of ECMA + 335. + + This code compiled with mcs is not verifiable under MS. The MS + verifier picks the first common interface of Foo and Bar, which is + wrong, but doesn't use a full join type of the 2 interfaces. + + CSC uses a clever hack to compile such code in a verifiable + way. It stores the intermediate values in a local variable with + the expected type. + + Fixes: #358102 + +2008-02-14 Miguel de Icaza + + * expression.cs: Do not fold BitwiseAnd operators when the left + side is a false constant, because we still need to evaluate the + right-hand side. + + Fixes #359789 + + * support.cs: Instead of throwing an InternalErrorException when + the position of the stream is outside the boundary of our buffer, + reset the state of the reader, and restart the reading from the + beginning of the file. + +2008-02-14 Marek Safar + + * generic.cs (TypeParameter.GetMembers): Is not supported operation. + +2008-02-14 Marek Safar + + A fix for bug #361686 + * decl.cs: A protected types used inside a private class which parents + derives from the protected class are accessible. + +2008-02-13 Marek Safar + + * generic.cs (ConstraintChecker): Use cached member lookup when looking for + the parameterless constructor. + +2008-02-13 Marek Safar + + * generic.cs, typemanager.cs, iterators.cs, codegen.cs: Refactored core + lookup methods to use standard member cache when doing member lookup. + +2008-02-12 Marek Safar + + * driver.cs: Don't report full path for referenced module as assembly error. + +2008-02-12 Marek Safar + + * Makefile: Fixed `qh' target to work on all machines. + + * report.cs, typemanager.cs, parameter.cs, ecore.cs, class.cs, anonymous.cs, + expression.cs, codegen.cs, statement.cs, doc.cs: Replaced type IsSubclassOf + and HasElementType with TypeManager implementation. + +2008-02-08 Marek Safar + + A fix for bugs #325134, #359749 + * expression.cs, ecore.cs: Try to resolve an extension method even if the + first binds point to non-method member expression. + +2008-02-08 Marek Safar + + * cs-parser.jay: Null coalescing operator is not part of ISO-1. + +2008-02-08 Marek Safar + + A fix for bugs #321394, #323028 + * generic.cs, parameter.cs, ecore.cs, class.cs, decl.cs, delegate.cs: + Reworked naive IsAccessibleAs implementation to handle nested types. + +2008-02-05 Jb Evain + + * class.cs: use generic type comparison for parameters + as well. + +2008-02-05 Marek Safar + + A fix for bug #325372 + * class.cs: Use generic type comparison when testing method signatures. + +2008-02-05 Marek Safar + + A fix for bug #357047 + * ecore.cs: Applied C# 3.0 changes to better conversion. + +2008-02-05 Marek Safar + + A fix for bug #358374 + * cs-parser.jay: Correctly set modifiers for all constructor types. + +2008-02-04 Marek Safar + + A fix for bug #355251 + * generic.cs: Added base class constraint based type inference. + +2008-02-01 Marek Safar + + A fix for bug #357255 + * decl.cs: One more missing visibility check. + +2008-02-01 Marek Safar + + * support.cs: Fixed broken return. + +2008-01-25 Marek Safar + + * report.cs: Correctly reset warnings count after probing. + +2008-01-25 Martin Baulig + + * namespace.cs + (NamespaceEntry.SymbolFileID): Make this work again after + MemberName.ToString() is gone. + +2008-01-25 Marek Safar + + * expression.cs: Implemented Divide, Equal, ExclusiveOr, GreaterThanOrEqual + expressions. + +2008-01-25 Marek Safar + + * generic.cs: Use full implicit conversion for type inference fixing. + +2008-01-24 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implemented Convert, ConvertChecked. + Fixed user operator conversions. + +2008-01-24 Marek Safar + + * generic.cs: Do nullable type to null comparison optimization during + resolve phase. + +2008-01-24 Marek Safar + + A fix for bug #355163 + * generic.cs: Enabled l-value resolve on nullable expressions. + +2008-01-24 Marek Safar + + A fix for bug #353986 + * class.cs: Ingore static ctors with parameters for any further checks. + +2008-01-24 Marek Safar + + A fix for bug #354310 + * namespace.cs: Removed redundant check. + +2008-01-24 Marek Safar + + A fix for bug #354928 + * expression.cs: ElementInitializers can be resolved only once. + +2008-01-24 Marek Safar + + * convert.cs, ecore.cs, expression.cs, generic.cs: Implemented Coalesce and + Condition expressions. + +2008-01-23 Marek Safar + + * codegen.cs: Fixed AssemblyBuilder initialization on other platforms. + +2008-01-22 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implicit bool? to bool conversion is + not allowed. + + * generic.cs: Implemented coalesce expression. + +2008-01-22 Marek Safar + + A fix for bug #355145 + * anonymous.cs, convert.cs, ecore.cs, generic.cs, lambda.cs: Implemented + expression tree type inference. + +2008-01-22 Raja R Harinath + + Fix #354663 + * expression.cs (Binary.IsUnsignedType): Fix typo. + +2008-01-22 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implemented NewArrayInit expression. + +2008-01-22 Marek Safar + + A fix for bug #355161 + * ecore.cs, expression.cs: Wider range of extension method supported + expressions. + +2008-01-22 Gert Driesen + + * codegen.cs: Use magic value for AssemblyBuilderAccess to instruct + AssemblyBuilder to operate in compiler context. Fixes mcs part of + bug #354970. + +2008-01-22 Marek Safar + + A fix for bug #355148 + * ecore.cs, expression.cs: Correctly report misused ref and out modifiers. + +2008-01-22 Miguel de Icaza + + * expression.cs (CreateExpressionTree): Add support for or and + logical or, and indent following the coding conventions. + + * typemanager.cs (LinqExpression): renamed from + ExpressionTreeManager, for a shorter name. + + Use TypeManager.CoreLookupType to lookup types from our core + assemblies and turn those into "Type" variables. + + Consumers that previously used "Namespace" and "Type" from this + class should instead use the TypeExpression which is a type that + is fully resolved (without involving the regular C# resolution + rules). + + This typically looks like this: + + TypeExpression texpr = new TypeExpression (LinqExpression.expression_type, loc); + new MemberAccess (texpr, name, type_arguments, loc) + + This avoids the problem in: #355178 + +2008-01-21 Marek Safar + + * cs-parser.jay, expression.cs: Check `namespace alias qualifier' language + feature in parser only as we do in other cases. + +2008-01-21 Marek Safar + + * attribute.cs, ecore.cs, class.cs, delegate.cs, expression.cs, linq.cs, + typemanager.cs: A refactoring of params arguments to reuse existing + expressions (params -> array initializer) to emit params argument instead + of specialized handling. + It was required by expression tree implementation and it has other benefits + as well, we now apply same optimization for params arguments as we do for + array initializers. + +2008-01-18 Marek Safar + + A fix for bug #353526 + * generic.cs: A type inference of params arguments may not required any + temporary array creation. + +2008-01-18 Marek Safar + + A fix for bug #353534 + * generic.cs, ecore.cs, expression.cs: A method group type inference is + supported for delegates only. + +2008-01-18 Marek Safar + + * generic.cs: Fixed 3.0 type inference fixing phase to determine a unique + type for more than 1 candidates. + +2008-01-18 Marek Safar + + * typemanager.cs, ecore.cs, expression.cs: Implemented ArrayLength and Call + expressions. + +2008-01-16 Marek Safar + + * generic.cs, typemanager.cs, lambda.cs, parameter.cs, ecore.cs, constant.cs, + expression.cs: Implemented Add, And, AndAlso, and ArrayIndex (without unary + operator) expressions. + +2008-01-16 Zoltan Varga + + * statement.cs: Avoid declaring an IL variable for this_variable since it is + not accessed from the generated IL. + +2008-01-14 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, ecore.cs, class.cs, delegate.cs, + iterators.cs, convert.cs, assign.cs, anonymous.cs, expression.cs, + statement.cs: The first expression tree implementation drop, mostly + infrastructure work. + +2008-01-14 Marek Safar + + * ecore.cs (IsNestedChild): Refactored. + +2008-01-11 Marek Safar + + * lambda.cs: Don't use a cast on unknown expression statement. + +2008-01-10 Geoff Norton + + * cs-tokenizer.cs: One more token to distinguish between method and lambda + arguments + +2008-01-09 Marek Safar + + * doc.cs: Report better /doc crash details. + +2008-01-09 Marek Safar + + A fix for bug #352536 + * ecore.cs, assign.cs, codegen.cs: Check event assignments. + +2008-01-08 Marek Safar + + A fix for bug #352287 + * ecore.cs, expression.cs: Do `this' access checking in all member access + expressions. + +2008-01-08 Marek Safar + + * rootcontext.cs, driver.cs: Switch to linq mode by default. + + * report.cs: Reset message stacks. + +2008-01-08 Marek Safar + + * generic.cs (InferInPhases): Correctly calculate params position. + +2008-01-08 Marek Safar + + * cs-tokenizer.cs: No need to parse full string when parsing lambda + arguments. + +2008-01-07 Marek Safar + + * cs-tokenizer.cs: Enabled lambda arguments micro-parser for all profiles. + + * decl.cs (LookupNamespaceOrType): Don't cache names which caused an error. + + * driver.cs: Updated --help option. + +2008-01-07 Marek Safar + + * generic.cs (InferParamsTypeArguments): Removed. + (InferInPhases): Add params type inference. + (LowerBoundInference): Fixed scoring mechanism. + + * cs-tokenizer.cs (PreProcessPragma): Use Location instead of line. + +2008-01-06 Gert Driesen + + * typemanager.cs: On 2.0 profile, GetPublicKeyToken returns an empty + byte array for unsigned "baked" assemblies. + +2008-01-05 Gert Driesen + + * codegen.cs: AssemblyName.GetPublicKey returns a zero-length byte + array for assemblies that are not strongnamed. + +2008-01-04 Marek Safar + + A fix for bug #351481 + * expression.cs (MemberAccess.ResolveNamespaceOrType): Use correct + declaring type for nested generic types. + +2008-01-04 Marek Safar + + * namespace.cs, class.cs, decl.cs, cs-parser.jay: Use GetSignatureForError + instead of ToString. + +2008-01-03 Marek Safar + + A fix for bug #351047 + * expression.cs (Binary.ResolveOperator): Allow equality operators between + null and structs only when equality and inequality operators are defined + either as an user-operators or predefined operators. + +2008-01-03 Marek Safar + + A fix for bug #351047 + * generic.cs, typemanager.cs, class.cs: New IsReferenceType helper method. + +2008-01-03 Marek Safar + + A fix for bug #351257 + * cs-tokenizer.cs: Advance line number for '\r' correctly. + +2008-01-03 Marek Safar + + A fix for bug #351157 + * class.cs (Using): Fixed yet another broken cloning. + + (Block): Put back more sensible default value for statements. + +2008-01-01 Gert Driesen + + * codegen.cs: Allow AssemblyVersion with only major version component. + Fixes bug #351055. + +2007-12-29 Marek Safar + + A fix for bug #324654 + * class.cs: Use FullName property as member name. + +2007-12-28 Marek Safar + + A fix for bug #342117 + * generic.cs (ConstraintChecker): Struct constraint also satisfies default + constructor constraint. + +2007-12-28 Marek Safar + + A fix for bug #338273 + * class.cs (ProbertyBase): Access modifier checks are required for overrides + only. + +2007-12-28 Marek Safar + + A fix for bug #350839 + * ecore.cs (MethodroupExpr): Probing hacks are no longer required. + +2007-12-27 AdTsai (http://code.google.com/u/AdTsai/) + + Reviewed by Ben Maurer, Miguel de Icaza, patches from Google's + GHOP: + + http://code.google.com/p/google-highly-open-participation-mono/issues/detail?id=4 + + * statement.cs: Changed some Hashtables to use HybridDictionaries + instead. It was observed that some HashTables only contained a few + items in the vast majority of cases. Since HybridDictionary is + more efficient on small sets (<10 elements), "known_variables" + from class ExplicitBlock as well as "labels" and "constants " from + class Block were changed to HybridDictionaries. + + Atsai results: (56216kb->54987kb) + + Miguel results (bootstrap of mcs): 59819kb -> 59290kb + + +2007-12-27 AdTsai (http://code.google.com/u/AdTsai/) + + Reviewed by Ben Maurer, Miguel de Icaza, patches from Google's + GHOP: + + http://code.google.com/p/google-highly-open-participation-mono/issues/detail?id=4 + + * expression.cs: foreach loop to for loop, saved on allocation of + enumerator (59333kb->59141kb) + + * statement.cs. Changed foreach loops to for loops, saved on + allocation of enumerator (59141kb->59006kb) + + * decl.cs: ArrayLists in .NET 1.1 allocate 16 elements by default + when constructed with no specified capacity. This was causing a + few ArrayLists to allocate more memory than they would potentially + need in the Block class and MemberCache class. Setting the + ArrayLists to construct with a capacity of 1 saves some + memory. (56216kb->55585kb) + +2007-12-27 Marek Safar + + A fix for bug #347189 (2nd issue) + * expression.cs (MemberAccess): Nested type can be found in base non-generic + type. + +2007-12-27 Miguel de Icaza + + * report.cs: Do not use colors if stdout and stderr are not a + terminal. + +2007-12-27 Marek Safar + + A fix for bug #346998 + * ecore.cs (MethodGroupExpr): Implemented override filter for generic + overloads. + +2007-12-27 Marek Safar + + A fix for bug #343465 + * class.cs: Explicit method name for nested types uses dots only. + +2007-12-27 Marek Safar + + A fix for bug #343707 + * cs-tokenizer.cs: Advance line number for mixed CR/LF files correctly. + +2007-12-27 Marek Safar + + * ecore.cs: Report type inference errors only when arguments count matches + parameter count. + + * generic.cs (NullCoalescingOperator): Cannot be applied to null. + + * expression.cs, report.cs: New warning. + + * typemanager.cs: Catch anonymous method type too. + +2007-12-23 Marek Safar + + A fix for bug #346379 + * expression.cs (UnaryMutator): Emit size of type for pointer mutator. + +2007-12-23 Marek Safar + + A fix for bug #347359 + * expression.cs (Invocation): Don't resolve already resolved expression. + +2007-12-23 Marek Safar + + A fix for bug #347189 + * class.cs (FixedField): Use non-dependent code only in the define phase. + +2007-12-23 Marek Safar + + A fix for bug #348076 + * ecore.cs (FieldExpr.DoResolve): Allow any variable based expression. + +2007-12-22 Marek Safar + + * ecore.cs (MethodGroupExpr.OverloadResolve): Set type arguments for + discovered extension methods. + +2007-12-22 Marek Safar + + * ecore.cs, namespace.cs, expression.cs: Removed broken ResolveGeneric + method. + +2007-12-21 Miguel de Icaza + + * report.cs (ErrorMessage): Add support for using colors on + terminals that support it. + +2007-12-21 Marek Safar + + * ecore.cs: Use information about expanded params for error reporting. + +2007-12-21 Marek Safar + + * ecore.cs, generic.cs, delegate.cs: Refactoring of method overloading code + and logic for params overloads. + +2007-12-15 Miguel de Icaza + + * generic.cs (NullCoalescingOperator.CloneTo): implement this one, + as this is also created from the parser. Fixes #349034 + +2007-12-12 Miguel de Icaza + + * statement.cs (Throw.CloneTo): it is valid to have empty + expressions for throw. + +2007-12-03 Marek Safar + + * cs-parser.jay: Set delegate constraint parsing region correctly. + +2007-12-03 Marek Safar + + A fix for bug #345467 + * typemanager.cs (IsEqual): Compare generic parameters position only. + +2007-11-28 Marek Safar + + * expression.cs (BaseAccess): Type arguments can be null. + +2007-11-27 Raja R Harinath + + * statement.cs (Block.Resolve): Ensure flow-branching tree is + consistent even when an error has occured. + (Switch.Resolve): Likewise. + +2007-11-22 Marek Safar + + A fix for bug #334505 + * class.cs: Don't ignore InternalsVisibleTo attribute for internal + overrides. + +2007-11-22 Marek Safar + + * ecore.cs, typemanager.cs, delegate.cs, expression.cs: The first of + refactorings required to resolve extension methods correctly when mixing + generics and non-generics members. + +2007-11-20 Marek Safar + + A fix for bug #342584 + * convert.cs: Added not documented explicit IntPtr/UIntPtr to enum + conversion. + +2007-11-19 Marek Safar + + A fix for bug #342512 + * delegate.cs: Use delegate argument expression when is available. Don't + emit virtual call when class is sealed. + +2007-11-16 Marek Safar + + A fix for bug #325423 + * assign.cs (FieldInitializer): Use resolved expression for emit. + + * class.cs: Print less confusing error message. + +2007-11-16 Marek Safar + + * cs-tokenizer.cs: Removed GMCS ifdefs. + + * rootcontext.cs, report.cs: Report unavailable gmcs features used by + mcs. + + * cs-parser.jay: Disabled nullable check. + + * generic-mcs: Copied more generic stuff. + +2007-11-16 Marek Safar + + * gcs-parser.jay: Merged to cs-parser.jay. + + * generic.cs, typemanager.cs, cs-tokenizer.cs, linq.cs, Makefile + * *.csproj, *.sources: Updated to use only jay parser file. + +2007-11-16 Marek Safar + + * gcs-parser.jay: Added nullable and default expression feature checks. + +2007-11-16 Marek Safar + + * gcs-parser.jay, cs-parser.jay, class.cs: Unified parameters parsing, + it fixes many TODOs and hidden bugs. + + * expression: Removed duplicate error check. + +2007-11-15 Marek Safar + + * gcs-parser.jay, statement.cs, decl.cs, ecore.cs: Try to resolve an + implicitly type local variable only when it is used in a declaration. + +2007-11-15 Marek Safar + + * attribute.cs: Use CS0612 for empty strings. + +2007-11-14 Marek Safar + + * lambda.cs, statement.cs: Contextual return may act as a statement. + +2007-11-14 Marek Safar + + A fix for a regression cause by #324222 + * class.cs: Don't report unused even when it implements an interface. + +2007-11-13 Marek Safar + + A fix for bug #341205 + * ecore.cs, expression.cs: Method group expression cannot do static + method access with an instance reference check before overloading takes + a place. + +2007-11-13 Marek Safar + + A fix for bug #325359 + * class.cs: Use predictable name for automatically generated property. + +2007-11-12 Marek Safar + + A fix for bug #324996 + * expression.cs (Is): Handle case where D is nullable and T is not + correctly. + + * generics.cs (Nullable.HasValue): Nullable HasValue expression. + +2007-11-12 Marek Safar + + * generic.cs, literal.cs, ecore.cs, class.cs, delegate.cs, const.cs, + anonymous.cs, expression.cs, attribute.cs, codegen.cs, statement.cs: + Flush small error reporting changes. + +2007-11-09 Marek Safar + + A fix for bug #324996 + * expression.cs: Rewrote Is expression implementation to work with + generics, nullable types, anonymous method. A const result expression + uses existing infrastructure instead of custom not fully-featured one. + +2007-11-08 Marek Safar + + A fix for bug #340202 + * class.cs: Consider generics for volatile field. + +2007-11-08 Marek Safar + + A fix for bug #335594 + * expression.cs: Use conversion rules when handling string addition. + +2007-11-07 Marek Safar + + A fix for bug #336651 + * expression.cs: Fixed a crash when probing is on. + +2007-11-07 Marek Safar + + A fix for bug #324242 + * covert.cs: Added a conversion from any nullable-type with an + underlying enum-type to the type System.Enum. + +2007-11-07 Marek Safar + + A fix for bug #324222 + * class.cs: Report all non-used event fields. + +2007-11-07 Marek Safar + + A fix for bug #325161 + * cs-parser.jay, gcs-parser.jay, decl.cs: Implemented namespace alias + qualifier for generic types. + +2007-11-07 Marek Safar + + A fix for bug #322971 + * expression.cs, ecore.cs: Added intermediate result value check for + indexers. + +2007-11-07 Marek Safar + + A fix for bug #324754 + * cs-parser.jay, gcs-parser.jay, class.cs: Try to create an interator + when it was requested. + +2007-11-07 Marek Safar + + A fix for bug #325101 + * expression.cs: Do type not value comparison for `is' expression. + +2007-11-07 Marek Safar + + A fix for bug #320236 + * convert.cs: Don't apply user conversion on underlying target type. + +2007-11-06 Marek Safar + + * expression.cs: Don't use unresolved expression for error reporting. + +2007-11-06 Marek Safar + + A fix for bugs #337712, #324490 + * ecore.cs (MethodGroupExpr): Refactored to handle delegate method + overloading resolution too. + + * delegate.cs: Uses MethodGroupExpr for overloading resolution. It makes + the process consistent and more robust. + + * expression.cs, linq.cs, report.cs: Update. + +2007-11-02 Marek Safar + + A fix for bug #332909 + * attribute.cs: Resolve attributes in correct context using error + handling procedure. + + * rootcontext.cs: Define Obsolete attribute members as core members. + +2007-11-02 Marek Safar + + * statement.cs: Removed unused methods. + +2007-10-31 Wade Berrier + + * Makefile: reenable copy of gmcs.exe.config, but include it in EXTRA + DIST (it doesn't get included because PROGRAM isn't defined to be gmcs + during 'make dist') + +2007-10-31 Marek Safar + + A fix for bug #338102 + * decl.cs (CheckExistingMembersOverloads): Workaround issue with generic + methods registered as non-generics. + +2007-10-31 Marek Safar + + A fix for bugs #337712, #324490 + * delegate.cs: Delegate covariance and contravariance is not allowed for + value types. + +2007-10-31 Marek Safar + + A fix for bug #337719 + * cs-tokenizer.cs: Restore identifier buffer when parsing contextual + `from' keyword. + +2007-10-30 Marek Safar + + * Makefile (net_2_0_bootstrap/mcs.exe.config): Reverted copy gmcs.exe.config. + +2007-10-29 Marek Safar + + * cs-tokenizer.cs, gcs-parser.jay, driver.cs: Fixed parsing of nested + query expressions. + +2007-10-29 Raja R Harinath + + * Makefile (net_2_0_bootstrap/mcs.exe.config): Copy gmcs.exe.config. + +2007-10-29 Marek Safar + + A fix for bug #334652 + * ecore.cs (MethodGroupExpr.OverloadResolve): Do also lookup for + extension methods when we have not found the best candidate in normal + container. + +2007-10-27 Marek Safar + + * AssemblyInfo.cs: Keep up-to-date. + +2007-10-27 Marek Safar + + * Makefile: Fixed generics compiler name. + +2007-10-27 Marek Safar + + * lambda.test: removed, lambda parsing is done differently. + + * gen-il.cs, gen-treedump.cs, old-code.cs : Obsolete. + +2007-10-27 Gert Driesen + + * Makefile: Removed dependency on gmcs.exe.config. Fixes build. + +2007-10-27 Marek Safar + + * Makefile, *.sources : All C# compilers are in mcs folder. + + * *.cs: Use existing 2_1 define for smcs. + +2007-10-26 Marek Safar + + A fix for bug #335847 + * assign.cs, expression.cs: Couple of changes to avoid creating a + temporary variable for each object initializer assignment statement. It + simplifies struct initialization too, otherwise two temporary variables + would be required. + Implemented optimization of redundant default element initializers. + +2007-10-25 Marek Safar + + A fix for bug #336766 + * expression.cs (Class.CheckBase): Use generic name when method is + generic. + +2007-10-25 Marek Safar + + A fix for bug #334737 + * expression.cs (IndexerAccess.EmitAssign): Emit local temporary + variable and not variable argument for prepared copies. + +2007-10-24 Marek Safar + + A fix for bug #325110 + * class.cs, expression.cs, attribute.cs: Use open generic method when + checking conditional attribute. + +2007-10-24 Marek Safar + + * report.cs, cs-tokenizer.cs, class.cs, cs-parser.jay, anonymous.cs, + expression.cs, statement.cs: Renamed method FeatureIsNotISO to + FeatureIsNotAvailable. + +2007-10-24 Marek Safar + + ** C# 3.0 Partial methods + + * cs-tokenizer.cs, support.cs, class.cs, decl.cs: Implemented partial + methods support. Because of member cache issue with generics only + non-generics partial methods are fully supported. + +2007-10-23 Marek Safar + + * class.cs, decl.cs: Rewrote member overloads check to cope with + generics and to use member cache for member checking. It also improves + performance and fixes remaining overloads issues. + +2007-10-20 Marek Safar + + * class.cs, const.cs, decl.cs, delegate.cs, enum.cs, generic.cs, + roottypes.cs, typemanager.cs: + + A member cache creation logic changed to add members immediately and + not rely on fallback. The member cache is now only prefered way + how to access and find type declaration members. It saves 5 MB of memory + during MWF compilation and makes code ready for more optimizations and + clean-ups, it's also a pre-requirement for partial methods. + +2007-10-18 Raja R Harinath + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Add special + handling for generic parameters. + +2007-10-15 Marek Safar + + * class.cs (FixedField): Removed redundant volatile check. + +2007-10-15 Marek Safar + + * class.cs, decl.cs: Fixed overload members verification to do only one + check per possible collision. + +2007-10-13 Marek Safar + + A fix for bug #325478 + * anonymous.cs (AnonymousContainer.Compatible): Merge are flags together + and create only one disposable flags container. + +2007-10-12 Marek Safar + + A fix for bug #332442 by Alexandre Gomes + * statement.cs (Fixed): Fixed variables cloning. + +2007-10-12 Marek Safar + + A fix for bug #333342 + * class.cs (EventField): Don't mark value type event as synchronized. + +2007-10-12 Marek Safar + + * ecore.cs, anonymous.cs (MethodGroupExpr): Use score from type + inference to identify best candidate method correctly. + (ProperyExpr): A range variable is read only and cannot be modified. + +2007-10-11 Marek Safar + + * ecore.cs, delegate.cs (MethodGroupExpr): Refactored best candidate + logic to identify best candidate method correctly. + +2007-10-11 Marek Safar + + * location.cs (Equals, GetHashCode): Removed. + +2007-10-11 Marek Safar + + * report.cs: Implemented message recorder. It is used mainly for lambda + expressions to capture otherwise swallowed error messages. + + * anonymous.cs, lambda.cs.cs: Do full parameters check. + + * ecore.cs (ExtensionMethodGroup): Report binding failure at the botton + and not at the top. + (MethodGroupExpr.DoResolve): Use message recorder for error handling. + + * expression.cs (MemberAccess): Always report lookup failure. + + * location.cs: Implemented Equals, GetHashCode. + + * statement.cs (Return.DoResolve): Fixed hardcoded error argument. + +2007-10-10 Jb Evain + + * codegen.cs: re-enable assembly version check. + +2007-10-09 Marek Safar + + * report.cs, anonymous.cs, driver.cs, expression.cs: Added few ISO-2 + checks. + + * namespace.cs (UsingAlias): Do correct version check. + +2007-10-08 Marek Safar + + * expresison.cs, ecore.cs: Issue extension method error message when + appropriate. + + * rootcontext.cs: Added ISO_2 compiler mode option. + +2007-10-08 Marek Safar + + * expresison.cs (UnaryMutator.ResolveOperator): Print more useful error + message. + +2007-10-08 Marek Safar + + * attribute.cs (GetString, GetBoolean): Work with both literal and + constant. + + * ecore.cs, expresison.cs, delegate.cs (Invocation, MethodGroupExpr): + Moved method overload specific methods to MethodGroupExpr. + + (IndexerAccess): Re-wrote resolving mechanism, fixed many issues and + it should be less memory consuming. + +Mon Oct 8 09:29:15 CEST 2007 Paolo Molaro + + * codegen.cs: remove the assembly version check until the buildbot is + fixed. + +2007-10-07 Jb Evain + + * attribute.cs (Attribute.GetString): if the value + expression is a StringConstant, return its string value. + +2007-10-07 Jb Evain + + * typemanager.cs: add `assembly_version_attribute_type`. + * codegen.cs: on attribute emission, check that the + AssemblyVersionAttribute doesn't overflow. + +2007-10-05 Marek Safar + + A fix for bug #324677 + * anonymous.cs, decl.cs: Yes another anonymous container hack. Overwrite + parent container of a scope container with currently resolved one. + +2007-10-05 Marek Safar + + A fix for bug #325534 + * class.cs (Invocation.DoResolve): Check invocation of object finalizer + only. + +2007-10-05 Marek Safar + + A fix for bug #327504 + * class.cs (Operator.Define): Refactored implicit and explicit user + operator conversion rules. + +2007-10-05 Marek Safar + + A fix for bug #327520 + * ecore.cs (ExtensionMethodGroupExpr): Emit resolved extension argument. + +2007-10-04 Marek Safar + + A fix for bug #328022 + * class.cs (MethodData.Define): Use correct method to check whether + a method implementents an accessor. + +2007-10-04 Marek Safar + + A fix for bug #330069 + * statement.cs (Fixed.Resolve): Read the first array element only when + an array is instantiated. + +2007-10-04 Marek Safar + + * expression.cs, assign.cs, generics.cs: Print correct operator when + compound assignment is used. + +2007-10-04 Marek Safar + + A fix for bug #325841 + * expression.cs (ArrayAccess): Use full argument cloning only for + string compound concatenation. + +2007-10-03 Marek Safar + + A fix for bug #328774 + * ecore.cs (FieldExpr.EmitAssign): Fixed string concatenation compound + assignment. + (PropertyExpr.EmitAssign): Fixed string concatenation compound + assignment. + +2007-10-03 Raja R Harinath + + Fix #328490 + * ecore.cs (SimpleName.DoSimpleNameResolve): Handle Property and + Event accessibility checks here. Remove some bogus code that + accidently made GenericMethods work. + (PropertyExpr.IsAccessibleFrom, EventExpr.IsAccessibleFrom): New. + +2007-09-25 Marek Safar + + * expression.cs (ArrayCreation): Fixed cloning of an implicit types. + + * statement.cs (Block): Refactored AddVariable to allow error handling + customization. + + * generic.cs: New stub. + +2007-09-23 Marek Safar + + * anonymous.cs, codegen.cs: Changed InferReturnType to be EmitContext + flag. + +2007-09-17 Marek Safar + + * class.cs: Use partial container to record whether any partial part + contains static field initializer and therefore default contructor has + to be defined. + +2007-09-14 Marek Safar + + * class.cs (TypeContainer.AddPartial): Fixed an issue reported on + mono-list when only one of two partial parts has defined accessibility + modifier. + +2007-09-14 Marek Safar + + A fix for bug #82845 + + * class.cs (TypeContainer): Set correct resolve context for all field + initializers. + +2007-09-13 Marek Safar + + * assign.cs: Fixed a crash when field is resolved twice with an error. + + * codegen.cs: Changed InFieldInitializer to be flag. + + * anonymous.cs, ecore.cs, expression.cs: Update after + IsInFieldInitializer rename. + + * const.cs: Removed unused parameter. + + * class.cs: Changed the way how we resolve and emit field initializers. + The field initilizers have to have access to contructor block to emit + compiler generated code. + +2007-09-13 Marek Safar + + * expression.cs (MemberAccess.DoResolve): DeclSpace is broken by + generics use TypeContainer instead. + +2007-09-12 Marek Safar + + * generic.cs (TypeInferenceContext.InflateGenericArgument): Stub. + + * lambda.cs (ResolveParameters): Use more powerful + InflateGenericArgument. + + * parameters.cs: Better exception message. + +2007-09-10 Marek Safar + + * anonymous.cs (AnonymousMethodExpression.CompatibleChecks): Report + correct expression block type. + + * ecore.cs (Expression.Error_MemberLookupFailed): Made virtual. + + * expression.cs (Invocation): Extracted method group resolve to + DoResolveOverload. + +2007-09-07 Marek Safar + + * ecore.cs (Expression.MemberLookupFinal): Removed unused loc parameter. + (MethodGroupExpr.ResolveGeneric): Use existing method group instance. + + * expression.cs (MemberAccess.DoResolve): Uses generic resolver for + generic extension methods. + +2007-09-06 Marek Safar + + A fix for bug #82676 (Do I get it right now?) + * convert.cs (Binary.ResolveOperator): An interface is converted to the + object before a standard conversion is applied. + +2007-09-06 Marek Safar + + * convert.cs (ImplicitReferenceConversionCore): Reverted wrong fix of + #82676. + +2007-09-05 Marek Safar + + A fix for bug #82676 + * convert.cs (ImplicitReferenceConversionCore): Check both sides for + non-generic interface types. + +2007-09-05 Marek Safar + + A fix for bug #82690 + * ecore.cs (PropertyExpr.EmitAssign): Leave a copy does just that. + +2007-09-05 Marek Safar + + A fix for bug #82571 + * anonymous.cs (AnonymousMethod.DoCreateMethodHost): Use internal + modifier for container based methods. + +2007-09-05 Marek Safar + + A fix for bug #82676 + * convert.cs (ImplicitReferenceConversionCore): From any class-type S to + any interface-type T means to any of interface type T. + +2007-09-04 Marek Safar + + * namespace.cs: We have 2 versions of System.Core assembly. + +2007-09-04 Marek Safar + + A fix for bug #82652 + * class.cs (Class.GetClassBases): Compare types and not expressions. + +2007-09-04 Marek Safar + + A fix for bug #82620 + * expression.cs (Invocation.EmitArguments): Duplicate params arguments + actually never worked before. + (IndexerAccess): Emit prepared arguments before they are modified. + +2007-09-04 Marek Safar + + A fix for bug #82563 + * assign.cs: Revert wrong fix. + + * expression.cs (VariableReference.EmitAssign): Handle ref reference + correctly. + (ArrayAccess): Changed the way we emit compound (prepared) assignments. + Instead of ldelema/stdind we have to use temporary variables to handle + cases like String.Concat (params string[]). + +2007-08-31 Marek Safar + + * class.cs: EmitAttributes to Emit rename. + + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Parent can be + null. + (MemberCore.HasClsCompliantAttribute): Don't depend on + GetClsCompliantAttributeValue execution. + +2007-08-31 Marek Safar + + * anonymous.cs: Use shorter type prefix. + + * ecore.cs (SimpleName.DoSimpleNameResolve): Use transparent identifiers + when exist. + + * expression.cs (LocalVariableReference.DoResolveBase): Don't capture + variables when probing is on. + + * statement.cs (LocaLInfo.Clone): Clone correctly resolved and + unresolved variables. + (TopLevelBlock.GetTransparentIdentifier): Default implementation doesn't + handle transparent identifiers. + +2007-08-26 Marek Safar + + * attribute.cs (IsClsCompliant): Add nullable types test. + +2007-08-24 Atsushi Enomoto + + * doc.cs : catch other types of exception than XmlException to + report CS1570. Fixed bug #82565. + +2007-08-23 Marek Safar + + * anonymous.cs (AnonymousMethodExpressin.ExplicitTypeInference): + The number of delegate parameters has to match. + (AnonymousMethodExpressin.VerifyParameterCompatibility): Handles generic + arrays. + +2007-08-21 Marek Safar + + * anonymous.cs (AnonymousMethod): Generate private anonymous method + to fix problem with private arguments. + +2007-08-20 Marek Safar + + * anonymous.cs (AnonymousTypeClass): An anonymous type can be empty. + + * decl.cs (MemberName): Ignore generic type with no generic arguments. + + * expression.cs (AnonymousTypeDeclaration): An anonymous type can be + empty. Add cloning suport. + + * roottypes.cs (GetAnonymousType): Fixed argument comparison logic. + +2007-08-20 Marek Safar + + * convert.cs, ecore.cs, expression.cs, literal.cs: Use factory method + to create EmptyCast. It handles EmptyConstantCast specialization for + constants. + +2007-08-18 Marek Safar + + * expression.cs (Binary.is_unsigned): Handle unsafe types too. + (EmitArrayArgument): One routine for array arguments. + (ArrayCreation.MakeByteBlob): Fixed an array alignment. + +2007-08-17 Marek Safar + + * cs-tokenizer.cs (GetKeyword): Handle from keyword in a different way. + +2007-08-17 Marek Safar + + * anonymous.cs: MemberLookupFinal update. + + * class.cs (ConstructorInitializer): Is expression based. + + * delegate.cs: MethodGroupExpr update. + + * ecore.cs (Error_MemberLookupFailed): Improved to report better error + messages. + (Error_MemberLookupFailed): Customizable error override. + (MethodGroupExpr): Keep queried type for later usage. + (MethodGroupExpr.OverloadResolve): Catch errors related to overload + resolve. + + * expression.cs: Error_MemberLookupFailed refactoring. + (New.DoResolve): Resolve as much as possible. + (ElementInitializer.Error_MemberLookupFailed): Object initializer + customization for invalid member types. + + * statement.cs: MethodGroupExpr update. + +2007-08-16 Marek Safar + + * modifier.cs (Check): Check all modifiers and not only accessibility + ones. + +2007-08-16 Marek Safar + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Report always a + type and not an expression. + +2007-08-16 Marek Safar + + * statement.cs (Catch.Clone): Type and variable can be null. + +2007-08-16 Marek Safar + + A fix for bug #81979 + * assign.cs (Assign.Emit): Prepare arguments for string concatenation. + I am really not sure whether this is the best fix. + + * expression.cs (VariableReference.EmitAssign): Do prepare_load test + only once. + +2007-08-14 Marek Safar + + ** C# 3.0 Object and collection initializers (major re-write) + + * assign.cs (DoResolve): Initializers are not assign related. + + * codegen.cs (EmitContext.CurrentInitializerVariable): Holds a varible + used during collection or object initialization. + + * expression.cs (Error_InvalidArguments): Add initializers specific + messages. More will come later because it requires some general + refactoring. + (New.DoResolve): Better error handling for unsafe types. + (EmptyExpressionStatement): New class. + (ElementInitializer): An object initializer expression. + (CollectionElementInitializer): A collection initializer expression. + (CollectionOrObjectInitializers): A block of object or collection + initializers. + (NewInitialize): New expression with element/object initializers. + + * statement.cs: Reverted object/collection initializer hacks. + + * typemanager.cs (CSharpName): Filter __arglist type. + +2007-08-09 Marek Safar + + ** C# 3.0 Anonymous Types (update to the latest standard) + + * expression.cs (Binary.ResolveOperator): Threat all null based types + same. + (AnonymousTypeDeclaration): Renamed from AnonymousType and simplified. + (AnonymousTypeParameter): Updated. + + * anonymous.cs (CompilerGeneratedClass): Add custom name overload. + (AnonymousTypeClass): New anonymous type container. + + * class.cs (AddField): Return operation result. + + * generic.cs: Another empty TypeArguments overload. + + * roottypes.cs (AddAnonymousType, GetAnonymousType): Anonymous types + are stored at top of normal hierarchy. + + * typemanager.cs (CSharpName): Filter anonymous types. + +2007-08-09 Marek Safar + + * expression.cs (StringConcat.Append): Handle 3 and more concatenation + as single Concat call. How could we miss that :-( + +2007-08-08 Marek Safar + + * expression.cs (ArrayCreation.CloneTo): Allocate exact size. + +2007-08-07 Miguel de Icaza + + * expression.cs: Fix the previous commit, the creation of the + arguments array list needs also to be conditional on the arguments + not being null. + + * class.cs: Add a little bit of help to help narrow down problems. + + * expression.cs (ArrayCreation.CloneTo): Argument can be null, do + not try to copy in that case. + + * driver.cs: When building SMCS, include a new different set of + default assemblies here. Do this here so we can control whether + to include the default assemblies with /noconfig. + +2007-08-03 Marek Safar + + A fix for bug #81979 + * expression.cs (TypeOf.GetAttributableValue): Check for type arguments + only. + +2007-08-03 Marek Safar + + A fix for bug #82300 + + * anonymous.cs (AnonymousContainer.Define): Don't define anything when + we are in probing scope. + +2007-08-03 Marek Safar + + A fix for bug #82301 + + * statement.cs (Catch.CloneTo): Clone blocks in the right order. + (Statement.CloneTo): Clone and not map children blocks. + +2007-08-03 Marek Safar + + A fix for bug #82299 + + * expression.cs (LocalVariableReference.CloneTo): Remap local info + variable too. + + * statement.cs (Statement.CloneTo): Clone variables before statements + to allow remaping of local variables. + +2007-08-03 Marek Safar + + A fix for bug #82296 + + * anonymous.cs, + * report.cs: Log crash details for future clone problems. + + * statement.cs (Return.Clone): Don't clone non-existent expression. + +2007-08-03 Raja R Harinath + + * class.cs (TypeContainer.AddBasesForPart): Make virtual. + (Class.AddBasesForPart): Move CS0537 check here from ... + * cs-parser.jay (class_declaration): ... here. Move calling of + 'AddBasesForPart' to ... + (class_bases): ... here. + (struct_declaration, interface_declaration): Update to changes. + +2007-08-02 Marek Safar + + A fix for bug #81923 + + * statement.cs (Using.ResolveLocalVariableDecls): Only non-user implicit + conversion is allowed. + +2007-08-02 Marek Safar + + A fix for bug #81564 + + * ecore.cs (EventExpr): Add IsBase handling. + + * expression.cs (BaseAccess.CommonResolve): Events can use base accessor + too. + +2007-08-02 Raja R Harinath + + Reduce some differences between cs-parser.jay in mcs/ and gmcs/. + * cs-parser.jay: Some whitespace cleanups. + (current_delegate): New. + (type_name): New. + (struct_declaration): Make similar to gmcs/cs-parser.jay -- add + a dummy code block, and use 'type_name' instead of 'member_name'. + (interface_declaration, class_declaration): Likewise. + (delegate_declaration): Likewise. Rearrange slightly and use + 'current_delegate'. + * cs-tokenizer.cs (handle_where): Rename from handle_constraints. + (GetKeyword): Update to change. Use '!foo' instead of 'foo == false'. + +2007-08-02 Marek Safar + + A fix for bug #82039 + + * ecore.cs (TypeLookup.GetSignatureForError): Use name when type is not + available. + + * typemanager.cs (CSharpName): Split to string overload. + +2007-08-02 Marek Safar + + * expression.cs, + * report.cs: Updated warning CS0472. + +2007-08-01 Marek Safar + + A fix for bug #82181 + * cs-parser.jay, + * cs-tokenizer.cs: Ignore partial keyword inside block expression. + +2007-08-01 Marek Safar + + A fix for bug #82277 + * statememnt.cs (Block.Clone): Don't clone explicit blocks twice. + +2007-08-01 Marek Safar + + ** C# 3.0 Type Inference (major bits are working) + + * anonymous.cs (AnonymousMethodExpression): Removed refactored fields. + (.ImplicitStandardConversionExists): Uses compatible. + (.ExplicitTypeInference): Infers type arguments based on explicit arguments + (.InferReturnType): New method. + (.Compatible): Refactored. + (.ResolveParameters): Uses factory to create resolved parameters. + (.CompatibleMethod): Add probing mode support. + (AnonymousContainer): Removed unused fields. Split Define and Resolve to + clearly distinguish between 2 different operations. + (LambdaMethod): Moved to lambda.cs. + (AnonymousMethod): Removed unused fields and methods. + (AnonymousDelegate): Simplified. + + * codegen.cs (ResolveTopBlock): Updated renamed Resolve to Define. + + * convert. cs (ImplicitConversionStandard): Compatible works differently. + + * delegate.cs (Delegate): New mehods to reduce code duplication. + (.GetConstructor): New method. + (.GetInvokeMethod): New method. + (DelegateCreation): Updated. + + * ecore.cs (ResolveOverloadExtensions): Don't crash when extension method + does not exist. + (OverloadResolve): Made probing little bit faster. + + * expression.cs (ParameterReference.DoResolveLValue): Reference can be null + when probing is on. + + * generic.cs (TypeInferenceContext): Dummy implementation. + + * iterators.cs: Updated after Resolve/Define rename. + + * lambda.cs (LambdaExpression) + (.ResolveParameters): Handles both type of arguments and type inference too. + + * parameter.cs (ImplicitLambdaParameter.Resolve): Sanity check. + (InflateTypes): Updated. + + * support.cs (InflateTypes): Changed signature and updated. + + * typemanager.cs (LookupMemberCache): Better dynamic type check. + (MemberLookup_FindMembers): More MS tricks. + (GetParameterData): Ditto. + (GetDelegateParameters): Uses quick path for dynamic types. + +2007-08-01 Marek Safar + + * class.cs (MethodData.Define): EmitContext is required for generic stuff + only. + +2007-07-31 Marek Safar + + * statement.cs (ProcessParameters): Don't crash when parameters have wrong + syntax. + +2007-07-26 Jb Evain + + * typemanager.cs (TypeManager.GetConstructor): Add a method overload + which takes a boolean 'report_errors', similar to the GetMethod. + (InitCodeHelpers): StructLayoutAttribute.ctor(int16) is not visible + in .net 2.1, do not report errors here. + + * typemanager.cs (TypeManager.InitCoreTypes): System.ArgIterator, + System.Runtime.CompilerServices.RequiredAttributeAttribute and + System.Runtime.CompilerServices.TypeForwardedToAttribute are internal + in .net 2.1. + + * typemanager.cs (TypeManager.InitCoreTypes): Move the resolution + of the type InternalsVisibleToAttribute before the first call + to CoreLookupType which is allowed to fail (third boolean parameter + to true). Because, during the resolution for a type that is not + immediately found, we try to check if the type is not defined in + a friend assembly, and to do so, we need the + InternalVisibleToAttribute. + +2007-07-23 Miguel de Icaza + + * expression.cs (Binary): Add support for the brain-dead CSC 2.x + feature that allows structs to be compared against null and inline + the result as true or false. + + Notice that the same code is not permitted inside a generic block + of code that would do: + + class Foo where T : struct { + bool Eval (T x) + { + return x == null; + } + } + + It is only allowed if the type of T is not bound (no where + clause). In my opinion, this CSC 2 behavior is broken but people + seem to be using it (IronRuby does, a few bug reports on bugzilla + have it and some people have complained about it). + + All of the users that depend on this behavior have code that is + very likely broken. + + * report.cs (Warning, Error): make these take object arguments, + not strings, as that allows us to take advantage of Format. + +2007-07-20 William Holmes + + * decl.cs: Changed MemberName.CountTypeArguments to also check the + Left member variable for the Count. + * doc.cs: Changed DocUtil.GetMethodDocCommentName to call + MemberName.CountTypeArguments to avoid a NRE. + + This code is contributed under the MIT X11 license + +2007-07-18 Marek Safar + + * cs-tokenizer.cs: Improved lambda parsing and removed old code. + +2007-07-18 Atsushi Enomoto + + * doc.cs : generic method arguments are written as ``x while generic + type arguments are `x. Combined with the previous change, fixed bug + #79706. + +2007-07-18 Raja R Harinath + + Fix #82120 + * expression.cs (Binary.ResolveOperator): When converting + 'a + (- b)' to 'a - b', ensure that the unary '-' is discarded. + +2007-07-18 Atsushi Enomoto + + * doc.cs : when T: or whatever x: is specified, it does not really + check the doc comment's syntax correctness. Fixed bug #82006. + +2007-07-18 Marek Safar + + * anonymous.cs (AnonymouseMethodExpression): Refactored to work with + LambdaExpression better. + + * cs-tokenizer.cs: Changed a way how we detect lambda parameters. + + * driver.cs (LambdaTypeParseTest): Removed, tested method is gone. + + * ecore.cs (Expression.MemberLookupFailed): Don't show currect context + as it can be generated. + + * expression.cs (Invocation.Error_InvalidArguments): Show correct + modifiers. + + * lambda.cs (LambdaExpression): Refactored to share same code with + AnonymousMethodExpression. + +2007-07-17 Marek Safar + + * anonymous.cs (MakeName): Include host name for easier debugging. + (LambdaMethod): New class for lambda spcecific stuff. + + * attribute.cs: Set EmitContext return type. + + * class.cs: Set EmitContext return type. + + * codegen.cs (EmitContext): Return type cannot be null to stop messing + with null/void meaning. + + * iterators.cs (ContainerType): Implemented. + + * rootcontext.cs: Set value of TypeManager.bool_type at early stage. + + * statement.cs (Return): Updated to lambda expressions. + (Block.CloneTo): Parent can be null. + +2007-07-13 Marek Safar + + A fix for bug #81917 + * attribute.cs (AttributeTester.GetFixedBuffer): More robust testing. + + * class.cs (FixedField): Check whether field is in unsafe scope. + + * ecore.cs (FieldExpr.DoResolve): Create fixed buffer expression here. + (FieldExpr.Emit): Fixed buffers cannot be volatile. + + * expression.cs (ElementAccess.Resolve): Move fixed buffers resolve to + FieldExpr. + + * statement.cs (Fixed.Resolve): Simplified fixed buffers. + +2007-07-13 Marek Safar + + * cs-tokenizer.cs, class.cs, decl.cs, driver.cs, namespace.cs, + rootcontext.cs, expression.cs, statement.cs: Updated to use WarningLevel + from Report class. + +2007-07-13 Marek Safar + + * ecore.cs (FieldExpr.AddressOf): Less confusing warning message. + +2007-07-13 Marek Safar + + * anonymous.cs (AnonymousMethodExpression): Parameters are r/o. + (AnonymousContainer.ResolveNoDefine): Another ec to aec flag conversion. + + * codegen.cs(EmitContext): Add ProbingMode flag. + + * delegate.cs (DelegateInvocation): Set few instance variables as r/o. + + * driver.cs: For now set both warning values. + + * ecore.cs (SimpleName): Name is readonly. + (MethodGroup.OverloadResolve): One quick path for probing. + + * expression.cs (Unary): Set Oper r/o. + (Binary): Set Oper r/o. + (ParameterReference): Set few instance variables as r/o. + (ParameterReference.DoResolveBase): Don't capture aruments when + the probing is on. + (Invocation.CloneTo): Fixed typo, looks easy, yeah. + (Arglist): arguments are private. + (SizeOf): type is private and r/o. + (MemberAccess): arguments are private. + + * report.cs: Enhanced reporting on/off capabilities. + + * lambda.cs: Uses ec.IsInProbingMode. + (ContextualReturn): Derives from return. + + * rootcontext.cs: For now set both warning values. + + * statement.cs (CloneContext.RemapBlockCopy): Remaps block to cloned + copy if one exists. + (Return.Resolve): Don't die immediately. + (Block.Resolve): Speed-up probing. + (Block.CloneTo): Clone only child blocks. + +Fri Jul 13 11:19:28 CEST 2007 Paolo Molaro + + * iterators.cs: reverted Miguel's latest change (r81925) as it + breaks the build in System. + +2007-07-13 Miguel de Icaza + + * iterators.cs (Yield.CheckContext): Check for the iterator type + also here as we can call into Yield even in codepaths that are not + directly checked by + (MethodOrOperator is the only path that was checked). + + In addition to the standard check, use a more specific check for + constructors to report a more verbose error. + +2007-07-12 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): Do not stop processing here, + report the warning and continue + + * statement.cs (Using.EmitLocalVariableDecls): We were leaving + values on the stack on the call to Emit. Use EmitStatement if + possible, or using Emit + Pop if not possible. Fixes #82064 + +2007-07-12 Raja R Harinath + + * expression.cs (Invocation.IsApplicable): Reorganize slightly to + avoid try...finally in some cases. + +2007-07-10 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Uses method group. + + * class.cs (ConstructorInitializer.Resolve): Use and keep method group + instead of method. Re-use standard error handling. + (ConstructorInitializer.Emit): Simplified. + + * delegate.cs: Updated after Invocation.EmitCall change. + + * ecore.cs (GetOperatorTrueOrFalse): Uses MethodGroupExpr only. + (SimpleName.SimpleNameResolve): Set and reset in_transit flag correctly. + (ExtensionMethodGroupExpr): Refactored to use same OverloadResolve + method and don't permanently changing input arguments. + (MethodGroupExpr): Introduced resolved best_candidate, when method group + is resolved it has one of the candidates is the best one which is later + used to emit. Removed a few unused method. + (MethodGroupExpr.MakeUnionSet): Moved from Invocation, it belongs here. + + * expression.cs (StaticCallExpr.MakeSimpleCall): Uses method group. + (Binary.ResolveOperator): Ditto. + (ConditionalLogicalOperator.DoResolve): Ditto. + (Invocation): Uses method group. + (Invocation.DoResolve): Simplified. + (Invocation.EmitCall): Removed useless is_static. + (Invocation.Emit): Delegate to method group. + (Invocation.EmitStatement): Simplified. + (New): Uses method group. + (MemberAccess.DoResolve): Don't destroy original expression. + + * statement.cs (ForEach.Resolve): Use null for no method arguments. + +2007-07-04 Marek Safar + + * ecore.cs (VarExpr.DoResolveLValue): More restriction checks. + + * anonymous.cs, + * lambda.cs: Add custom error message type. + +2007-07-03 Marek Safar + + * lambda.cs: Simplified little bit. + + * parameter.cs: Introduced ImplicitLambdaParameter. + (Parameters.CreateFullyResolved): New factory instead of ctor. + + * anonymous.cs, + * class.cs, + * delegate.cs: Updated parameter creation. + +2007-07-03 Marek Safar + + * ecore.cs (SimpleName.GetSignatureForError): Display correctly generic + arguments. + + * generic.cs: Synchronized with gmcs. + +2007-07-03 Marek Safar + + * class.cs (Indexer): Check return type as soon as possible. + + * cs-parser.jay: Initialize implicit_value_parameter_type for interface + members too. + + * ecore.cs (VarExpr.DoResolveLValue): Set eclass value. + + * expression.cs (Invocation.Error_InvalidArguments): Show type only. + + * parameter.cs (Parameter): Use expression type when it is available. + + * support.cs (ReflectionParameters.ParameterDesc): Show an extension + method modifier for the first parameter only. + +2007-06-24 Marek Safar + + A fix for bug #81938 + * typemanager.cs (ChangeType): Fixed couple of char conversions. + + * constant.cs: Tide up an exception message. + +2007-06-22 Marek Safar + + * ecore.cs (SimpleName.DoSimpleNameResolve): Better error reporting when + an uninitialized variable is used. + + * expression.cs (LocalVariableReference.DoResolve): Ditto. + +2007-06-22 Marek Safar + + * ecore.cs (SimpleName.TypeOrNamespaceNotFound): Allow to override type + not found error handling. + + * expression.cs (ArrayCreation): Removed redundant fields and little bit + simplified. + (ArrayCreation.ResolveArrayElement): To be ready to customization. + (ArrayCreation.DoResolve): Simplified. + (ImplicitlyTypedArrayCreation.DoResolve): Implicitly typed arrays have + its own resolve process. + (ImplicitlyTypedArrayCreation.ResolveArrayElement): Conversion magic. + +2007-06-20 Marek Safar + + * namespace.cs (NamespaceEntry.Error_AmbiguousTypeReference): Print + more error details. + +2007-06-20 Marek Safar + + * cs-tokenizer.cs: Removed var related stuff. + + * ecore.cs (Expression.ResolveAsContextualType): Introduced new method. + (VarExpr): Changed to derive from SimpleName. VarExpr now behaves as + a type and a keyword at same time. + + * decl.cs (MembeName.GetTypeExpression): Create VarExpr when type name + matches to "var". + + * expression.cs (ImplicitlyTypedArrayCreation): New empty class for + implicitly typed arrays, more changes will follow. + + * statement.cs (LocalInfo.Resolve): Resolve type as contextual type. + +2007-06-19 Marek Safar + + * ecore.cs (VarExpr): Removed Handled field. + + * statement.cs (Using.ResolveLocalVariableDecls): Refactored to use + build-in assign functionality. + (ForEach.Resolve): Removed all implicitly typed local variable code and + simplified. + (ArrayForeach.Resolve): Infer implicitly typed local variable here. + (CollectionForeach.Resolve): Infer implicitly typed local variable here. + +2007-06-18 Marek Safar + + * assign.cs: Removed implicitly typed local variable check. + + * expression.cs (LocalVariableReference.DoResolve): Add check for self + referencing implicitly typed local variable. + (LocalVariableReference.DoResolveLValue): Infer implicitly typed local + variable here. + + * statement.cs (Fixed): Removed unsupported implicitly typed local + variable code. + +2007-06-15 Marek Safar + + * decl.cs (MemberName): Moved all Unbound stuff to parser. + +2007-06-14 Marek Safar + + A fix for bugs #81855 and #76274 + * attribute.cs (AttachTo): Always set owner for global attributes to + prefined owner. + + * ecore.cs (Error_TypeDoesNotContainDefinition): A type location can be + usefull too. + + * cs-parser.jay: Assembly and module attributes must precede all other + elements except using clauses and extern alias declarations. + +2007-06-13 Marek Safar + + A fix for bug #81748 + * cs-tokenizer.cs, + * expression.cs: More checks for non ISO-1 features. + +2007-06-12 Marek Safar + + A fix for bug #81807 + * statement.cs(Switch.TableSwitchEmit): Define null label when it's not + present inside switch statement and it is required by nullable check. + +2007-06-12 Marek Safar + + A fix for bug #81840 + * ecore.cs (SimpleName.ResolveAsTypeStep): Look for non-generic type + when type matching fails. + + * namespace.cs: Tiny error message change. + +2007-06-12 Marek Safar + + * decl.cs (CheckAbstractAndExtern): Moved to MemberCore for easier error + reporting. Added automatic property check. + + * class.cs: Updated after CheckAbstractAndExtern relocation. + (AEventPropertyAccessor.GetSignatureForError): Customized. + +2007-06-11 Marek Safar + + * class.cs (DefineBaseTypes): Base type can be undefined. + + * ecore.cs (TypeLookup): Minor refactoring. + (DoResolveAsTypeStep): Removed redundant check. + + * namespace.cs (Lookup): Removed redundant check. + + * rootcontext.cs (BootstrapCorlib_ResolveType): Uses normal + ResolveAsTypeTerminal step. + (BootstrapCorlib_*): Simplified. + (PopulateCoreType): Core types can be now external. + +2007-06-07 Marek Safar + + * anonymous.cs (VerifyExplicitParameterCompatibility): Add flag to do + verification only. + (InferTypeArguments): Infers anonymous expression type arguments. + (Compatible): Split to Compatible and InferTypeArguments. + + * lambda.cs: Updated. + +2007-06-08 Marek Safar + + * anonymous.cs (AnonymousContainer): Marked as compiler generated. + +2007-06-07 Raja R Harinath + + Fix #80477, cs0135-2.cs, cs0135-3.cs + * statement.cs (ToplevelBlock.ProcessParameters): Add parameter + names to the "known" variables list. + (Block.CheckInvariantMeaningInBlock): Handle the fact the + parameter names are also "known". + (Block.CheckError136): Remove. + (ExplicitBlock.CloneTo): New. Set 'known_variables' in target to + null. + +2007-06-07 Marek Safar + + * ecore.cs (MethodGroupExpr.OverloadResolve): Print full method definition. + +2007-06-06 Marek Safar + + * ecore.cs (SimpleName.Emit): Emitting unresolved simple name is + internal error not an user error. + + * expression.cs (IsApplicable): Refactored to make debugging easier. + + * support.cs: More tricks for non-mono runtimes. + + * typemanager.cs (CoreLookupType): Made public. + (InitSystemCore): All linq specific stuff moved to linq.cs + +2007-06-05 Marek Safar + + * typemanager.cs (CSharpSignature): One more missing build-in types + replacement. + More tricks for non-mono runtime. + +2007-06-05 Raja R Harinath + + * statement.cs (Block.CheckError136_InParents): Remove. + (Block.AddVariable): Use GetParameterInfo instead. + (ToplevelBlock.ProcessArguments): Likewise. + +2007-06-04 Raja R Harinath + + * statement.cs (ToplevelBlock.CloneTo): New. Copy over parameter + information too. + (ToplevelBlock.GetParameterInfo): Split out of ... + (ToplevelBlock.GetParameterRefernce): ... this. + (ToplevelBlock.ParameterMap): Remove. + * expression.cs (ParameterReference): Update to use + ToplevelParameterInfo. + + * statement.cs (ToplevelBlock.ProcessParameters): Workaround some + regression. + + * flowanalysis.cs (FlowBranching.CheckOutParameters): Move ... + * statement.cs (ToplevelBlock.CheckOutParameters): ... here. + + * statement.cs (ToplevelBlock.ResolveMeta): Move CS0136 checks ... + (ToplevelBlock.ProcessParameters) ... here. + (ToplevelBlock..ctor): Invoke it. + + * statement.cs (ToplevelBlock.ResolveMeta): Add sanity checks for + new parameters. + + * statement.cs (IKnownVariable): New interface. + (LocalInfo): Implement it. + (ToplevelParameterInfo): New class. + (ExplicitBlock.AddKnownVariable): Use IKnownVariable. + (ExplicitBlock.GetKnownVariable): Likewise. Rename from + GetKnownVariableInfo. + +2007-06-03 Raja R Harinath + + Partly speed up CS0136 error checks. + * statement.cs (ExplicitBlock.GetKnownVariableInfo): Remove + 'recurse' parameter. + (Block.DoCheckError136): Only check errors in parameters. Move + local variable checks ... + (Block.AddVariable): ... here, and ... + (ToplevelBlock.ResolveMeta): ... here. + +2007-06-02 Raja R Harinath + + * statement.cs (Block.IsChildOf): Remove. + + * statement.cs (Statement.Clone): Move special case code ... + (Block.CloneTo): ... here. + +2007-05-29 Raja R Harinath + + * statement.cs (ToplevelBlock.container): Remove field. It's + redundant with 'Parent'. + (ToplevelBlock.ContainerBlock): Remove accessor. + (ToplevelBlock..ctor): Update to changes. Register anonymous + child with parent here, ... + * cs-parser.jay (end_anonymous): ... not here. Don't modify + current_block. + (start_anonymous): Don't save current_block. + (top_current_block): Remove. + + * statement.cs (Block.Flags): Remove IsExplicit and IsToplevel flags. + (Block.Resolve): Update to changes. + (Block..ctor): Move setting of "correct" 'Toplevel' + and 'Explicit' fields to ... + (ExplicitBlock..ctor, ToplevelBlock..ctor): ... here. + +2007-05-27 Raja R Harinath + + Kill Block.Implicit + * statement.cs (Block.Implicit): Remove. + (Block): Update to changes. + * flowanalysis.cs: Likewise. + + Mildly speed up CheckInvariantMeaningInBlock + * statement.cs (ExplicitBlock.AddKnownVariable): Move here from Block. + Recursively call AddKnownVariable to all enclosing blocks. + (ExplicitBlock.GetKnownVariableInfo): Move here from Block. + Remove recursive calls. + (Block): Update to changes. + + New ExplicitBlock invariants + * statement.cs (Block.Explicit): New field. It points to the + immediately enclosing non-implicit block. + (Block..ctor): Maintain the invariant. + * cs-parser.jay: Take advantage of invariant. + + Introduce ExplicitBlock + * statement.cs (ExplicitBlock): New. + (ToplevelBlock): Derive from it. + (Block.Flags.IsExplicit): Rename from '...Implicit' and invert + sense of flag. + (Block.Implicit): Update to changes. + * cs-parser.jay: Update to changes. + + Remove unused field + * codegen.cs (EmitContext.IsLastStatement): Remove. + * statement.cs (Block.DoEmit): Update to changes. + +2007-05-25 Raja R Harinath + + * cs-parser.jay: Use 'start_block' and 'end_block' rather than + modifying current_block directly. + +2007-05-23 Scott Peterson + + * class.cs: Implemented automatic properties (C# 3.0) + Thanks to Marek for the help. + +2007-05-23 Raja R Harinath + + * flowanalysis.cs (VariableInfo.SetAssigned): When noting a + variable as assigned, note also that all its components are + assigned too. + (MyBitVector.SetRange): New. Function to set multiple bits to true. + +2007-05-19 Marek Safar + + * anonymous.cs, class.cs: Emit Compiler generated attribute when + member is marked as compiler generated. + + * decl.cs (MemberCore): Refactored ModFlags into property. + + * modifiers.cs: Add new modifier (COMPILER_GENERATED). + (Check): Check only accessibility modifiers. + +2007-05-18 Raja R Harinath + + Track all assignable slots in one bit array + * statement.cs (ToplevelBlock.ParameterMap): Convert into array. + (ToplevelBlock.ResolveMeta): Don't create a VariableMap. Move + logic from VariableMap constructor here. Use the same 'offset' + variable that's later used for computing offsets of local + variables. + * flowanalysis.cs (UsageVector.parameters): Remove. + (UsageVector): Update to changes. + (VariableMap): Remove. + + Avoid creating ParameterMap in every block + * statement.cs (Block.ParameterMap): Move ... + (ToplevelBlock.ParameterMap): ... here. + (ToplevelBlock.ResolveMeta): Create VariableMap for parameters + only once. + * flowanalysis.cs (FlowBranching.param_map): Remove. + (FlowBranching.UsageVector): Update to changes. + (FlowBranchingToplevel.CheckOutParameters): Likewise. + + * statement.cs (Block.CloneTo): Clone Toplevel field too. + + * expression.cs (ParameterReference): Distinguish between block + where parameter was referenced and declared. + +2007-05-18 Marek Safar + + * flowanalysis.cs, statement.cs: Put back improved error handling. + +2007-05-15 Scott Peterson + + * assign.cs: + * expression.cs: + Imporved object and collection initialization (C# 3.0). + +2007-05-15 Marek Safar + + A fix for bug #81380 + * expression.cs (Is.DoResolve): Only value types have constant `is' + behaviour. + +2007-05-15 Raja R Harinath + + * statement.cs (ToplevelBlock.child): Remove. + +2007-05-15 Raja R Harinath + + Rationalize ResolveMeta: refactoring + (Block.ResolveMeta): Remove wrong or superfluous comments. Carve + out constant handling code into ... + (Block.DoResolveConstants): ... this. + + Rationalize ResolveMeta: kill local_map + * statement.cs (Block.local_map, Block.LocalMap): Remove. + (Block.AssignableSlots): New. + (Block.ResolveMeta): Make protected. Don't create a VariableMap + for locals -- move code from VariableMap here. Avoid unnecessary + allocations. + * flowanalysis.cs (FlowBranching.local_map): Remove. + (FlowBranching..ctor): Use Block.AssignableSlots. + (VariableMap): Remove unused constructors. + +2007-05-11 Raja R Harinath + + * Makefile [PROFILE=net_2_0_bootstrap]: Add special-case rules. + +2007-05-11 Marek Safar + + * typemanager.cs (IsFriendAssembly): Should not be called for building + assembly. + +2007-05-09 Marek Safar + + * literal.cs (NullConstant): Print null in all cases. + + * expression.cs (Binary.ResolveOperator): Implemented delegate + comparison based on C# 2.0 changes. + +2007-04-28 Scott Peterson + + This code is contributed under the MIT X11 license + + The following enables support for several C# 3.0 language features: + + * cs-tokenizer.cs: Added support for the "var" keyword. + + * ecore.cs: Refactored TypeLookupExpression.DoResolveAsTypeStep(). + Added VarExpr class to facilitate type inferencing. + + * class.cs: Added IDictionary field AnonymousTypes to TypeContainer + to support anonymous types. + + * assign.cs: Added support for type inferencing and initialization. + + * anonymous.cs: Added AnonymousClass class to enable anonymous types. + + * expression.cs: Added implicit array support to ArrayCreation. + Added 5 types and 1 interface: + + IInitializable Implementing classes can inject initializing + statements after object instantiation. + + Initializer Stores data for object initialization. + + AnonymousType An expression for anonymous types. + + AnonymousTypeParameter Stores data about an anonymous type's field. + + NewInitialize An expression for object initialization. + + CollectionInitialize An expression for collection initialization. + + * statement.cs: Added "var" keyword support to the foreach, using, and fixed + statements. + +2007-05-06 Marek Safar + + A fix for bug #81500 + * cs-tokenizer.cs: Add special handling for coalescing operator. + +2007-05-06 Marek Safar + + A fix for bug #81529 + * attribute.cs (GetAttributeUsage): AttributeUsage attribute inherits + its value from base class until it is redefined. + +2007-05-02 Raja R Harinath + + Fix regression in cs0631-3.cs + * cs-parser.jay (operator_declarator): Add opt_attributes to error + fallback. Make error fallback catch more cases. + +2007-05-01 Miguel de Icaza + + * cs-parser.jay: Allow parameters in operator declarations to have + attributes. + +2007-04-27 Miguel de Icaza + + * statement.cs (If.CloneTo): Only clone the FalseStatement if it + exists. + + * lambda.cs (ContextualReturn.Resolve): An expression is valid + inside the ContextualReturn, it does not have to be an + ExpressionStatement. + +2007-04-24 Miguel de Icaza + + * lambda.cs (ContextualReturn.Resolve): if the return type is not + set, set it. + +2007-04-23 Miguel de Icaza + + * anonymous.cs (AnonymousContainer): split the virtual Resolve + method in two methods: ResolveNoDefine and Resolve. + + ResolveNoDefine will stop just after ResolveTopBlock has been + called. + + Resolve will then continue by creating a method and issuing the + call to method.Define (). + + (AnonymousMethod): Split and implement the new Resolve and + ResolveNoDefine as well. + + * lambda.cs (LambdaExpression): Split the anonymous method + resolution code into a separate routine (CoreCompatibilityTest) + from DoCompatibleTest. + + (LambdaExpression.TryBuild): New method, this method tries to + build the LambdaExpression with the given set of types to be used + as the types for the various parameters of the lambda expression. + + If the compilation succeed with the given types, the infered type + of the Anonymous method is returned, otherwise null is returned. + +2007-04-23 Marek Safar + + A fix for bug #81414 + * delegate.cs: Better fix, moved ApplyAttributes from Define to Emit. + +2007-04-22 Miguel de Icaza + + * cs-tokenizer.cs: Change various identifiers here from the + camelCasing to the recommended Linux-like style for instance + variables from the Coding Guidelines. + +2007-04-19 Martin Baulig + + * convert.cs + (Convert.ImplicitReferenceConversionCore): Allow conversions from + System.Enum to System.ValueType. + +2007-04-13 Martin Baulig + + Rewrote implicit reference conversions. We need to distinguish + between implicit reference conversions (13.1.4) and implicit + boxing conversions (13.1.5). + + According to the spec, there's an an implicit conversion + "From a one-dimensional array-type S[] to IList and base + interfaces of this interface, provided there is an implicit + reference conversion from S to T." Note that this does not + include boxing conversions. + + * convert.cs + (Convert.ImplicitTypeParameterBoxingConversion): New method. + (Convert.ImplicitReferenceConversion): Split into + ImplicitReferenceConversionCore() and + ImplicitBoxingConversionExist(). + (Convert.ImplicitReferenceConversionExists): Use the new + ImplicitReferenceConversionCore() and ImplicitBoxingConversionExists(). + +2007-04-12 Martin Baulig + + * convert.cs (Convert.ImplicitReferenceConversion): Move the + `TypeManager.null_type' checks up to the top of the method. + +2007-04-11 Marek Safar + + A fix for bug #81350 + * class.cs, decl.cs, ecore.cs, namespace.cs: The optimization for private + extension methods. + +2007-04-11 Martin Baulig + + * statement.cs (Foreach.CollectionForeach.ProbeCollectionType): + Use `TypeManager.GetInterfaces(t)' rather than `t.GetInterfaces()' + to make this work for generic classes; fixes #79561. + +2007-04-11 Martin Baulig + + * expression.cs (As): Add support for nullable types; fixes #79371. + +2007-04-11 Martin Baulig + + * doc.cs (DocUtil.GetSignatureForDoc): Don't crash if + `type.FullName' is null; fixes #80243. + +2007-04-11 Martin Baulig + + * expression.cs (Invocation.IsApplicable): Don't modify the method + if type inference succeeded, but the method was not applicable. + Fixes #81250. + +2007-04-10 Marek Safar + + A fix for bug #81324 + * namespace.cs (Namespace.LookupExtensionMethod): Always inspect both + internal and external namespaces containers. + +2007-04-10 Martin Baulig + + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Use + TypeManager.DropGenericMethodArguments() so we also call + IMethodData.SetMemberIsUsed() for generic methods. Fixes #80357. + +2007-04-10 Martin Baulig + + * iterators.cs (Iterator.CreateIterator): Don't crash if + `method.ReturnType' is null. This happens if something went wrong + while resolving that typ (we already reported an error in this case). + +2007-04-10 Martin Baulig + + * expression.cs (New.DoResolve): Don't call CheckComImport() on + generic interfaces; report the CS0144 directly. + +2007-04-10 Martin Baulig + + * ecore.cs (MemberExpr.ResolveMemberExpr): If `left' is a + `TypeExpr', call ResolveAsTypeTerminal() on it; fixes #81180. + +2007-04-10 Martin Baulig + + * expression.cs (New.DoEmitTypeParameter): Fix #81109. + +2007-04-09 Raja R Harinath + + A better fix + * flowanalysis.cs (UsageVector.MergeChild): Handle child.Block == null. + * statement.cs: Use KillFlowBranching only in ResolveUnreachable. + + Fix #81338 + * statement.cs (For.Resolve): If resolution fails, use + KillFlowBranching. + +2007-04-08 Marek Safar + + * anonymous.cs (MakeName): Make faster and zero-based. + (VerifyExplicitParameterCompatibility): Back to mode where generic + parameter is ignored. + (AnonymousMethodMethod.Emit): Decorate method as compiler generated. + + * class.cs (EmitType): Method can emit another new method. + + * cs-tokenizer.cs (IsLinqEnabled): Fixes static cctor race. + + * driver.cs: Updated. + + * lambda.cs: Reuse predefined empty parameters. + + * parameter.cs: Updated + + * support.cs: Implemented InflateTypes. + + * typemanager.cs (GetFullName): Don't use FullName as it can be null. + (InitSystemCore): Introduced to isolate 3.0 dependencies. + +2007-04-03 Martin Baulig + + Fix #80632. + + * statement.cs (Foreach.CollectionForeach.TryType): Use a custom + version of TypeManager.IsOverride() which also works with generic + types. + +2007-04-03 Martin Baulig + + Fix #81044. + + * convert.cs + (Convert.ExplicitReferenceConversion): We need to cast when + converting from IList to S[]. + +2007-04-01 Marek Safar + + * decl.cs (FindExtensionMethods): Consider all candidates with same name + at this level. + + * expression.cs (MemberAccess.DoResolve): Cache resolved expression. + +2007-03-31 Marek Safar + + * anonymous.cs (AnonymousMethodExpression.Compatible): Handles both + argument and return type inferring. + + * codegen.cs (InferReturnType): Flag whether return can be inferred. + (ReturnType): Turned to property. + + * statement.cs (Return): Implemented return type inferring. + + * support.cs (ReflectionParameters): Use local types if possible. + +2007-03-30 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove. + (FlowBranching.UsageVector): Update to changes. + + Prepare to kill 'Reachability' + * flowanalysis.cs (UsageVector): Remove 'Reachability' from + argument of constructor. + +2007-03-29 Raja R Harinath + + Prepare to kill 'Reachability' + * flowanalysis.cs (UsageVector.is_unreachable): New. + (UsageVector): Update to maintain 'is_unreachable' in parallel to + 'reachability', and verify they're consistent. + + Fix #81121 + * expression.cs (New.EmitStatement): Handle type parameters here too. + +2007-03-29 Martin Baulig + + Fix #79148. + + * anonymous.cs + (ScopeInfo.ctor): Use `Modifiers.PUBLIC' if we're a nested + CompilerGeneratedClass. + (ScopeInfo.EmitScopeInstance): Make this protected. + (CapturedVariable.EmitInstance): Use `Ldarg_0' if + `ec.CurrentAnonymousMethod.Scope == Scope'. + + * statement.cs (Block.ScopeInfo): Make this a property. + +2007-03-27 Raja R Harinath + + Prepare to kill 'Reachability' + * flowanalysis.cs (FlowBranching.Reachability): Make class private. + (FlowBranching.UsageVector.Reachability): Remove property. + (FlowBranching.UsageVector.IsUnreachable): New property. + (FlowBranching.UsageVector.ResetBarrier): New. + (FlowBranching.UsageVector, FlowBranchingLabeled): Update to changes. + * codegen.cs, statement.cs: Update to changes. + +2007-03-27 Martin Baulig + + Fix #81209. + + * decl.cs + (DeclSpace.LookupNestedTypeInHierarchy): Correctly handle nested + generic types. + +2007-03-26 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Use a boolean + instead of TriState. Remove all mention of TriState. + + * flowanalysis.cs (FlowBranching.Reachability): Prepare to be + replaced by a boolean. Add boolean 'is_unreachable' field, check + and maintain invariants. + +2007-03-25 Marek Safar + + * anonymous.cs: Restored checks disabled for uninflated anonymous methods. + +2007-03-25 Marek Safar + + * expression.cs: Stop using obsolete 2.0 opcodes. + +2007-03-25 Marek Safar + + * enum.cs (EnumMember.Define): Fixed regression and slowdown caused by + one of the latests Martin's fixes. + +2007-03-23 Miguel de Icaza + + * expression.cs: On BigEndian systems, swap the bytes, temporary + solution until we get a new bitconverter class. + +2007-03-23 Martin Baulig + + Fix #81158. + + * decl.cs (MemberCache.AddMembers): Add generic methods both as + "Method" and "Method`1". Normally, a cache lookup is done on the + "Method" form (ie. without the generic arity), but this one makes + lookups on the full form work as well. + +2007-03-22 Raja R Harinath + + * flowanalysis.cs (Reachability): Reorganize slightly, and remove + unused properties. + +2007-03-20 Bill Holmes + * class.cs: + Added 2 MemberCoreArrayList objects, ordered_explicit_member_list and + ordered_member_list, to TypeBuilder to store members to be defined + in the order they were parsed in. + - ordered_explicit_member_list contains all properties indexers + and methods that are defined as explicit implementation of an + interface or base class. + - ordered_member_list contains all properties indexers and methods + that are not defined as explicit implementation of an interface + or base class. + + Removed MethodArrayList and IndexerArrayList from TypeBuilder. The + functionality in these removed classes has been replaced with + ComputeIndexerName, EmitIndexerName, HasEqualss, HasGetHashCode, and + CheckEqualsAndGetHashCode members defined and called in the TypeBuilderClass. + + Adding CheckForDuplications to PropertyBase.PropertyMethod and calls + to CheckForDuplications inside GetMethod and SetMethod Define Method + to handle method property and indexer name conflicts. + + Fixes #79434 + + All code is contributed under the MIT/X11 license. + +2007-03-20 Martin Baulig + + * class.cs (TypeContainer.Interfaces): Removed; they're now + included in `TypeContainer.Types'. + +2007-03-20 Martin Baulig + + Fix #77963, #80314 and #81019. Added gtest-317, ..., gtest-320. + + * class.cs (TypeContainer.CreateType): New public method. This is + now called before DefineType() to create the TypeBuilders. + (TypeContainer.DefineType): Don't create the TypeBuilder here; it + has already been created by CreateType(). + (TypeContainer.DefineTypeBuilder): Renamed into CreateTypeBuilder(); + don't resolve our base classes here; this has been moved into + DefineBaseTypes(). We're now called from CreateType(). + (TypeContainer.DefineBaseTypes): New private method; resolve our + base classes here. We're now called from DefineType(). + + * rootcontext.cs + (RootContext.ResolveTree): Call TypeContainer.CreateType() on all + our types first to create all the TypeBuilders. After that, call + TypeContainer.DefineType() on all the types which'll resolve their + base classes and setup the resolve order. + +2007-03-20 Martin Baulig + + * class.cs (TypeContainer.Enums): Removed; they're now included in + `TypeContainer.Types'. + +2007-03-20 Martin Baulig + + * class.cs + (TypeContainer.DefineType): Don't call ResolveMembers() here. + (TypeContainer.DoResolveMembers): Call DefineType() on our + `compiler_generated' classes; moved here from DefineNestedTypes(). + + * rootcontext.cs + (RootContext.ResolveTree): Call ResolveMembers() on all + TypeContainer's in the `type_container_resolve_order'. + +2007-03-19 Marek Safar + + * class.cs: Use corlib to handle InternalMethodImplAttribute. + +2007-03-17 Marek Safar + + * class.cs (EventFieldAccessor.EmitMethod): Don't override existing + implementation flags. + +2007-03-17 Marek Safar + + * class.cs: More optimizations for type parameters. + +2007-03-15 Marek Safar + + * anonymous.cs (AnomymousMethod): Can be now hosted in generic container. + + * ecore.cs, parameter.cs: More common code for both corlibs. + + * typemanager.cs (IsGenericMethod): Simplified. + +2007-03-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove handling of + 'returns'. + * statement.cs, iterators.cs, lambda.cs: Update to changes. + + * statement.cs (Lock.Resolve): Invoke 'ec.NeedReturnLabel' + unconditionally. Simplify explanation. + (Try.Resolve, Using.Resolve): Likewise. + +2007-03-15 Martin Baulig + + Fix #80731. + + * decl.cs (DeclSpace): If we're a partial class, use our + `PartialContainer's `TypeParameters' and `CurrentTypeParameters'. + +2007-03-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove handling of + 'throws'. + (FlowBranching.UsageVector): Update to changes. + (FlowBranching.MergeSiblings): Likewise. + * statement.cs: Likewise. + +2007-03-15 Martin Baulig + + Fix #79302. + + * decl.cs + (MemberCache): Added a special .ctor for type parameters. + + * typemanager.cs + (TypeManager.MemberLookup_FindMembers): `TypeParameter' now has a + `MemberCache'. + +2007-03-09 Martin Baulig + + * enum.cs (Enum): Make this a TypeContainer. + (EnumMember): Derive from `Const'. + + * const.cs + (Const.DoResolveValue): New protected virtual method; move most of + the functionality of ResolveValue() here so we can override it in + `EnumMember'. + (Const.CreateConstantReference): Make this virtual. + + * class.cs (Kind): Add `Kind.Enum'. + (TypeContainer.Emit): Don't emit the enums here; they're already + in the `RootContext.typecontainer_resolve_order'. + + * rootcontext.cs (RootContext.EmitCode): Don't emit the enums + here; they're already in the `typecontainer_resolve_order'. + + * ecore.cs (EnumConstant.ConvertImplicitly): Add + TypeManager.DropGenericTypeArguments(). + + * typemanager.cs + (TypeManager.CSharpEnumValue): Add DropGenericTypeArguments(). + (TypeManager.IsEnumType): Likewise. + (TypeManager.EnumToUnderlying): Likewise. + (TypeManager.IsEqual): Add support for enums. + +2007-03-12 Raja R Harinath + + * typemanager.cs (InitCoreTypes) [NET_2_0]: Allow + DefaultParameterValueAttribute to be undefined, say if System.dll + is not referenced. + +2007-03-11 Marek Safar + + * ecore.cs, parameter.cs, typemanager.cs: Another gmcs fix to work with + any mscorlib. + +2007-03-10 Marek Safar + + * class.cs, parameter.cs: Unified parameters verification. + +2007-03-08 Martin Baulig + + * cs-parser.jay (constructor_header): Pass the location to the + newly created TopLevelBlock. + +2007-03-07 Martin Baulig + + * statement.cs (Block.Resolve): Don't crash on error; bug #80715. + +2007-03-06 Miguel de Icaza + + * convert.cs (ExplicitReferenceConversionExists): Sync this method + with the changes from David, fixes the build. + +2007-03-05 David Mitchell + + * convert.cs: Implement From System.Collecitons.Generic.IList + and its base interfaces to a one-dimensional array type S[], + provided there is an implicit or explicit reference conversion + from S to T. + +2007-03-03 Marek Safar + + * cs-tokenizer.cs: Implemented basic linq grammar. + + * driver.cs: Set linq lang version on demand. + +2007-02-26 Marek Safar + + * cs-parser.jay, expression.cs: Compile empty __arglist correctly. + +2007-02-25 Marek Safar + + * attribute.cs: Replaced DefinePInvoke in favor of S.R.E implementation + (Fixes #80455) + + * class.cs (InterfaceMemberBase): Share common `extern' modifier checks + here. + Check property and event extern attributes. + + * codegen.cs (ModuleClass): HasDefaultCharSet when module defined global + charset. + +2007-02-24 Marek Safar + + A fix for bug #80407 + * ecore.cs: Don't report ambiguity error when methods have same parent. + +2007-02-23 Marek Safar + + A fix for bug #80878 + * class.cs, cs-parser.jay: Event property can host anonymous methods. + +2007-02-22 Marek Safar + + * attribute.cs: Enable ExtensionAttribute presence test. + +2007-02-22 Marek Safar + + * class.cs: Warn about missing GetHashCode only when Equals is override. + + * decl.cs: Check accessibility of type arguments. + + * typemanager.cs: Correctly report nullable array. + +2007-02-20 Marek Safar + + * class.cs, report.cs: Capture more details when things go wrong. + +2007-02-20 Marek Safar + + A fix for bug #80650 + * cs-parser.jay: Anonymous container starts at constructor declaration + and not at block beginning because it has to be usable in constructor + initializer. + + * statement.cs: Use context location and not block one for error reporting. + +2007-02-18 Marek Safar + + A fix for bug #78712 + * class.cs.cs, decl.cs, ecore.cs: LookupAnyGeneric inspects nested types + too. + +2007-02-18 Marek Safar + + A fix for bug #80493 by Atsushi Enomoto + * cs-parser.jay: Ignore invalid attribute target. + +2007-02-18 Marek Safar + + * cs-tokenizer.cs: Ignore '\0' as white space character. + +2007-02-17 Miguel de Icaza + + * cs-parser.jay: Add support for lambda expressions to the mcs + compiler as well. + + * lambda.cs: Only clone when we are probing, not on the final call + (Compatible is the final call). + + * statement.cs (CloneContext): Introduce class to provide block + remapping during clone. + + All statements Clone themselves now. + + (Clone): special handling for blocks, when we clone a block, we + register the block inside this routine, as children of the block + might trigger a lookup. + + * expression.cs: Add support for CloneContext in all expressions. + +2007-02-17 Marek Safar + + A fix for bug #80493 + * statement.cs: Report ambiguous warning when interfaces are not related. + +2007-02-15 Marek Safar + + C# 3.0 extension methods. + + * attribute.cs (Error_MisusedExtensionAttribute): Extension attribute + cannot be used directly. + + * class.cs (Class.Emit): Emit extension attribute if any class method + is extension method. + (Method.Define): Add basic extension method validation conditions. + (Method.Emit): Emit extension attribute for method. + + * codegen.cs (AssemblyClass): Emit extension attribute if at least one + extension method exists. Currently we follow same approach as Microsoft + does, emit even if a method or a class are private but this can change + later. + + * cs-parser.jay: Add handling of `this' keyword in method parameters + context. + + * decl.cs (DeclSpace.IsStaticClass): New property. + (MemberCache.FindExtensionMethods): Looks for extension methods with + defined name and extension type. + + * doc.cs: Updated after OverloadResolve changes. + + * driver.cs: Add new soft reference to System.Core.dll. + + * ecore.cs (MethodLookup): Can return only MethodGroupExpr. + (ExtensionMethodGroupExpr): Represents group of extension methods. + + * expression.cs (Invocation): Moved methods BetterConversion, MoreSpecific, + BetterFunction, IsOverride, IsAncestralType, OverloadResolve + to MethodGroupExpr and made non-static for easier customization. + (Invocation.DoResolve): Add extension method lookup when no standard + method was found. + (MemberAccess.DoResolve): Try extension methods if no member exists. + + * modifiers.cs: Add METHOD_EXTENSION modifier. + + * namespace.cs (RegisterExtensionMethodClass): Register class namespace + as well as candidate extension type. + (ComputeNamespaces): When assembly constains extension methods registers + them. + (Namespace.RegisterExternalExtensionMethodClass): Register type for later + extension method lookup. + (Namespace.LookupExtensionMethod): Looks for extension method in this + namespace. + (NamespaceEntry.LookupExtensionMethod): Does extension methods lookup to + find a method which matches name and extensionType. + + * parameter.cs (Parameter): Add This modifer. + (HasExtensionMethodModifier): New property. + (Resolve): Add extension parameter check. + (ModFlags): turned to property to exclude this modifier as it is not real + parameter modifier. + (Parameters): Implemented ExtensionMethodType and HasExtensionMethodType. + + * support.cs (ParameterData): Add ExtensionMethodType. + (ReflectionParameters): Implemented ExtensionMethodType interface property. + + * typemanager.cs: Add type and ctor extension attribute type. + +2007-02-15 Miguel de Icaza + + * report.cs (DisableErrors, EnableErrors): used to prevent error + output when we are "trying" to compile various methods with + different types. + + * ecore.cs (Expression): Add Clone method that calls the virtual + CloneTo method. The current CloneTo method in Expression throws + an exception so we can track down all the places where this must + be implemented (not using abstract, because that would be a lot of + up-front-work before we can start testing the implementation + idea). + + Important: we only need Clone capabilities for expressions created + by the parser, as the expressions we will be cloning are + expressions in the pre-resolved state. This vastly simplifies + the work required. + + (SimpleName): Add CloneTo that does nothing. + (EmptyCast): Add CloneTo. + + * expression.cs (Binary): Implement CloneTo. + (Invocation.IsApplicable): Store the current ec in + EmitContext.TempEc and restore it on return. This is used so we + do not have to sprinkle hundres of methods with an extra + EmitContext, we know that the only user is the lambda expression + ImplicitConversionExists code. + + (Argument): Add Cloning capabilities. + (LocalVariableReference, ParenthesizedExpression, Unary, Probe, + Cast, Conditional, ArrayCreation, InvocationOrCast, Invocation, + ArglistAccess, ArgList, TypeOf, SizeOf, CheckedExpr, + UnCheckedExpr, ElementAccess, BaseAccess, BaseIndexerAccess, + IndexerAccess): Add Clone capability. + + (LocalVariableReference, This): TODO: needs cloned Block mapping. + + (Argument): Add cloning capability. + + * assign.cs (Assign): Implement CloneTo. + + * anonymous.cs (ImplicitStandardConversionExists): Make virtual. + + * lambda.cs (ImplicitStandardConversionExists): Implement lambda + version by calling Convert with the EmitContext (that we are + currently storing in ec, this is not great, but will do for now, + to avoid passing EmitContext parameters to hundreds of functions + that do not need them now). + + (SetExpression): Remove, it is not needed. + + (ContextualReturn): Implement CloneTo. + + * statement.cs (Statement): Implement cloning infrastructure, + similar to expressions. + + (Block): Partial implementation of Clone for statements. + + (Return): Implement clone. + + * constant.cs (Constant.CloneTo): New method, does nothing. + + * codegen.cs (TempEc): Add a static EmitContext as a temporary + solution, until we decide how to exactly do this. + +2007-02-14 Marek Safar + + A fix for bug #80493 + * class.cs (FindOutBaseMethod): When the base accessor does not exist and + a property is override we need to use second accessor. + +2007-02-13 Marek Safar + + A fix for bug #80418 + * attribute.cs, class.cs: Use correct calling conventions for pinvoke + methods. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + * class.cs Better error message. + + * driver.cs: Add shorter versions of -optimize option. + +2007-02-13 Martin Baulig + + * class.cs (Constructor.Emit): Check the return value of + ec.ResolveTopBlock() and return on error. + +2007-02-13 Raja R Harinath + + * ecore.cs (Error_InvalidExpressionStatement): Add a comma to error + message to fix error message regression. + +2007-02-12 Marek Safar + + * delegate.cs: Delegate creation expression cannot be of Nullable type. + +2007-02-12 Marek Safar + + A fix for bug #80749 + * assign.cs (FieldInitializer): FieldInitializer has to keep track of + its parent container. + + * class.cs (DefineFieldInitializers): Each initializer can has different + resolve context. + + * const.cs: Updated. + +2007-02-11 Miguel de Icaza + + * lambda.cs (LambdaExpression.Compatible): Remove some early code, + now all the heavy lifting to check that embedded statements or + expressions have the right form is done in the ContextualReturn. + + (ContextualReturn): New class. + + * ecore.cs (Error_InvalidExpressionStatement): Make a helper + method that can be invoked to report 201, so we do not replicate + this everywhere. + + * cs-parser.jay: Reuse Error_InvalidExpressionStatement. + + * cs-tokenizer.cs (xtoken): Correctly compute the column, it was + treating tabs as spaces. + +2007-02-09 Marek Safar + + A fix for bug #80315 by martin.voelkle@gmail.com (Martin Voelkle) + * assign.cs: Use full implicit conversion for right side check. + +2007-02-09 Marek Safar + + * statement.cs (Switch): Switch over boolean type is not standardized. + +2007-02-08 Marek Safar + + A fix for bug #80755 + * decl.cs (FindBaseEvent): Don't use method cache for events. + +2007-02-07 Marek Safar + + * cs-parser.jay: Better syntax error handling. + + * ecore.cs, enum.cs, statement.cs, typemanager.cs: Print enum member name + instead of underlying type value. + +2007-02-06 Marek Safar + + * driver.cs: Check define identifier before is registered. + + * namespace.cs: Use existing error message. + + * report.cs: New warning. + +2007-02-06 Marek Safar + + A fix for bug #80742 + * expression.cs: Delegate Invoke method can be called directly. + +2007-02-06 Marek Safar + + A fix for bug #80676 + * class.cs (IsEntryPoint): The Main method can have params modifier. + +2007-02-04 Miguel de Icaza + + * parameter.cs (Parameter, Parameters): Add Clone method. + + * anonymous.cs (Compatible): Turn method into virtual method, so + LambdaExpression can implement a different behavior. + + (CompatibleChecks, VerifyExplicitParameterCompatibility): Factor + out the basic checking here, so it can be used by + LambdaExpressions. + + * lambda.cs: Introduce "Compatible" function that will do the + heavy lifting. + +2007-02-02 Marek Safar + + * attribute.cs: Unified one error message. + + * class.cs (Class): Use type attributes and not properties to test static + class. + (IsEntryPoint): Don's pass local variable. + + * convert.cs: Removed duplicate check. + + * decl.cs, doc.cs, ecore.cs (LookupType): Renamed to LookupNamespaceOrType. + + * driver.cs: Don't crash when soft reference does not exist. + + * namespace.cs (EnsureNamespace): Renamed to RegisterNamespace. + (UsingEntry): Removed redundant allocation. + + * parameter.cs: Add fast path for type parameters. + + * support.cs: Don't allocate attribute when it's not used. + +2007-01-30 Miguel de Icaza + + * anonymous.cs + (AnonymousMethodExpression.ImplicitStandardConversionExists): turn + this into a virtual method, so we can override it in LambdaExpression. + + * driver.cs: Improve diagnostics in case of failure. + + * cs-tokenizer.cs: Instead of trying to parse a type and a name, + write a function that is slightly more complex and that parses: + + type identifier [, type identifier]* ) + + The old function would return incorrectly a OPEN_PARENS_LAMBDA for + this expression: + + (canEmpty ? i >= 0 : i > 0) + +2007-01-30 Raja R Harinath + + * cs-tokenizer.cs (parse_namespace_or_typename): Don't throw an + exception on possibly valid code. + +2007-01-29 Raja R Harinath + + * cs-tokenizer.cs (is_punct) ['<']: Update to changes in + Push/PopPosition. + (parse_opt_type_arguments): Remove. It's almost the same as + parse_less_than. + (parse_namespace_or_typename): Use parse_less_than. + +2007-01-28 Miguel de Icaza + + * cs-tokenizer.cs: Typo fix, its not GMCS_SOURCES but GMCS_SOURCE, + this bug took a few hours to find, because the state saved and + restored by PushPosition and PopPosition was ignoring the state of + parse_generic_less_than. + + I can also now remove the handling of OP_LT and OP_GT, this solves + the big mistery. + + * cs-tokenizer.cs: store the location for the ARROW token, we use + that in the parser. + + (PushPosition, PopPosition): save/restore also `current_token', + restore `parse_generic_less_than' (was missing). + + (parse_opt_type_arguments): use parse_type, not + parse_namespace_or_typename to parse types. + + * lambda.cs: Empty new file, will eventually have the lambda + expression implementation. + + * lambda.test: used to test the internal tokenizer. + + * report.cs (FeatureIsNotISO1): Rename from + FeatureIsNotStandardized, because it was about the language level + (1 vs 2) it was not about standarization. + + (FeatureRequiresLINQ): New. + + * support.cs (SeekableStreamReader): Only require that the reader + is a TextReader, not a StreamReader, so we can plug StringReader. + + * cs-tokenizer.cs (parse_type_and_parameter): Returns true if at a + given position in the input stream the following tokens can be + parsed as a type followed by an identifier. + + (is_punct): after a '(' if parse_type_and_parameter returns true, + then return a special token OPEN_PARENS_LAMBDA which is used to + avoid reduce/reduce errors in the grammar for the + lambda_expression rules. + + (parse_type): implement a type parser inside the + tokenizer, the parser only returns true or false depending on + whether the input at a given position can be parsed as a type. + + (peek_token): new method used during type parsing. + +2007-01-28 Raja R Harinath + + Fix #80531 + * anonymous.cs (ScopeInfo.InflateParameters): New. + (AnonymousContainer.Resolve): Use it to redirect types of + delegate parameters. + +2007-01-27 Raja R Harinath + + Fix #80530 + * expression.cs (Error_InvalidArguments): Don't use two different + messages for CS1503. Use ExtraInformation and + SymbolRelatedToPreviousError instead. + + Fix #80358 + * decl.cs (DeclSpace.initialize_type_params): Don't access + 'type_params' of a partial class directly. + +2007-01-26 Miguel de Icaza + + * constant.cs: Removed a handful of out-of-range checks that were + not necessary. + +2007-01-25 Marek Safar + + * expression.cs (CheckUselessComparison): Add additional check for char + constants. + + * namespace.cs: Fixed typo. + +2007-01-23 Miguel de Icaza + + * constant.cs: Bloat removal, CheckRange and CheckUnsigned are + gone, instead we inline the test, preventing the needless casts to + longs, ulongs and doubles for the parameters, avoiding calls to + methods that overchecked stuff, and instead inlined things + nicely. + +2007-01-20 Marek Safar + + * cs-parser.jay: Better parameter error handling. + +2007-01-17 Marek Safar + + A fix for bug #80368, #80522 + * expression.cs (ArrayCreation.only_constant_initializers): Indicates + whether array initializer contains constants only. + (ArrayCreation.Emit): Use better formula to decide when + are array initializers for static initialization. + (ArrayCreation.EmitDynamicInitializers): When the array is small enough we + have to emit even constants otherwise they are pre-initialized. + +2007-01-17 Bill Holmes + Raja R Harinath + + Fix emit order of 'get' vs. 'set'. + * support.cs (Accessors): New. + * cs-parser.jay (accessor_declarations): Use it instead of 'Pair'. + Note the order in which accessors are declared in the source. + * class.cs (PropertyBase.DefineGet, PropertyBase.DefineSet): New. + Refactored from Property.Define and Indexer.Define. + (PropertyBase.DefineAccessors): New helper that calls the above in + appropriate order as noted by the parser. + (Property.Define, Indexer.Define): Update to changes. + (PropertyBase.SetMethod.PropertyInfo): Don't return a null. + +2007-01-17 Raja R Harinath + + Fix cs0029-6.cs and gcs0029-2.cs (regression) + * ecore.cs (EmptyConstantCast.ConvertImplicitly): Check that + there's an implicit conversion from the current type to the target + type before converting the underlying constant. + +2007-01-16 Marek Safar + + * const.cs (ResolveValue): Updated after constant conversion was made more + generic. + + * constant.cs (GetAttributableValue): constant to object conversion is + used for attributes only. + (IntConstant.ConvertImplicitly): Moved from convert to be used in all + constant conversions. + (LongConstant.ConvertImplicitly): Ditto. + + * convert.cs (ImplicitNumericConversion): Extracted constant bussiness. + (ImplicitConversionStandard): Handle constant conversion as extra step. + It solves the issue when constant conversion was called indirectly like + inside array initializer and constant folding was skipped. + + * literal.cs (NullLiteral.ConvertImplicitly): Fixed an issue exposed by + this change. + + * statement.cs(ImplicitConversionStandard): Updated after constant + conversion was made more generic. + +2007-01-16 Sergey P. Kondratyev + + * expression.cs (As.DoResolve): Use GenericConstraints instead of + Constraints, solves the problem where the compiler incorrectly + reported that a type parameter was not constrained to a class (Bug + 80518) + +2007-01-14 Marek Habersack + + * doc-bootstrap.cs: Fix a compilation problem in the bootstrap phase. + +2007-01-14 Marek Safar + + A fix for bug #80368 + * assign.cs (FieldInitializer): New class implements field + initializer statement. + + * attribute.cs: Update after FieldMember rename. + + * class.cs (PropertyBasedMember): New common class for property based + types. + (InterfaceMemberBase): New base class for all members which can be used as + an interface members. + (MethodCore): Moved really common code to InterfaceMemberBase. + (Method.Define): Equal and GetHasCode detection is relevant for methods + only. + (MethodData.Define): Don't assume that public event implements an + interface automatically. + (MethodData.DefineMethodBuilder): Issue an error even if only extern + modifier is used. + (MemberBase): Moved all interface speficic code to InterfaceMemberBase. + (FieldMember): Merged with FieldBase. + (EventProperty.AEventPropertyAccessor): New specialization to check whether + event extern modifier can be used. + (EventField.EventFieldAccessor): Moved event field specific code here. + (Event.AllowedModifiers): Even event can be extern. + (Event.FindOutBaseMethod): New override specific to events. + (Indexer.parameters): Reintroduce parameters because base class holds + only properties common data. + (Indexer.CheckForDuplications): Indexers are threated as methods so we + need do extra parameters check. + + * const.cs: Update after FieldMember rename. + + * decl.cs (MemberCache.FindBaseEvent): New method. + + * doc.cs (GetMethodDocCommentName): Accept parameters as extra argument + to reflect that indexer is now derived from PropertyBased. + + * ecore.cs (GetMemberType): Made public. + (EventExpr.ResolveMemberAccess): Use right event cache and checks for + obsolete event. + + * flowanalysis.cs, statement.cs: Update after FieldMember rename. + + * typemanager.cs (CSharpSignature): Correctly print event accessors. + (RegisterEvent): Removed. + (RegisterPrivateFieldOfEvent): Renamed to RegisterEventField. + (GetPrivateFieldOfEvent): Renamed to GetEventField. + +2007-01-11 Raja R Harinath + + Fix #80249 + * statement.cs (CollectionForeach.TryType): Prefer generic + GetEnumerator over non-generic variant. Fix code to follow comments. + +2007-01-09 Raja R Harinath + + Fix #80446 + * support.cs (ReflectionParameter): Don't use an invalid index on + the generic parameter data. + +2007-01-08 Miguel de Icaza + + * driver.cs: Just add a tiny bit of infrastructure. + +2007-01-02 Marek Safar + + * class.cs (VerifyMembers): Fixed an crash reported on mono mailing list + where field type is struct from current assembly. + + * ecore.cs (EnumConstant.AsString): Report an enum member name whenever + it is possible. + +2007-01-02 Marek Safar + + A fix for bug #80381 + * attribute.cs (AttributeTester.RegisterNonObsoleteType): Registers + the core types. + + * namespace.cs (GlobalRootNamespace.LookupTypeReflection): Better error + messages. + (Namespace.LookupType): Always use core types from corlib when speficied. + + * report.cs: A new warning. + + * rootcontext.cs (BootstrapCorlib_ResolveInterface, + BootstrapCorlib_ResolveClass): Register type as non-obsolete type. + (ResolveCore): Add missing System.Runtime.InteropServices._Attribute. + + * typemanager.cs (CoreLookupType): Register type as non-obsolete type. + (InitCoreTypes): Set expression type of object_type and value_type + immediately after lookup. + +2007-01-01 Miguel de Icaza + + * cs-tokenizer.cs: Accept Pc class characters (Connector + Punctuation) as valid identifiers. Fixes #78259 + + * expression.cs (Invocation.DoResolve): Moved the check for the + use of `this' for doing method calls to the Invocation resolution + step, after overload resolution has taken place instead of doing + the check at the low-level `This.DoResolve' level. + + The `This.DoResolve'(appens before overload resolution, so it has + no way of knowing if the method that will be called will be + instace or static, triggering an erroneous report for cs0188 (Bug + 78113). + + We now do the check for instance method invocations after we know + what method will be called. + + (This.CheckThisUsage): Move the actual use of this structure + checking into its own method and expose it. + + * Everywhere that called Error_ValueCannotBeConverted: pass a new + EmitContext. + + Exceptions: Null.ConvertImplicitly, + Constant.ImplicitConversionRequired as there are too many call + sites for passing the ec. + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Take an + EmitContext, if the value is null, then we do not try to provide + the extra information from the error (If a userdefined conversion + exists, as UserDefinedConversion requires a non null-EmitContext). + + Fixes: #80347 + +2006-12-30 Raja R Harinath + + * flowanalysis.cs (MyBitVector): Document some invariants. + (MyBitVector.Or, MyBitVector.And): Reimplement the optimizations + introduced below, and add a couple of others, + +2006-12-30 Marek Safar + + * attribute.cs (GetMethodObsoleteAttribute): Uses new + GetPropertyFromAccessor and GetEventFromAccessor. + + * class.cs (MethodCore.CheckBase): A new warning when obsolete member + overrides non-obsolete one. + (Indexer.Define): Error message has been moved to the parser. + + * cs-parser.jay: Better syntax errors handling. + + * delegate.cs (NewDelegate.DoResolve): Issue less confusing error message + when an invocation has no arguments. + + * ecore.cs: Removed not used caching. + + * expression.cs (IsSpecialMethodInvocation): Reuses TypeManager + implementation. + + * report.cs: Add a new warning. + + * support.cs (ReflectionParameters): Implements Equals, GetHashCode. + + * typemanager.cs (enumeration_type): Removed. + (CSharpSignature): Reuses IsSpecialMethod. + (IsEqual): Hack for MS BCL. + (GetPropertyFromAccessor): New method. + (GetEventFromAccessor): New method. + (IsSpecialMethod): Fixed to handle more cases. + +2006-12-30 Marek Safar + + * cs-tokenizer.cs (PreProcessDefinition, handle_preprocessing_directive): + Made white spaces array static. + + * ecore.cs (RemoveGenericArity): Optimized. + + * flowanalysis.cs (MyBitVector.Or, MyBitVector.And): Optimized (up to + 10 times faster). + (MyBitVector.initialize_vector): Simplified. + +2006-12-22 Miguel de Icaza + + * ecore.cs: Am not entirely happy with this hack, but it seems to + address the issue in 80257 (a small test case for + CreativeDocs.NET). + + I set the MethodGroupExpr.Type to an internal compiler type + (itself in this case) to force the resolution to take place. Why + it does not take place with a null is beyond me. + +2006-12-20 Marek Safar + + A fix for bug #80288 + * expression.cs (ResolveOperator): Consider user defined conversion for + logical and operator too. + (EmitBranchable): Optimization for logical and when full constant folding + could not be applied but one operand is constant. + +2006-12-19 Marek Safar + + * class.cs (GetClassBases): Write 5 times every day, will never use + FullName for error reporting. + + * decl.cs (AsAccessible, CheckAccessLevel): Always unpack arrays first. + +2006-12-19 Martin Baulig + + * statement.cs (LocalInfo.EmitSymbolInfo): New public method; emit + the symbol file info here. + +2006-12-18 Marek Safar + + * cs-tokenizer.cs (handle_preprocessing_directive): When previous section + of `elseif' is taking then following sections are not taking. + Fixes an issue reported on mono mailing list. + +2006-12-18 Marek Safar + + A fix for bug #80300 + * cs-tokenizer.cs (PreProcessDefinition): Do no define/undefine when + a caller is not taking. + +2006-12-18 Raja R Harinath + + * anonymous.cs: Change several TypeContainer declarations to DeclSpace. + (CompilerGeneratedClass): Use parent.PartialContainer unconditionally. + (RootScopeInfo, AnonymousMethodMethod): Update to changes. + * iterator.cs: Change several TypeContainer declarations to DeclSpace. + * class.cs: Update to changes. + +2006-12-17 Marek Safar + + A fix for bug #79934 + * anonymous.cs (CompilerGeneratedClass): Register class in a shared + partial container. + + * class.cs (ResolveMembers): Register an iterator in current container and + not in shared one. + +2006-12-16 Raja R Harinath + + Fix test-543.cs + * expression.cs (VerifyArgumentsCompat): Allow zero arguments to + satisfy a params annotated parameter. + +2006-12-16 Marek Safar + + A fix for bug #77014 + * expression.cs (Invocation.BetterFunction): Fixed to cope with dynamic + paramters correctly and not rely on hacks in Parameters class. + (Invocation.IsParamsMethodApplicable): Changed to accept params parameter + at any possition. + (Invocation.VerifyArgumentsCompat): Ditto. + (Invocation.EmitArguments): Changed to correctly emit params arguments at + any possition. + + * parameter.cs (HasParams): Don't assume that params is the last one. + + * support.cs (ReflectionParameters.ctor): Look for params attribute + correctly. + (ReflectionParameters.ParameterType): Removed hack when we returned last + parameter for out of range parameters. + (ParameterName, ParameterModifier): Ditto. + +2006-12-14 Marek Safar + + A fix for bug #79987 + * decl.cs (DeclSpace.VerifyClsCompliance): External names cache is null + when assembly is not CLS compliant but type is. I have no idea why is this + allowed. + + * typemanager.cs (Reset): Invalidate AllClsTopLevelTypes cache. + +2006-12-13 Miguel de Icaza + + * class.cs (ConstructorInitializer.Resolve): Allow for ":this()" + in struct constructors, they are basically no-ops. + +2006-12-12 Marek Safar + + * cs-tokenizer.cs (Position): Save preprocessor status too. + +2006-12-12 Marek Safar + + A fix for bug #77794 + * cs-tokenizer.cs (consume_identifier): Check for correct partial context. + +2006-12-12 Marek Safar + + * cs-tokenizer.cs (get_cmd_arg): Support CR as the line terminator. + Fixes #69299. + (pp_expr): Report error for an invalid expression. + (handle_preprocessing_directive): Simplified; add more error checking. + +2006-12-11 Marek Safar + + A fix for bug #74939 + * cs-tokenizer.cs (is_punct): We cannot simply disable preprocessor + directives handling. + +2006-12-10 Marek Safar + + A fix for bugs #80093, and #75984 + * cs-tokenizer.cs (handle_preprocessing_directive): Fixed #if/#else/#endif + logic, it seems to me as it worked before "by coincidence". + (xtoken): Simplified to use reworked handle_preprocessing_directive. + (cleanup): Enabled endif check. + +2006-12-09 Marek Safar + + A fix for bug #80162 + * statement.cs (CollectionForeach.TryType): Generics and non-generics + enumerators are never ambiguous. + +2006-12-08 Raja R Harinath + + Fix #80060 + * cs-tokenizer.cs (parse_less_than): Recognize double-colons too. + +2006-12-06 Marek Safar + + A fix for bug #80144 + * class.cs (EventProperty.Define): Explicit implementation means + that an even is used. + +2006-12-06 Marek Safar + + Fixes the operators implementation (part II) + + * cfold.cs (DoConstantNumericPromotions): Renamed to + DoBinaryNumericPromotions and simplified. + (BinaryFold): Couple of conversion fixes; simplified. + + * constant.cs, ecore.cs, literal.cs + (ToType): Renamed to ConvertImplicitly. + (Reduce): Renamed to ConvertExplicitly. + + * class.cs, convert.cs: Updated. + + * expression.cs: TryReduce doesn't throw an exception. + +2006-12-01 Marek Safar + + A fix for bug #80108 + * ecore.cs (EventExpr.EmitAddOrRemove): Don't crash when right side is not + compatible. + +2006-11-30 Marek Safar + + Fixes unary operators implementation (part I) + Also fixes #80026 + + * cfold.cs (Error_CompileTimeOverflow): Made internal + + * const.cs (IConstant): Changed to use reference to constant and + not constant itself. + Updated IConstant implementations. + + * constant.cs (CreateConstant): New factory method. + Updated IConstant implementation. + + * convert.cs (ImplicitStandardConversionExists): Uses compiler Equals. + + * ecore.cs: Updated to use CreateConstantReference. + + * enum.cs: Reflects IConstant changes. + + * expression.cs (Unary): Reimplemented +,-,~ to conform C# standard. + + * literal.cs (NullConstant): Change to be independently usable. + +2006-11-29 Martin Baulig + + * class.cs (Constructor.Emit): Correctly handle anonymous methods; + we need to emit the scope initializer before calling the base .ctor. + + * anonymous.cs: Merged back from the new anonymous methods branch. + (AnonymousMethodHost): Renamed to `RootScopeInfo'. + + * expression.cs (ParameterReference.DoResolveBase): Create a + "normal" ScopeInfo when capturing parameters rather than using the + root scope; this makes things work with anonymous methods having + parameters. + + * statement.cs + (ToplevelBlock.AnonymousMethodHost): Renamed into `RootScope'. + +2006-11-22 Marek Safar + + A fix for bug #79987 + * class.cs (VerifyClsCompliance): Move redundant CLS compliance attribute + check to a base class. + * decl.cs (VerifyClsCompliance): Warn that CLS compliance cannot be tested + only when assembly has missing attribute. + * report.cs: Update. + +2006-11-21 Marek Safar + + * cs-tokenizer.cs: Merged with gmcs version. + +2006-11-20 Marek Safar + + * cs-tokenizer.cs, + * cs-parser.jay: Better error message when partial keyword is misplaced. + +2006-11-19 Gert Driesen + + A fix for bug #79810 + report.cs: CS1058 only applies to 2.0 profile (gmcs). + codegen.cs: on 2.0 profile, non-exception throwables are wrapped in + a RuntimeWrappedException by default. + +2006-11-18 Marek Safar + + A fix for bug #79843 + * delegate.cs (Delegate.VerifyMethod): Fixed covariance and contravariance + implementation. + (DelegateCreation.Error_NoMatchingMethodForDelegate): Ditto. + +2006-11-18 Marek Safar + + * driver.cs, namespace.cs: Uses faster IndexOf version. + +2006-11-17 Marek Safar + + A fix for bug #79941 + * class.cs (MemberCore.IsDuplicateImplementation): Add more tricks for + operators. + (Operator.Define): Implicit/Explicit operator of same type is duplicate + even if internal name is different. + * convert.cs (GetConversionOperator): Replaced EmitContext with parentType. + (UserDefinedConversion): Simplified as the operators cannot be internal. + * ecore.cs (Error_ValueCannotBeConverted): Take account of user + conversions. + (MethodLookup): Replaced EmitContext with parentType. + * expression.cs: Updated. + +2006-11-09 Raja R Harinath + + * driver.cs (BadAssembly): Handle all the ugliness of + DefineDynamicAssembly. + +2006-11-08 Raja R Harinath + + Address parts of #58244 -- most of what's left is in the runtime + * driver.cs (LoadAssembly): Simplify slightly. Add CS0009 and + CS1509 error checks, and handle them for all assembly loads, not + just the first invocation. + (LoadModule): Likewise. Move handling of 'adder_method' ... + * codegen.cs (AssemblyClass.AddModule): ... here. + +2006-11-02 Marek Safar + + * statement.cs.cs (CollectionForeach.TryType): Issue a error when + IEnumerable is ambiguous. + +2006-10-31 Marek Safar + + A fix for bug #67689 + * statement.cs.cs (CollectionForeach.TryType): Issue a warning when + GetEnumerator is ambiguous. + + * report.cs: Add new warning. + +2006-10-29 Marek Safar + + A fix for bug #78602 + ecore.cs (PropertyExpr.InstanceResolve): The qualifier for access + to protected member can be nested type. + +2006-10-28 Marek Safar + + A fix for bug #78965 + ecore.cs (PropertyExpr.InstanceResolve): The qualifier for access + to protected member must derive from current type. + +2006-10-27 Marek Safar + + assign.cs: Reuses error method. + + ecore.cs (Expression.Error_ValueCannotBeConverted): Report a value + instead of type for constants. + (Expression.Error_ValueAssignment): Common error method. + + * expression.cs (UnaryMutator.ResolveOperator): Value cannot be used + for any assignment. + +2006-10-27 Marek Safar + + A fix for bug #79081 + * expression.cs (MemberAccess.DoResolve): Check nested type + accessibility. + +2006-10-27 Atsushi Enomoto + + * doc.cs : nested delegates were not handled. Fixed bug #79754. + +2006-10-26 Marek Safar + + A fix for bug #76591 + * cs-tokenizer.cs (IsCastToken): Enable a cast of anonymous method. + +2006-10-26 Marek Safar + + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Don't allow to have + type forwarder of the same type multiple times. + +2006-10-26 Raja R Harinath + + Fix #78820 + * ecore.cs (PropertyExpr.InstanceResolve): Always resolve the + instance as an rvalue, even when we later resolve as an lvalue. + +2006-10-25 Martin Baulig + + * anonymous.cs: Fix #79673. + +2006-10-24 Marek Safar + + A fix for bug #79666 + expression.cs (ArrayCreation.GetAttributableValue): An initializer can be + ignored when is optimized (= default value) as its value is already set. + +2006-10-23 Marek Safar + + A fix for bug #79724 + * report.cs (SymbolRelatedToPreviousError): Uses DeclSpace instead of + TypeContainer for type lookup. + +2006-10-23 Marek Safar + + A fix for bug #79231 + * ecore.cs (ResolveAsBaseTerminal): Removed redundant error test. + * expression.cs (OverloadResolve): Always convert type name for + an error message. + (ResolveNamespaceOrType): Don't confuse a nested type with any + other member. + +2006-10-18 Martin Baulig + + * anonymous.cs: Propagate the IsStatic state, fixes the crasher in banshee. + +2006-10-17 Miguel de Icaza + + * convert.cs: Fix typo, fixes the test-535.cs, we were casting to + an int32, but requesting an int64 from the conversion + +2006-10-12 Martin Baulig + + * anonymous.cs + (AnonymousContainer.Resolve): Inflate the `ReturnType'. Fixes #79592. + +2006-10-12 Martin Baulig + + * statement.cs + (Using.EmitLocalVariableDeclFinally): Small fix for iterators. + +2006-10-11 Miguel de Icaza + + * convert.cs: Remove broken code: I was doing the "Existance" + tests for Implicit conversions. + +2006-10-10 Miguel de Icaza + + * convert.cs: Added one missing case in + ImplicitStandardConversionExists uint64 to intptr. + + Fixes #59800 + + * typemanager.cs (uintptr_type): another core known type. + + * ecore.cs (OperatorCast): routine used to do cast operations that + depend on op_Explicit. We could change some of the Decimal + conversions to use this. + + This one has a probe mechanism that checks both types for an op_ + which it coudl be used to eliminate two classes: CastToDecimal + and CastFromDecimal. + + * convert.cs: Implement the conversions documented in #59800 + +2006-10-10 Martin Baulig + + * iterators.cs (Iterator.Resolve): Call RootScope.ResolveType() + before RootScope.ResolveMembers(). + + * anonymous.cs (ScopeInfo.CapturedScope.ctor): Use the child's + `CurrentType' if appropriate. + +2006-10-09 Marek Safar + + A fix for bug #78568 + * cs-tokenizer.cs (Deambiguate_CloseParens): Expression cannot be cast + when contains binary operators. + * cs-parser.jay: Updated. + +2006-10-09 Martin Baulig + + * delegate.cs + (Delegate.DefineType): Don't call TypeParameter.Resolve() here; + moved that into Define() and also do the other type parameter + checks there. Fixes #79094. Added gtest-292.cs. + + * expression.cs + (ArrayCreation.EmitDynamicInitializers): Use `etype.IsValueType' + since that doesn't include type parameters; don't use `Ldelema' + for type parameters. Fixes #78980. Added gtest-293.cs. + +2006-10-08 Marek Safar + + A fix for #77796 + * convert.cs (ExplicitReferenceConversion): Only enum to enum value + conversion is allowed. + +2006-10-06 Marek Safar + + * ecore.cs (Expression.MemberLookup): Don't register any symbol for + error reporting when no error occurs. + +2006-10-06 Marek Safar + + * cfold.cs (ConstantFold.BinaryFold): Report an error when the conversion + does not exist. + +2006-10-06 Raja R Harinath + + Fix #79584 + * class.cs (DefineTypeBuilder): Check circular dependencies before + setting the parent of the TypeBuilder. + (CheckRecursiveDefinition): Don't use 'BaseType', since + it may not be valid until after DefineTypeBuilder. Use + 'base_type' instead. + +2006-10-04 Martin Baulig + + Merged the Anonymous Methods patch. + + * anonymous.cs, iterators.cs: The new anonymous methods code. + + * statement.cs (Variable): New public abstract class. + (LocalInfo.Variable): New public property. + (LocalInfo.ResolveVariable): New public method. + (Block.Flags): Add `IsIterator'. + (Block.AddVariable): Improved the CS0136 check. + (Block.AnonymousChildren): New public property. + (Block.AddAnonymousChild): New public method. + (ToplevelBlock): Update to use the new anonymous method framework. + (ToplevelBlock.ctor): `container' is now a `Block' and not a + `ToplevelBlock'; this is required to correctly implement the + CS0136 check. + (Fixed, Using): Use `TemporaryVariable' instead of directly + creating the `LocalBuilder'. + + * parameter.cs (Parameter.ResolveVariable): New public method. + (Parameters.ResolveVariable): Likewise. + + * ecore.cs (TemporaryVariable): Use the new `Variable' framework. + + * class.cs (TypeContainer): Replaced the `iterators' list and + corresponding methods with a list of `CompilerGeneratedClass'es. + (TypeContainer.ResolveMembers): New public method. + (Method): `IIteratorContainer' has been replaced by + `IAnonymousHost'. + + * expression.cs (VariableReference): New public abstract base + class for `LocalVariableReference', `ParameterReference' and + `This'. + + * codegen.cs (EmitContext): Removed `capture_context', + `HaveCaptureInfo', `EmitScopeInitFromBlock()' and `Capture*()'. + (EmitContext.EmitThis): Removed. + + * cs-parser.jay: Replace `iterator_container' with + `anonymous_host'. + +2006-10-04 Martin Baulig + + * generic.cs (GenericMethod): Don't make this abstract. + (Constraints.Clone): Added dummy implementation. + +2006-10-04 Raja R Harinath + + Fix #79577 + * namespace.cs (LookForAnyGenericType): Avoid nullref on + 'declspaces'. Avoid allocating arrays willy-nilly. + + Fix #79553 + * cfold.cs (BinaryFold): Move boolean Equality and Inequality + cases out of the switch. + +2006-09-28 Marek Safar + + * namespace.cs (Namespace.Error_NamespaceDoesNotExist): Better error + message when non-generic type is used with the type arguments. + * expression.cs: Updated. + +2006-09-28 Raja R Harinath + + Fix #79013 + * convert.cs (Convert.ImplicitStandardConversionExists): Avoid infloop. + * expression.cs (EmptyExpression.Grab, EmptyExpression.Release): + Change semantics slightly. Don't insist on having only one + temporary EmptyExpression -- just throttle the creation of new ones. + + Fix #79451 + * ecore.cs (Expression.MemberLookup): Enable CS0229 errors for + non-interfaces too. If no methods are found, don't try to create + a MethodGroupExpr. + +2006-09-28 Marek Safar + + * ecore.cs (ResolveAsTypeStep): Print better error when type can be + generic type. + + * namespace.cs (Namespace.LookForAnyGenericType): New method to help + us produce better error message. + +2006-09-27 Marek Safar + + * expression.cs (Binary.ResolveOperator): Warn about a side effect + of the `|' operator. + + * report.cs: A new warning added. + +2006-09-27 Martin Baulig + + * generic.cs (GenericMethod): Don't make this abstract. + +2006-09-27 Martin Baulig + + * report.cs + (InternalErrorException): Added overloaded ctor taking a params array. + +2006-09-26 Marek Safar + + * class.cs, codegen.cs, const.cs, cs-tokenizer.cs, driver.cs, ecore.cs: + Fixed the cases when same error was reported twice. + + * report.cs (SymbolRelatedToPreviousError): Simplified as all our messages + now report symbol information. + +2006-09-25 Martin Baulig + + * class.cs: Completely unified with the gmcs version. + +2006-09-25 Martin Baulig + + * typemanager.cs (TypeManager.IsNullableType): New public function. + (TypeManager.IsNullableTypeOf): Likewise. + (TypeManager.IsNullableValueType): Likewise. + + * class.cs (MethodCore): Added the `GenericMethod' argument from + gmcs and also unified all classes derived from `MethodCore' with gmcs. + +2006-09-24 Raja R Harinath + + * convert.cs: Unify with gmcs version. + +2006-09-24 Marek Safar + + * decl.cs (DeclSpace.VerifyClsCompliance): When type has type parameters + verify them as well. + + * report.cs: New warning. + +2006-09-24 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Cannot generate arguments + for anonymous block with out argument. + +2006-09-24 Marek Safar + + * class.cs (ClassOrStruct.VerifyMembers): Fixed to report correctly + not used private events only. + +2006-09-23 Marek Safar + + * cfold.cs (BinaryFold): On the guest to unify empty constant cast. + + * const.cs (Const.Define): Check for constant type. + (Const.IsConstantTypeValid): Looks for valid constant types. + + * convert.cs (ImplicitReferenceConversion): NullCast to EmptyConstantCast. + + * ecore.cs (EmptyConstantCast): New common class for all constant based + EmptyCast(s). + + * expression.cs (Is.DoResolve): Handle null constant especially. + (New.DoResolve): Check for new void(). + (MemberAccess.DoResolve): Cope with all kind of nulls. + + * literal.cs (NullConstant): Uses EmptyConstantCast. + (NullDefault): Based on EmptyConstantCast. + (NullLiteral): Uses EmptyConstantCast. + + * statement.cs (Block.ResolveMeta): Check for constant type. + +2006-09-22 Martin Baulig + + * delegate.cs, attribute.cs: Merged with the gmcs versions. + +2006-09-22 Raja R Harinath + + * literal.cs (NullDefault): The type of default(IFoo) is 'IFoo', + not the null type. + + Fix part of #79451 + * typemanager.cs (Closure.Filter): Consider PrivateScope attributes. + * decl.cs (DeclSpace.FindMemberToOverride): Likewise. Reorganize + code slightly. + +2006-09-22 Martin Baulig + + * ecore.cs: Merged with the gmcs version. + + * generic.cs (ConstructedType): New dummy class. + (TypeArguments): Don't make this abstract. + + * typemanager.cs + (TypeManager.IsGenericTypeDefinition): New method. + (TypeManager.GetGenericFieldDefinition): Moved here from gmcs. + +2006-09-22 Raja R Harinath + + * expression.cs (ComposedCast): Check for arrays of TypedReference + before creating the type, not after. + +2006-09-21 Marek Safar + + * cfold.cs, const.cs, enum.cs, statement.cs: Updated + after ToType change. + + * constant.cs (Constant.ImplicitConversionRequired): Designed to used + when constant must be implicitly convertible. + + * convert.cs (ImplicitReferenceConversion): Reuse ToType. + + * ecore.cs (NullCast): Derives from NullConstant. + + * expression.cs (Is.DoResolve): Removed useless variables. + (Conditional.DoResolve): Quick hack for `Foo () ? null : null'. + (New.Constantify): Add enum support. + (MemberAccess.DoResolve): Add warning when accessing null constant or + variable. + + * generic.cs (GenericConstraints.IsReferenceType): Another dummy + property. + + * literal.cs (NullConstant): New abstract class with common + functionality for all null specializations. + (NullDefault): Represents default(X) when result can be + reduced to null. + (NullLiteral): Updated. + + * report.cs: Add new warning. + +2006-09-21 Martin Baulig + + * generic.cs (GenericTypeParameterBuilder): Removed this ugly hack. + +2006-09-21 Martin Baulig + + * generic.cs (GenericConstraints): New dummy class. + (Constraints): Likewise. + (TypeParameter): Likewise. + (TypeParameterName): Likewise. + (GenericMethod): Likewise. + + * typemanager.cs (TypeManager.GetGenericArguments): New method. + + * decl.cs: Merged with the gmcs version. + +2006-09-21 Raja R Harinath + + * generic.cs (TypeParameter): Implement IMemberContainer. + (GenericTypeParameterBuilder): New. An abominable repugnant hack. + + * rootcontext.cs: Unify with gmcs version. + + * report.cs: Unify with gmcs version. + * typemanager.cs (AddTypeParameter, LookupTypeParameter): Move + from gmcs/generics.cs. + * generics.cs (TypeParameter): New dummy class. + + * support.cs: Unify with gmcs version. + +2006-09-20 Raja R Harinath + + * ecore.cs (MethodGroupExpr.ResolveGeneric): New dummy method. + * expression.cs (MemberAccess, BaseAccess): Remove GMCS_SOURCE #ifdef. + + * decl.cs (MemberName): Unify with gmcs, except for GetTypeExpression. + * generic.cs (TypeArguments): New dummy class to help avoid #ifdefs. + * mcs.exe.sources: Add generic.cs. + + * codegen.cs: Unify with gmcs version. + + * codegen.cs (IResolveContent.GenericDeclContainer): Copy from gmcs. + (EmitContext): Add GenericDeclContainer implementation. + * decl.cs (MemberCore, DeclSpace): Likewise. + * namespace.cs: Remove #ifdef GMCS_SOURCE. + + * namespace.cs (GetTypeInAssembly): Remove #ifdef GMCS_SOURCE. + MCS TypeManager has a corresponding dummy method. + +2006-09-19 Martin Baulig + + * expression.cs: Completely merged with the gmcs version. + +2006-09-19 Martin Baulig + + * expression.cs (Invocation): Merged with the gmcs version. + (ArrayAccess.GetStoreOpcode): Likewise. + +2006-09-19 Martin Baulig + + * typemanager.cs + (TypeManager.IsGenericMethod): Moved here from ../gmcs/generic.cs. + (TypeManager.IsGenericMethodDefinition): Likewise. + +2006-09-19 Martin Baulig + + * typemanager.cs + (TypeManager.IsEqual): Moved the gmcs implementation here. + (TypeManager.DropGenericTypeArguments): Likewise. + (TypeManager.DropGenericMethodArguments): Likewise. + (TypeManager.GetTypeArguments): Moved here from gmcs. + (TypeManager.HasGenericArguments): Likewise. + +2006-09-19 Martin Baulig + + * expression.cs (Binary): Merged with the gmcs version. + +2006-09-19 Martin Baulig + + * expression.cs (Probe, As, Is): Merged with the gmcs version. + +2006-09-19 Martin Baulig + + * typemanager.cs: Merged with the gmcs version. + +2006-09-16 Raja R Harinath + + * AssemblyInfo.cs [GMCS_SOURCE]: Unify with gmcs source. + * driver.cs: Likewise. + +2006-09-16 Marek Safar + + A fix for #79401 + * class.cs (MethodCore.VerifyClsCompliance): Do check for abstract members + only if parent type is class. + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Fixed missing cache + update. + +2006-09-15 Marek Safar + + * cs-parser.jay, + * expression.cs(MemberAccess.DoResolve): Don't crash when not allowed + keywords are used. + * typemanager.cs(CSharpName): Converts NullType to null. + +2006-09-15 Martin Baulig + + * typemanager.cs + (TypeManager.GetMethodName): Added mcs implementation. + (TypeManager.IsEqual): Likewise. + + * ecore.cs + (SimpleName.RemoveGenericArity): Added dummy implementation. + + * pending.cs: Merged with the gmcs version. + +2006-09-15 Martin Baulig + + * statement.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * statement.cs (Switch): Merge with the gmcs implementation + (without nullables), which is newer. + +2006-09-15 Martin Baulig + + * statement.cs (Block.Variables): Make this public. + (ToplevelBlock.Parameters): Make this a property. + (Throw.Resolve): Use `TypeManager.IsSubclassOf ()'. + +2006-09-15 Martin Baulig + + * namespace.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * decl.cs (MemberName): Minor code cleanups. + +2006-09-15 Martin Baulig + + * parameter.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * enum.cs: Merge with the gmcs version: 3005 is a warning in gmcs + and an error in mcs. + +2006-09-15 Martin Baulig + + * flowanalysis.cs: Merged from GMCS; added the generics code into + a `GMCS_SOURCE' conditional so we can share this file. + +2006-09-08 Martin Baulig + + * typemanager.cs (TypeManager.interlocked_type): New public field. + (TypeManager.int_interlocked_compare-exchange): New public field. + (TypeManager.InitEnumUnderlyingTypes): Also initialize the + enumerator types here and call InitGenericCoreTypes(). + (TypeManager.InitCoreTypes): Call InitEnumeratorTypes() right + after calling InitEnumUnderlyingTypes(). + + * rootcontext.cs + (RootContext.ResolveCore): Added `System.Threading.Interlocked' to + `classes_second_stage'. + +2006-09-14 Marek Safar + + * assign.cs, ecore.cs, expression.cs: Share error message text. + * class.cs (FieldMember.Define): Check for varible of static type. + * driver.cs (LoadAssembly): Uses error output for errors. + * statement.cs: Updated. + +2006-09-08 Marek Safar + + * expression.cs (Error_OperatorCannotBeApplied): Report type instead of + type instance. + +2006-09-07 Martin Baulig + + * driver.cs + (MainDriver): Revert r62663 from Marek; see #70506 for details. + +2006-08-29 Miguel de Icaza + + * cs-parser.jay: Turn 1522 into a warning, instead of an error #79210 + +2006-08-17 Miguel de Icaza + + * cs-tokenizer.cs: Apply patch from Atsushi Enomoto that fixes + #52019 and #79064, the use of the \uXXXX sequence in source code + to represent unicode characters. + +2006-08-15 Marek Safar + + * expression.cs (SizeOf.DoResolve): Check for void type. Fixed enum types + support. + * class.cs, ecore.cs, statement.cs: Merged to one error message. + +2006-08-13 Miguel de Icaza + + * assign.cs: Catch attempts to assign to a method groups in += and + report as 1656 + +2006-08-13 Marek Safar + + A fix for #79056 + * cs-parser.jay: Don't destroy current array type by typeof of array's. + +2006-08-12 Marek Safar + + * class.cs (Method.Define): Issue a warning when generic method looks like + an entry point. + * decl.cs (MemberCore.GetSignatureForError): Print member type arguments + as well. + +2006-08-09 Marek Safar + + * anonymous.cs(AnonymousDelegate.Emit): Uses Constructor filter when + looking for ctor. + * decl.cs (MemberCache.FindMembers): When container is interface we need to + search all base interfaces as a member can be ambiguous. + * delegate.cs (Delegate.FindMembers): Fixed to return valid data for + Constructor member type filter. + (Delegate.ResolveConstructorMethod) Uses Constructor filter. + * ecore.cs: (Expression.MemberLookup): Implemented ambiguity error/warning + reporting for returned memberinfos. + * report.cs: Updated. + * typemanager.cs (TypeManager.LookupBaseInterfacesCache): Uses TypeManager + version to work on all runtimes. + (TypeManager.RealMemberLookup): Removed members filtering. + +2006-08-08 Raja R Harinath + + * ecore.cs (FieldExpr.EmitAssign): Release temporary. + (PropertyExpr.EmitAssign): Likewise. + * expression.cs (Indirection.EmitAssign): Likewise. + (LocalVariableReference.EmitAssign): Likewise. + (ParameterReference.EmitAssign): Likewise. + (Invocation.EmitArguments): Likewise. + (ArrayAccess.EmitAssign): Likewise. + (IndexerAccess.EmitAssign): Likewise. + (This.EmitAssign): Likewise. + (ConditionalLogicalOperator.Emit): Likewise. + + Fix #79026 + * codegen.cs (EmitContext.GetTemporaryLocal): Simplify. Use Stack + instead of ArrayList. If the hashtable has a LocalBuilder, don't + leave it in after returning it. + (EmitContext.FreeTemporaryLocal): Simplify. Update to changes. + +2006-08-06 Marek Safar + + * expresssion.cs (IndexerAccess.DoResolve): Fixed to report correct error + message. + +2006-08-03 Raja R Harinath + + Fix cs0146-3.cs and cs0146-4.cs. + * class.cs (TypeManager.CheckRecursiveDefinition): Check that + enclosing types don't depend on the current type. + +2006-08-02 Raja R Harinath + + Fix #77963 + * class.cs (TypeContainer.DoDefineMembers): Use + FindBaseMemberWithSameName on Parent, since we're interested in + whether we hide inherited members or not. + (FindBaseMemberWithSameName): Make slightly more robust. + + Fix the non-generic testcase from #77396 + * decl.cs (DeclSpace.DeclContainer): Remove override. + + * namespace.cs (NamespaceEntry.Doppelganger): Create slave + declspaces for doppelgangers too. + (UsingEntry): Implement IResolveContext. + (UsingEntry.Resolve): Don't set ToplevelTypes.Namespace. Use + 'this' as the resolve context. + (LocalAliasEntry): Likewise. + + Implement parts of #77403 + * roottypes.cs (RootDeclSpace): New. Used to represent the + toplevel declaration space. Each namespace declaration introduces + a "partial" root declaretion space. + * namespace.cs (NamespaceEntry.SlaveDeclSpace): New. + (NamespaceEntry.ctor): Create a SlaveDeclSpace if necessary. + * cs-parser.jay (CSharpParser.ctor): Initialize 'current_class' + from 'current_namespace.SlaveDeclSpace'. + (namespace_declaration): Likewise. + * class.cs (TypeContainer.ctor): Remove parent==ToplevelTypes + check. It can't happen now. + * decl.cs (DeclSpace.LookupType): Likewise. + * driver.cs (MainDriver): Sanity check. + +2006-08-01 Raja R Harinath + + * decl.cs (DeclSpace.FindNestedType): Remove. + (DeclSpace.LookupNestedTypeINHierarchy): Use PartialContainer and + LookupTypeContainer to get the container of the nested type. + * class.cs (TypeContainer.FindNestedType): Make non-override. + +2006-07-31 Raja R Harinath + + * decl.cs (DeclSpace.PartialContainer): Move field from ... + * class.cs (TypeContainer.PartialContainer): ... here. + (TypeContainer.AddBasesForPart): New helper. + (MemberBase.ParentContainer): Remove. Use Parent.PartialContainer + instead. + * cs-parser.jay (current_class): Convert to DeclSpace. + (struct_declaration, interface_declaration, class_declaration): + Use AddBasesForPart instead of .Bases directly. + * const.cs, iterators.cs: Update to changes. + +2006-07-28 Raja R Harinath + + * class.cs (TypeContainer.AddMemberType): Rename from + AddToTypeContainer. + (TypeContainer.AddMember): Rename from AddToMemberContainer. + (AddTypeContainer): New. Combine AddClassOrStruct and + AddInterface. + (AddPartial): Update. Add 'is_partial' argument. + * roottypes.cs: Update to changes. + * cs-parser.jay (push_current_class): New helper for handling + current_container and current_class. + (struct_declaration, interface_declaration, class_declaration): + Use it. + +2006-07-26 Raja R Harinath + + * roottypes.cs: Rename from tree.cs. + + Rename RootContext.Tree.Types to RootContext.ToplevelTypes. + * tree.cs (Tree, ITreeDump): Remove types. + * rootcontext.cs (tree, Tree): Remove fields. + (root, ToplevelTypes): New. + * *.cs: Update to rename. + + * tree.cs (Tree.RecordDecl): Remove. + (RootTypes.AddToTypeContainer): Record the toplevel type in its + namespace here. + * class.cs, cs-parser.jay: Remove mention of RecordDecl. + +2006-07-23 Raja R Harinath + + * codegen.cs (EmitContext.Flags): Move InCatch, InFinally, + DoFlowAnalysis and OmitStructFlowAnalysis here. + (ec.With): Rename from WithUnsafe and generalize. + (ec.WithCheckState): Remove. All users can be handled by 'With'. + (ec.WithFlowAnalyis): New. + * ecore.cs, expression.cs, statement.cs: Update. + +2006-07-22 Raja R Harinath + + * statement.cs (Block.ResolveMeta): Simplify slightly. + + * codegen.cs (EmitContext.Flags): New enum. Used to represent the + multiple boolean fields. Convert InUnsafe, constant_check_state, + check_state to flags. + (CheckState, ConstantCheckState): Update. + (InUnsafe): New read-only property. + (FlagsHandle): Rename from CheckStateHandle and convert to handle + arbitrary flags. + (WithUnsafe): New helper similar to WithCheckState. + * statement.cs (Block.ResolveMeta): Use WithUnsafe. + (Unsafe.Resolve, Unsafe.DoEmit): Likewise. + +2006-07-21 Raja R Harinath + + Make comparisons use the same IL irrespective of whether they're + in a 'checked' or 'unchecked' context: one of the issues in #78899 + * codegen.cs (EmitContext.CheckState): Make read-only property. + (EmitContext.ConstantCheckState): Likewise. + (EmitContext.CheckStateHandle, EmitContext.WithCheckState): New + helper that implement a save/restore stack for CheckState + values. This is the only way to change check-state. + * ecore.cs (Expression.ExpressionToArrayArgument): Use WithCheckState. + * expression.cs (CheckedExpr.DoResolve, CheckedExpr.Emit): Likewise. + (CheckedExpr.EmitBranchable): New forwarding method. + (UnCheckedExpr): Likewise. + * statement.cs (Block.ResolveMeta): Use WithCheckState. + (Unchecked.Resolve, Unchecked.DoEmit): Likewise. + (Checked.Resolve, checked.DoEmit): Likewise. + +2006-07-20 Miguel de Icaza + + * anonymous.cs: Cache the resolved anonymous delegate, and return + this so that the ResolveTopBlock is only triggered once, not + twice. + + Currently we trigger ResolvetopBlock twice due to a first pass of + argument check compatibility, and a second pass that does the + actual resolution. + +2006-07-15 Marek Safar + + * annonymous.cs (AnonymousMethod.CreateScopeType): Fixed nested type + modifiers. + * rootcontext.cs (Reset): Add helper_classes. + +2006-07-15 Marek Safar + + A fix for #78860 + * statement.cs (Switch.SimpleSwitchEmit): Handle case null at any position + correctly. + +2006-07-13 Miguel de Icaza + + * statement.cs (Lock): Handle expressions of type + TypeManager.null_type specially. Fixes #78770 + +2006-07-08 Marek Safar + + * expression.cs (Binary.ResolveOperator): Don't crash when null is assigned + to an event. + +2006-07-08 Marek Safar + + * attribute.cs (AttributeTester.GetMethodObsoleteAttribute): Fixed to look + for accessors as well. + * ecore.cs (EventExpr): Add AccessorTable. + +2006-07-01 Marek Safar + + A fix for #78738 + * attribute.cs, class.cs, ecore.cs : Add missing location of related symbol + for CS0122 where appropriate. + * typemanager.cs (IsNestedChildOf): Type can be null in the case of top + level attributes. + (Filter): Assembly can be null in the case of top level attributes. + +2006-06-25 Marek Safar + + A fix for #78690 + + * ecore.cs (Expression.MemberLookupFailed): Don't crash when failed lookup + is done at global level. + +2006-06-24 Marek Safar + + A fix for #77002, Implemented TypeForwarder support. + + * attribute.cs (Attribute.GetArgumentType): Reads type argument. + * expression.cs (TypeOf.TypeArgument): Exposes typeof type. + * typemanager.cs (): Add type_forwarder_attr_type. + +2006-06-24 Marek Safar + + * report.cs: Add CS0469 warning. + +2006-06-21 Martin Baulig + + * codegen.cs (CodeGen.Save): Moved the symbol file generation into + the `try'-block, so we also report CS0016 etc. there. + +2006-06-21 Martin Baulig + + * delegate.cs + (Delegate.VerifyMethod): Allow `params' methods; fixes #78678. + +2006-06-21 Martin Baulig + + * expression.cs (Unary.ResolveOperator): In `Operator.AddressOf', + also report CS1686 for parameters. + +2006-06-21 Martin Baulig + + * statement.cs (GotoCase.Resolve): Report a warning (CS0469) + instead of an error if the value is not implicitly convertible to + the switch types; fixes #77964. + +2006-06-21 Raja R Harinath + + Fix #78673 + * class.cs (FieldBase.ResolveInitializer): Stop resolution if + FieldBuilder is null. + + Fix #78662 + * expression.cs (Binary.CheckShiftArguments): Don't overwrite original + 'left' and 'right' before error-checking. + +2006-06-16 Juraj Skripsky + + * ecore.cs (SimpleName.Error_ObjectRefRequired): Do not truncate the name. + Fixed bug #78601. + (MemberExpr.EmitInstance): Use GetSignatureForError () to get full name. + (FieldExpr.DoResolve): likewise. + (PropertyExpr.InstanceResolve): likewise. + (EventExpr.InstanceResolve): likewise. + +2006-06-04 Marek Safar + + * parameter.cs (Parameter.ApplyAttributeBuilder): More DefaultValue + attribute applicable tests for attribute argument. + +2006-06-02 Raja R Harinath + + Fix #78079 + * expression.cs (Binary.DoNumericPromotions): Remove and rewrite. + (Binary.OverloadResolve_PredefinedIntegral): New. + (Binary.OverloadResolve_PredefinedFloating): New. + (Binary.OverloadResolve_PredefinedString): New. + (Binary.ResolveOperator): Use those instead of DoNumericPromotions. + Follow the standard more closely, and treat numeric promotions in + terms of overload resolution. + (Binary.CheckShiftArguments): Simplify. + +2006-06-01 Raja R Harinath + + * flowanalysis.cs (MyBitVector): Simplify representation. + (MyBitVector.Clone): Avoid allocating BitArray. + (MyBitVector.operator&): Rename from MyBitVector.And and make symmetric. + (MyBitVector.operator|): Likewise, with MyBitVector.Or. + (*): Update. Change all references to MyBitVector.And and + MyBitVector.Or to &= and |=. + +2006-05-29 Raja R Harinath + + Fix cs0231-[34].cs. + * cs-parser.jay (formal_parameter_list): Extend the pattern below + to param arguments too. + +2006-05-26 Miguel de Icaza + + * cs-parser.jay: Catch another parsing form for arglist being + followed by other arguments. Fixes #78313. + +2006-05-24 Raja R Harinath + + * flowanalysis.cs (FlowBranchingToplevel.AddReturnOrigin): Move + checking of out parameters to ... + (FlowBranchingToplevel.Merge): ... here. + (FlowBranchingException.AddBreakOrigin): If 'finally_vector' is + set, propagate the origin upward, and only complain if there was + no other error. + (FlowBranchingException.AddContinueOrigin): Likewise. + (FlowBranchingException.AddReturnOrigin): Likewise. + (FlowBranchingException.AddGotoOrigin): Likewise. + +2006-05-23 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeOrigins): If an origin is + unreachable, skip it. + (FlowBranchingException.Merge): Always propagate jumps, even if + the finally block renders subsequent code unreachable. + +2006-05-18 Raja R Harinath + + Fix #77601 + * statement.cs (Goto.Resolve): Move responsibility for resolving + 'goto' to FlowBranching.AddGotoOrigin. + (Goto.SetResolvedTarget): New. Callback to set the + LabeledStatement that's the target of the goto. + (Goto.DoEmit): Use Leave instead of Br when crossing an + unwind-protect boundary. + * flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from + LookupLabel and adjust to new semantics. + (FlowBranchingToplevel.AddGotoOrigin): Likewise. + (FlowBranchingBlock.AddGotoOrigin): Likewise. Use + Goto.SetResolvedTarget to update target. + (FlowBranchingLabeled.AddGotoOrigin): Likewise. + (FlowBranchingException.AddGotoOrigin): Rewrite to be similar to + AddBreakOrigin & co. Delay propagation until ... + (FlowBranchingException.Merge): ... this. + + * statement.cs (Block.Resolve): Always depend on flow-branching to + determine unreachability. Kill workaround that originally emitted + only one statement after an "unreachable" label (see infloop in + test-515.cs). + + Fix #77869, #76148, #77755, #75255 and a host of other bugs. + This is still "wrong", but anything better would probably need a + multi-pass algorithm. + * flowanalysis.cs (FlowBranchingLabeled): Salt away a copy of the + usage vector. Force current usage vector to be reachable, to + optimistically signify backward jumps. + (FlowBranchingLabeled.LookupLabel): Note if a backward jump is + detected. + (FlowBranchingLabeled.Merge): New. If no backward jump was + detected, return the original salted-away usage vector instead, + updated with appropriate changes. Print unreachable warning if + necessary. + * statement.cs (Block.Resolve): Don't print unreachable warning on + a labeled statement. + +2006-05-17 Gert Driesen + + * driver.cs: Pass filename without path to AssemblyBuilder's + AddResourceFile. Fixes bug #78407. + +2006-05-17 Raja R Harinath + + * statement.cs (LabeledStatement.Resolve): Move merging of origins ... + * flowanalysis.cs (FlowBranchingLabeled): ... here. + (FlowBranching.MergeChild): Overwrite + reachability information from Labeled branchings too. + +2006-05-16 Raja R Harinath + + * statement.cs (Goto.Resolve): Merge jump origins here ... + * flowanalysis.cs (FlowBranching.Label): ... rather than here. + + * flowanalysis.cs (FlowBranching.LookupLabel): Move CS0159 check ... + (FlowBranchingToplevel.LookupLabel): ... here. Add CS1632 check. + (FlowBranchingGoto.LookupLabel): New. Handle back jumps. + (FlowBranchingBlock.LookupLabel): Call LabeledStatement.AddReference + here, ... + * statement.cs (Goto.Resolve): ... not here. + (Goto.Emit): Remove CS1632 check. + +2006-05-14 Marek Safar + + * ecore.cs (Expression.ResolveAsTypeTerminal): Fixed type in the obsolete + error message. + +2006-05-11 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeJumpOrigins): Kill. + (FlowBranchingBlock.Label): Use UsageVector.MergeOrigins. + (FlowBranchingException.Label): Likewise. + + * flowanalysis.cs (MyBitVector.SetAll): New. Sets all bits to the + given value. + (MyBitVector.Or): Use it to avoid losing information (Count). + (FlowBranching.MergeOrigins): Likewise. + + * flowanalysis.cs (UsageVector.IsDirty): Remove. + (UsageVector.Parameters, UsageVector.ParameterVector): Likewise. + (UsageVector.Locals, UsageVector.LocalVector): Likewise. + (UsageVector.ToString): Simplify. + (UsageVector.MergeSiblings): Move here from ... + (FlowBranching.Merge): ... here. + (FlowBranchingToplevel.CheckOutParameters): Take an UsageVector, + not a MyBitVector. + +2006-05-10 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeOrigins): Simplify, now that a + null bitvector is treated as all-true. + + * flowanalysis.cs (MyBitVector.And, MyBitVector.Or): Make lazier. + (MyBitVector): Rationalize invariants. 'vector != null' implies + that we have our own copy of the bitvector. Otherwise, + 'InheritsFrom == null' implies all inherited bits are true. + +2006-05-09 Marek Safar + + * statement.cs (LocalInfo): Add IsConstant. + (LocalInfo.DeclareLocal): Moved from EmitMeta and changed to don't emit + local variable for constants. + +2006-05-09 Raja R Harinath + + * flowanalysis.cs (MyBitVector.Empty): New. + (MyBitVector): Don't allow InheritedFrom to be null. + (MyBitVector.And, MyBitVector.Or): Treat 'null' as all-ones. + (UsageVector, FlowBranching): Update to changes. + + * flowanalysis.cs (FlowBranching.InTryWithCatch): Don't terminate + recursion. The 'Parent == null' condition isn't sufficient for + anonymous methods. + (FlowBranching.AddBreakOrigin): Likewise. + (FlowBranching.AddContinueOrigin): Likewise. + (FlowBranching.AddReturnOrigin): Likewise. + (FlowBranching.StealFinallyClauses): Likewise. + (FlowBranching.MergeTopBlock): Move to FlowBranchingToplevel. + (FlowBranching.CheckOutParameters): Likewise. + (FlowBranchingToplevel): Terminate all the above recursions here. + (FlowBranchingToplevel.End): Rename from MergeTopBlock. + * codegen.cs (EmitContext.ResolveTopBlock): Update to changes. + + * flowanalysis.cs (BranchingType.Toplevel): New. Represents a + toplevel block. + (FlowBranchingToplevel): New. Empty for now. + (FlowBranching.MergeTopBlock): Update. + * codegen.cs (EmitContext.ResolveTopBlock): Create a Toplevel + branching for the anonymous delegate. + (EmitContext.StartFlowBranching): Add ToplevelBlock variant. + + * flowanalysis.cs (UsageVector.MergeOrigins): Reorganize. + (UsageVector.MergeJumpOrigins): Don't ignore current reachability + information at the start of the merge. Reorganize. + +2006-05-07 Marek Safar + + * class.cs (MethodData.Define): Method cannot implement interface accessor. + +2006-05-07 Marek Safar + + * expression.cs (QualifiedAliasMember.ResolveAsTypeStep): Pass location + to newly introduced ctor. + + * namespace.cs (Namespace.Error_NamespaceDoesNotExist): Moved an error + message to one place. + (GlobalRootNamespace.Error_NamespaceDoesNotExist): Custom message for + global namespace. + +2006-05-07 Marek Safar + + * const.cs (Const.Error_ExpressionMustBeConstant): Better error message. + + * ecore.cs (Expression.ResolveAsConstant): Updated. + + * statement.cs (ResolveMeta): Updated. + +2006-05-06 Marek Safar + + * cs-parser.jay: __arglist cannot be used in initializer. + +2006-05-06 Marek Safar + + A fix for #77879 + * namespace.cs (LocalAliasEntry.DoResolve): Don't allow to access nested + private types. + +2006-05-05 Raja R Harinath + + * statement.cs (EmptyStatement.ResolveUnreachable): Override. + (LabeledStatement): Add 'name' parameter. + (LabeledStatement.Name, LabeledStatement.JumpOrigins): New. + (Block.AddLabel): Update to changes. + * cs-parser.jay (labeled_statement): Likewise. + + * flowanalysis.cs (BranchingType.Labeled): New. + (UsageVector.MergeOrigins): Remove unused 'branching' argument. + (FlowBranchingLabeled): New. Does nothing for now, but will + eventually handle 'goto' flows. + * codegen.cs (StartFlowBranching): Add new LabeledStatement variant. + * statement.cs (LabeledStatement.Resolve): Create a FlowBranching + that's terminated ... + (Block.Resolve): ... here. + + * flowanalysis.cs (UsageVector.MergeFinally): Remove. + (UsageVector.MergeFinallyOrigins): Likewise. + (FlowBranching.InTryOrCatch): Likewise. + (FlowBranching.AddFinallyVector): Likewise. + (FlowBranchingException): Update to changes. + + Fix #78290 + * statement.cs (Return.Resolve): Move error checking to ... + * flowbranching.cs (FlowBranching.AddReturnOrigin): ... this. + (FlowBranchingException): Handle return origins like break and + continue origins. + (FlowBranching.UsageVector.CheckOutParameters): Remove. + +2006-05-04 Marek Safar + + A fix for #76122 + * class.cs (TypeContainer.FindMembers): Includes event method in the methods + filter. + +2006-05-04 Marek Safar + + A fix for #77543 + * class.cs (MethodData.Define): Do public accessor check only when method + implements an interface. + +2006-05-04 Raja R Harinath + + Remove special handling of 'break' + * flowanalysis.cs (Reachability): Remove all mention of 'breaks'. + (Reachability.Meet): Simplify. Remove 'do_breaks' argument. + (UsageVector.Break): Remove. + (FlowBranching.Merge): Use 'Reachable.IsUnreachable' to determine + reachability. + (FlowBranchingBreakable.Merge): Don't ResetBreaks. + + * statement.cs (Break.Resolve): Call UsageVector.Goto (), not + UsageVector.Breaks (). Don't set NeedsReturnLabel. + +2006-05-03 Marek Safar + + A fix for #75726 + * pending.cs (PendingImplementation.BaseImplements): A found member cannot + be the interface member. + +2006-05-03 Marek Safar + + A fix for #60069 + * constant.cs (LongConstant.EmitLong): Fixed to catch also negative values + for emitting small (int) values. + +2006-05-03 Raja R Harinath + + Fix #59427 + * flowanalysis.cs (FlowBranchingException.Merge): Ensure + control-flow passes through the 'finally' after merging-in all the + control-flows from 'try' and the 'catch' clauses. + + * flowanalysis.cs (FlowBranching.IsLoop): Remove. + (FlowBranching.IsTryOrCatch): Remove 'is_return' parameter. It's + always true at the only non-recursive entry point. + (FlowBranching.CreateBranching) [BranchingType.Loop]: Return a + FlowBranchingBreakable. + (FlowBranchingLoop): Remove. + * statement.cs (Return.DoResolve): Update to changes. + + Fix #76471, #76665 + * flowanalysis.cs (FlowBranching.BranchingType.Embedded): New. + (FlowBranching.CreateBranching): Handle it: create a + FlowBranchingContinuable. + (FlowBranching.BreakCrossesExceptionBoundary): Remove. + (FlowBranching.AddContinueOrigin): Similar to AddBreakOrigin, + except that it handles the 'continue' command. + (FlowBranching.UsageVector.MergeOrigins): Rename from + MergeBreakOrigins. + (FlowBranchingContinuable): Similar to FlowBranchingBreakable, + except that it overrides AddContinueOrigin. + (FlowBranchingException): Override AddContinueOrigin, similar to + AddBreakOrigin. + * statement.cs (While.Resolve, Foreach.ArrayForeach.Resolve): + Create a new branching around the embedded statement. + (Do.Resolve, For.Resolve): Likewise. Do reachability analysis for + control flow after the embedded statement. + (Continue.Resolve): Move all error checking to AddContinueOrigin. + + * flowanalysis.cs (FlowBranching.IsSwitch): Remove. + (FlowBranching.CreateBranching) [BranchingType.Switch]: Create a + FlowBranchingBreakable. + (FlowBranchingSwitch): Remove. + + Fix test-503.cs + * statement.cs (Break.Resolve): Simplify. Move responsibility for + error reporting to ... + * flowanalysis.cs (FlowBranching.AddBreakOrigin) ... this. + Rename from 'AddBreakVector'. Add new location argument. Return + a bool indicating whether the 'break' crosses an unwind-protect. + (FlowBranchingException.AddBreakOrigin): Add. + (FlowBranchingException.Merge): Propagate 'break's to surrounding + flowbranching after updating with the effects of the 'finally' + clause. + (FlowBranchingBreakable): New common base class for + FlowBranchingLoop and FlowBranchingSwitch. + + * statement.cs (Foreach.ArrayForeach.Resolve): Set barrier after + embedded statement. + (Foreach.CollectionForeach.Resolve): Remove extraneous flowbranching. + +2006-05-02 Raja R Harinath + + * statement.cs (Do.Resolve): If the loop is infinite, set the + barrier. + (While.Resolve, For.Resolve): Set a barrier after the embedded + statement. There's no direct control flow that goes from the end + of the embedded statement to the end of the loop. + * flowanalysis.cs (FlowBranching.Infinite): Remove. + (FlowBranchingLoop.Merge): Don't look at 'Infinite'. The changes + above ensure that the reachability is correctly computed. + + * flowanalysis.cs (Reachability.ResetBarrier): Remove. + (UsageVector.MergeBreakOrigins): If the current path is + unreachable, treat it as if all parameters/locals are initialized. + (FlowBranchingLoop.Merge): Don't clear any barriers. Handle + infinite loops before merging-in break origins. + + * flowanalysis.cs (Reachability.Meet): Simplify code handling 'returns'. + (Reachability.Reachable): Split part into ... + (Reachability.Unreachable): ... this. Simplify. + (Reachability.IsUnreachable): Use 'Unreachable' instead. + + * flowanalysis.cs (Reachability.SetReturnsSometimes): Remove. + (Reachability.SetThrowsSometimes): Likewise. + (FlowBranchingBlock.MergeTopBlock): Don't compare against + TriState.Always, use corresponding property. + * statement.cs (Lock.Resolve, Try.Resolve, Using.Resolve): Likewise. + (Block.Resolve): Likewise. Remove some redundant checks. + +2006-05-02 Raja R Harinath + + * flowanalysis.cs (UsageVector.Throw): Set barrier too. + (Reachability.Meet): Don't bother checking AlwaysThrows -- + barrier is always set. + (FlowBranchingBlock.Merge): Likewise. + +2006-05-01 Raja R Harinath + + * codegen.cs (EmitContext.ResolveTopBlock): Remove redundant + checks for unreachable. + +2006-05-01 Marek Safar + + A fix for #77980 + * flowanalysis.cs (UsageVector.IsAssigned): Add flag to ignore short path. + + * statement.cs (Block.UsageWarning): Uses newly introduced flag to detect + whether field is really assigned. + +2006-04-30 Raja R Harinath + + * flowanalysis.cs (Reachability): Make 4-argument constructor + private. + (Reachability.Meet): Rename from 'And'. Remove static variant. + (Reachability.Always): Rename from the highly misleading + 'Reachability.Never'. + (FlowBranching.Merge): Update to changes. Mark an impossible + situation with a 'throw'. + (*): Update to changes. + +2006-04-29 Raja R Harinath + + * flowanalysis.cs (TriState): Rename from FlowBranching.FlowReturns. + Remove 'Undefined'. + (FlowBranching.TriState_Meet): Rename from AndFlowReturns. Simplify. + (FlowBranching.TriState_Max): Rename from OrFlowReturns. Simplify. + (*): Update to changes. + * statement.cs: Update to changes. + +2006-04-28 Marek Safar + + A fix for #78049 + *class.cs (Method.FindOutBaseMethod): Base method cannot be property method. + +2006-04-28 Raja R Harinath + + * flowanalysis.cs (FlowBranching.MergeTopBlock): Don't create a + dummy UsageVector. + + * flowanalysis.cs (UsageVector.MergeChild): Change FlowBranching + argument to two arguments: an usage-vector and a bool. Move call + to FlowBranching.Merge () ... + (FlowBranching.MergeChild, FlowBranching.MergeTopBlock): ... here. + + * flowanalysis.cs (UsageVector.MergeChild): Move special-case + handling of loop and switch reachability to ... + (FlowBranchingLoop.Merge, FlowBranchingSwitch.Merge): ... these. + +2006-04-27 Raja R Harinath + + * flowanalysis.cs (FlowBranching.InLoop): Move special-case + handling to FlowBranchingLoop.InLoop. + (FlowBranching.InSwitch): Likewise, to FlowBranchingSwitch. + +2006-04-26 Marek Safar + + A fix for #78115 + * anonymous.cs (AnonymousMethod.DoResolve): Moved the check whether + anonymous method is allowed from AnonymousContainer here. + + * attribute.cs, codegen.cs (EmitContext): Add IsAnonymousMethodAllowed. + +2006-04-24 Raja R Harinath + + Fix #78156 + * flowanalysis.cs (MyBitVector.Or): Add null check on argument. + +2006-04-23 Marek Safar + + A fix for #49011. + * constant.cs (FloatConstant.Reduce): Add range checking for checked context. + (DoubleConstant.Reduce): Ditto. + +2006-04-23 Raja R Harinath + + * expression.cs (LocalVariableReference.DoResolveBase): Simplify. + Remove 'lvalue_right_side' argument. Move parts to ... + (LocalVariableReference.ResolveLocalInfo, LocalVariable.DoResolve) + (LocalVariable.DoResolveLValue): ... these. + +2006-04-21 Raja R Harinath + + Fix cs1655.cs + * codegen.cs (EmitContext.InRefOutArgumentResolving): Remove. + * expression.cs (EmptyExpression.LValueMemberOutAccess): New. + (LocalVariableReference.DoResolveBase): Use it to implement new + CS1655 check. + (IndexerAccess.DoResolveLValue): Handle LValueMemberOutAccess. + (Argument.Resolve): Simplify. Move CS1510 check ... + * ecore.cs (Expression.ResolveLValue): ... here. + (UnboxCast.DoResolveLValue): Handle LValueMemberOutAccess. + (PropertyExpr.DoResolveLValue): Likewise. + (FieldExpr.Report_AssignToReadonly): Likewise. + (FieldExpr.DoResolve): Add 'out_access' argument. Use + LValueMemberAccess or LValueMemberOutAccess on instance depending + on it. + (FieldExpr.DoResolveLValue): Pass 'out_access' argument to + DoResolve as appropriate. + +2006-04-20 Raja R Harinath + + Fix #75800 + * expression.cs (Invocation.VerifyArgumentsCompat): Don't try + implicit conversions on 'out' and 'ref' arguments. + + * expression.cs (Invocation.VerifyArgumentsCompat): Reorganize to + improve clarity. Remove dead code. + + Fix #66031 + * statement.cs (Block.UsageWarning): Allow VariableInfo to be null. + (Catch.Resolve): Resolve VarBlock if it exists. + +2006-04-19 Miguel de Icaza + + * statement.cs (Foreach.EmitFinally): Do not emit the enumerator + twice, this was some residual code, the enumerator was emitted + properly in the two branche of if later. + +2006-04-19 Raja R Harinath + + * expression.cs (Cast.ResolveLValue): Remove. The result of a + cast is never an lvalue. + (Cast.DoResolve, Cast.ResolveRest): Combine. + (Argument.Emit): Simplify slightly. Move 'Expr is + IMemoryLocation' check ... + (Argument.Resolve): ... here. + (Argument.Error_LValueRequired): Remove. Inline into only user. + + Simplifications. Fix cs0191-2.cs + * ecore.cs (FieldExpr.DoResolve): Move handling of CS0192, CS0198, + CS1649 and CS1651 to ... + (FieldExpr.Report_AssignToReadonly): ... this. Simplify by moving + the actual selection of the error code and message to a lookup + table. Add a dummy return value to simplify callsites. + (FieldExpr.ResolveLValue): Don't allow a constructor to write to + readonly fields of other instances of the same type. Move CS0197 + warning from ... + * expression.cs (Argument.Resolve): ... here. Simplify code. + Ensure that ec.InRefOutArgumentResolving is only set during LValue + resolution of an out or ref argument. The code simplification + above uses this invariant. + +2006-04-18 Raja R Harinath + + Possibly fix #77752. Fix cs1690-[4-7].cs. + * ecore.cs (Expression.CheckMarshalByRefAccess): Renamed from + CheckMarshallByRefAccess. Drop parameter. + (FieldExpr.CheckMarshalByRefAccess): Update. Change CS1690 to a + warning. + (FieldExpr.DoResolve): Call CheckMarshalByRefAccess on + InstanceExpression. + * report.cs (AllWarnings): Add CS1690. + * expression.cs (Argument.Resolve): Use EmptyExpression.OutAccess + for ref access too. + (LocalVariableReference.DoResolveBase): Update. + +2006-04-09 Marek Safar + + * class.cs (MethodOrOperator): Moved common parts from method class. + detect obsolete attributes. + (Method.Define): Simplified as it reuses code from base. + (Constructor.ValidAttributeTargets): Fixed issue found during + refactoring. + (Destructor.ValidAttributeTargets): Fixed issue found during + refactoring. + (Operator): Finished refactoring set off by #78020. Operator class is now + ordinary method class. + + * anonymous.cs: Updated. + + * decl.cs (DeclSpace): Add IsGeneric + +2006-04-09 Marek Safar + + * class.cs (Constructor.Emit): Don't emit the attributes twice. + +2006-04-09 Marek Safar + + * class.cs (Operator.Emit): Extracted code from MethodData to correctly + detect obsolete attributes. + (Method.CreateEmitContext): Moved to MethodOrOperator. + +2006-04-09 Marek Safar + + A fix for #78048. + * class.cs (TypeContainer.MemberCoreArrayList.DefineContainerMembers): Throw + customized exception to make crash detection easier. + (MethodOrOperator): Started to work on new base class for methods and + operators. + (Method): Derives from MethodOrOperator. + (Constructor.Emit): Emits its own attributes. + (AbstractPropertyEventMethod.Emit): Ditto. + (Operator): Derives from MethodOrOperator, will refactor fully in extra + patch. + (Operator.Emit): It's temporary more tricky than should be. + + * doc.cs (GetMethodDocCommentName): Updated after operator changes. + + * report.cs (InternalErrorException): Add ctor with inner exception. + +2006-04-08 Marek Safar + + A fix for #76744. + * ecore.cs (SimpleName.ResolveAsTypeStep): Report better error when type is + only not visible. + +2006-04-07 Marek Safar + + A fix for #77916. + * expression.cs (ArrayCreation.GetAttributableValue): Creates correctly typed + array. + +2006-04-06 Marek Safar + + * class.cs (Class.ApplyAttributeBuilder): Report an error when ComImport + attribute is present and Guid not. + (Interface.ApplyAttributeBuilder): Ditto. + + * attribute.cs: Add error message. + +2006-04-06 Marek Safar + + A fix for #78020. + + * attribute.cs (Attribute.AttachTo): The attribute can have multiple + sources (it's composite) so hold them in extra array as they are used in + Emit phase only. It worked in the previous versions by mistake. + (Attribute.Emit): Emit attribute for more owners when exist. + + * codegen.cs, class.cs: Updated to don't re-attach attribute twice as now + it has now different behaviour. + +2006-04-04 Marek Safar + + * constant.cs (Constant.IsDefaultInitializer): New method. + + * class.cs: Updated. + + * expression.cs (ArrayCreation.CheckIndices): Add an optimization to don't + re-initialize default values. It saves KBs almost for every assembly. + Thanks Zoltan for the idea. + (ArrayCreation.ResolveInitializers): Renamed from ValidateInitializers. + (ArrayCreation.DoResolve): Resolve only once. + (ArrayCreation.Emit): Emit static initializer only when it is faster. + (ArrayCreation.GetAttributableValue): Cope with optimized values. + +2006-04-03 Zoltan Varga + + * report.cs (Warning, Error): Add 0-, 1-, and 2- argument specializations. + From #77961. + +2006-04-01 Marek Safar + + * assign.cs (Assign.DoResolve): Assignment to same variable can occur + in an embedded statement too. + +2006-04-01 Raja R Harinath + + Fix #77958 + * statement.cs (Switch.EmitObjectInteger) [ulong]: Remove bad cast. + +2006-04-01 Marek Safar + + A fix for #77966. + + * class.cs (TypeContainer.AddPartial): Don't report an error when modifier + was not specified. + + * modifiers.cs: Add DEFAULT_ACCESS_MODIFER. + +2006-03-31 Marek Safar + + * assign.cs (LocalTemporary): Don't require ILGenerator in the resolve + phase. + + * anonymous.cs, assign.cs, ecore.cs, expression.cs: Updated after + LocalTemporary change. + + * class.cs (ClassOrStruct.DefineDefaultConstructor): Moved from + TypeContainer. + (ClassOrStruct.DefineFieldInitializers): Implemented static field + initializers optimization. + (ClassOrStruct.TypeAttr): Moved from modifiers. + (Constructor.CheckBase): Don't crash when static ctor has parameters. + (FieldBase.ResolveInitializer): Resolves initializer. + (FieldBase.HasDefaultInitializer): New property. + + * cs-parser.jay: Removed message. + + * expression.cs (CompilerGeneratedThis): New specialization. + + * modifiers.cs (TypeAttr): Moved to ClassOrStruct.TypeAttr + +2006-03-28 Marek Safar + + * cs-parser.jay, cs-tokenizer.cs: On demand Stack allocation. + +2006-03-27 Marek Safar + + * ecore.cs (Expression.ResolveAsConstant): Clean up, enum constants should + be now EnumConstants only. + +2006-03-27 Marek Safar + + * attribute.cs, driver.cs: Reset more caches. + +2006-03-26 Marek Safar + + * cs-tokenizer.cs (adjust_real): Uses float.Parse for float literals. + +2006-03-26 Marek Safar + + * constant.cs (Constant.Reduce): Replaced EmitContext with single bool + for easier reuse. Updated all overrides. + (IntegralConstant): New base class for all integral constants. + (IntegralConstant.Error_ValueCannotBeConverted): When assigned value if out + of the constant range, report custom error. + (UIntConstant.Reduce): Fixed uint conversion. + + * ecore.cs, literal.cs: Reduce updates. + +2006-03-26 Marek Safar + + A fix for #75813. + + * class.cs (Constructor.Define): Removed extra if for default ctors. + A patch from Atsushi Enomoto. + +2006-03-26 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Conversion was moved to + GetAttributableValue. + + * constant.cs (Constant.GetAttributableValue): Does implicit conversion + when required. + + * convert.cs (ImplicitConversionRequired): Error message moved to + DoubleLiteral. + + * ecore.cs (Expression.GetAttributableValue): Add type parameter for + automatic implicit conversion of an output value. + (EnumConstant.GetAttributableValue): Don't reduce the enum constants. + + * expression.cs (ArrayCreation.GetAttributableValue): Add element type + conversion. + (TypeOf.GetAttributableValue): Add extra handling for object type. + + * literal.cs (DoubleLiteral.Error_ValueCannotBeConverted): Doubles can have + special error message. + +2006-03-25 Marek Safar + + * class.cs (Constructor.Emit): Don't crash when struct ctor is + InternalCall. + (Constructor.ApplyAttributeBuilder): Transform MethodImplAttribute to be + compatible with MS runtime. + +2006-03-23 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Check for an invalid + attribute arguments here. + + * class.cs (Indexer.Define): The check was moved to attribute class. + +2006-03-22 Marek Safar + + * assign.cs, class.cs, codegen.cs, convert.cs, decl.cs, ecore.cs, + expression.cs, typemanager.cs: Minor changes from gmcs to make merging + easier. + +2006-03-22 Raja R Harinath + + Support ParameterDefaultValueAttribute in gmcs. Also applied to + mcs to keep code differences small. + * attribute.cs (Attribute.GetParameterDefaultValue): New. + * typemanager.cs (parameter_default_value_attribute_type): New. + * parameter.cs (Parameter.ApplyAttributeBuilder): Use them. Add + CS1908 check. + +2006-03-21 Marek Safar + + * expression.cs (StringConcat.Append): Reverted back to no warning state. + +2006-03-21 Marek Safar + + * const.cs (Error_ConstantCanBeInitializedWithNullOnly): Share a message. + + * statement.cs (Block.ResolveMeta): Look for wrong object constants in + the blocks too. + +2006-03-21 Atsushi Enomoto + + * doc-bootstrap.cs : fix build. + +2006-03-20 Marek Safar + + * expression.cs (StringConcat.Append): Issue a warning when empty string + is going to append. + +2006-03-20 Marek Safar + + * assign.cs (CompoundAssign.ResolveSource): Removed. + + * attribute.cs (ResolvePossibleAttributeType): Updated after MemberAccess + clean up. + + * class.cs (TypeContainer.FindMethods): Removed. + (TypeContainer.CheckMemberUsage): Made static. + + * codegen.cs (GetAssemblyName): Uses Length for empty string test. + + * constant.cs (CheckRange): Removed unused type argument. + (CheckUnsigned): Removed unused type argument. + + * cs-parser.jay: Updated after MemberAccess clean up. + Uses Length for empty string test. + + * cs-tokenizer.cs: Uses Length for empty string test. + (IsCastToken): Made static. + (is_hex): Made static. + (real_type_suffix): Made static. + + * decl.cs (SetupCache): Made static. + (OnGenerateDocComment): Removed unused ds argument. + + * delegate.cs (VerifyDelegate): Removed unused argument. + + * doc.cs: Uses Length for empty string test. + + * driver.cs: Uses Length for empty string test. + + * enum.cs (IsValidEnumType): Made static + + * expression.cs (EnumLiftUp): Removed unused argument. + (ResolveMethodGroup): Ditto. + (BetterConversion): Ditto. + (GetVarargsTypes): Ditto. + (UpdateIndices): Ditto. + (ValidateInitializers): Ditto. + (MemberAccess.ctor): Ditto. + (GetIndexersForType): Ditto. + + * flowanalysis.cs: (MergeFinally): Removed unused argument. + + * iterators.cs: Updated after MemberAccess clean up. + + * location.cs: Uses Length for empty string test. + + * namespace.cs: Uses Length for empty string test. + + * report.cs (CheckWarningCode): Made static. + + * statement.cs (LabeledStatement): Removed unused argument. + + * typemanager.cs (FilterNone): Removed. + +2006-03-18 Marek Safar + + * codegen.cs (EmitContext.TestObsoleteMethodUsage): Removed as it become + obsolete. + + * class.cs: Updated. + +2006-03-18 Marek Safar + + * cs-parser.jay.cs: __arglist is not allowed for delegates. + +2006-03-18 Marek Safar + + A fix for #77822. + + * expression.cs (VerifyArgumentsCompat): Reverted to double error + reporting, it's more tricky than I thought. + +2006-03-18 Marek Safar + + A fix for #77816. + + * anonymous.cs.cs (AnonymousMethod): Add host to allow access to + host container. + (AnonymousMethod.ImplicitStandardConversionExists): New method. + (AnonymousMethod.Compatible): Moved parameter resolving to DoResolve. + Add more error reporting; Fixed issue with params. + + * convert.cs (ImplicitStandardConversionExists): Returned conversion check. + + * cs-parser.jay: AnonymousMethod requires host container. + + * delegate.cs (NewDelegate.DoResolve): Updated after Compatible changes. + +2006-03-18 Raja R Harinath + + * class.cs: Change 'TypeContainer ds' constructor argument to + 'DeclSpace parent'. Some classes were missed below due to + different naming convention. + + * class.cs (MemberCore.Parent): Delete. This makes the + ParentContainer changes below enforceable by the compiler. + + Treat pointers to enclosing declaration space as 'DeclSpace', not + 'TypeContainer'. + * class.cs, const.cs, delegate.cs, enum.cs, iterator.cs: Change + 'TypeContainer parent' constructor argument to 'DeclSpace parent'. + + * statement.cs (LocalInfo..ctor): Use DeclSpace argument instead + of TypeContainer. + (Block.AddThisVariable): Likewise. + * class.cs (MethodData.Define, MethodData.Emit): Likewise. + (AbstractPropertyEventMethod.Emit): Likewise. + (AbstractPropertyEventMethod.EmitMethod): Likewise. + (GetMethod.Define, SetMethod.Define): Likewise. + (PropertyMethod.Define, DelegateMethod.Define): Likewise. + (DelegateMethod.EmitMethod): Likewise. + + Fix regression test-partial-13.cs. + Rationalize use of PartialContainer. Ensure that the partial + class semantics can be tied to type-correctness, i.e., any + violation will cause a compile error. + * class.cs, const.cs: Access all fields that belong to class + TypeContainer via ParentContainer. Arguments of EmitContexts and + Resolve()-like functions still use 'Parent'. + + * class.cs (SourceMethod): Use DeclSpace, not TypeContainer. + (*.CreateEmitContext): Change TypeContainer argument to DeclSpace. + (PropertyMethod.CheckModifiers): Remove unused argument. + * codegen.cs (EmitContext..ctor): Change TypeContainer argument to + DeclSpace. + +2006-03-17 Raja R Harinath + + Make semantics of PartialContainer simpler. + * decl.cs (DeclSpace.IsPartial): Remove. + * class.cs (TypeContainer.IsPartial): Likewise. + (TypeContainer..ctor): Set PartialContainer to point to self. + (TypeContainer.GetClsCompliantAttributeValue): Don't use IsPartial. + (TypeContainer.FindNestedType): Likewise. + (MemberCore.ParentContainer): Simplify. Remove deprecation. + +2006-03-17 Marek Safar + + * typemanager.cs.cs (GetInterfaces): Don't recreate 0-sized arrays. + +2006-03-15 Marek Safar + + * class.cs (FieldMember.Emit): ParentContainer is real parent for partial + classes. + +2006-03-15 Marek Safar + + * class.cs (Operator.Define): An error for base conversion was not + reported correctly. + +2006-03-14 Atsushi Enomoto + + * iterator.cs : yield break is allowed in try statement which has + catch clauses. Fixed bug #77767. + +2006-03-13 Marek Safar + + A fix for #77593, #77574. + + * class.cs (MethodCore.CheckBase): Another if for operator. + +2006-03-09 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Don't crash when parameters + were not resolved + + * delegate.cs (Delegate.GetInvokeMethod): Use emitcontext free MemberLookup. + (DelegateCreation.ImplicitStandardConversionExists): New method for just + conversion test. + + *ecore.cs (Expression.MemberLookup): Don't ask for emitcontext when it's + not needed. + + * assign.cs, constant.cs, convert.cs, delegate.cs, expression.cs: + Updated after another emitcontext usage was clean up. It should help us to + synchronize with gmcs easier. + +2006-03-04 Marek Safar + + A fix for #77353. + + * class.cs (SetMethod.DefineParameters): Uses new parameters type ctor. + (Event.Define): ditto + (SetIndexerMethod.DefineParameters): Uses Parameters.MergeGenerated. + + * delegate.cs (Delegate.Define): Uses Parameters.MergeGenerated. + Removed redundant code and set NewSlot for Invoke method too. + + * parameter.cs (Parameters.ctor): Add custom, type ctor. + (Parameters.MergeGenerated): New method. Use this method when you merge + compiler generated argument with user arguments. + +2006-03-03 Marek Safar + + * attribute.cs (ResolveAsTypeTerminal): Removed. + + * ecore.cs (Expression.ResolveAsTypeTerminal): Make virtual to allow + specialization for predefined types; 30% speed up. + Finally placed obsolete check to right place. + (Expression.ResolveType): Removed. + + * enum.cs, expression.cs, parameter.cs, statement.cs, typemanager.cs: + Updated after ResolveType was removed. + + * expression.cs (Cast.ctor): Check void cast. + (Binary.ResolveAsTypeTerminal): Is never type. + (Conditional.ResolveAsTypeTerminal): Is never type. + + * rootcontext.cs (ResolveCore): Set base type to simplify some code later. + +2006-03-01 Raja R Harinath + + Fix #77679. + * expression.cs (ParameterReference.DoResolveBase): Change return + type to bool. + (ParameterReference.DoResolve, ParameterReference.DoResolveLValue): + Update. + + Fix #77628. + * ecore.cs (PropertyExpr.InstanceResolve): Fix CS1540 check. + + Fix #77642. + * typemanager.cs (GetFullNameSignature): Don't nullref on + protected accessors. + +2006-02-27 Marek Safar + + * attribute.cs (Attribute.PosArguments, Attribute.NamedArguments): Use + these two separated members to simplify the code. + (Attribute.Resolve): Refactored to use new fields and methods. + (Attribute.ResolveConstructor): Extracted from ResolveArguments and + implemented obsolete attribute checking. + (Attribute.ResolveNamedArguments): Extracted from ResolveArguments and + implemented obsolete checking again. It look line never ending quest ;-) + (GlobalAttribute.ResolveConstructor): Need to override as the rest. + + * cfold.cs (BinaryFold): TryReduce throws an exception to indicate error. + + * constanct.cs (TryReduce): Throws OverflowException to indicate error. + + *class.cs (Property.Define): Add RegisterProperty call. + + * cs-parser.jay: Replaced ArrayList with fixed array for attribute + argument groups (only 2). + + * ecore.cs (Expression.GetAttributableValue): New virtual method used for + encoding expression to arguments. + (Expression.ExprClassToResolveFlags): Just turned to property. + + * expression.cs (ArrayCreation.ValidateInitializers): Slightly optimized. + (ArrayCreation.GetAttributableValue): Renamed from EncodeAsAttribute and + optimized as well as implemented support for zero-length attributes. + + * typemanager.cs (TypeManager.RegisterProperty, TypeManager.GetProperty): + Add caching of PropertyInfo's. + +2006-02-25 Marek Safar + + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Don't report + error multiple times. + +2006-02-25 Marek Safar + + New partial class implementation. + A fix for #77027, #77029, #77403 + + * attribute.cs (Attributable): Made attributes protected. + + * class.cs (TypeContainer): Add PartialContainer and partial_parts as + the replacements of ClassPart and PartialContainer. + (TypeContainer.AddClassOrStruct): Call RecordDecl here. + (TypeContainer.AddInterface): Ditto. + (TypeContainer.AddPartial): The main method for partial classes. It checks + for errors and merges ModFlags and attributes. At the end class is added to + partial_parts list. + (TYpeContainer.DefineDefaultConstructor): Checks whether default ctor is + required here. + (TypeContainer.GetClsCompliantAttributeValue): Cope with partial class too. + (TypeContainer.GetNormalPartialBases): Resolves base classes and interfaces + from the rest of partial classes. + (TypeContainer.GetClassBases): Simplified. + (TypeContainer.DefineTypeBuilder): New method, mostly extracted from + DefineType. + (TypeContainer.DefineDefaultConstructor): Is used by derived classes. + (TypeContainer.HasExplicitLayout): Uses Flags now. + (PartialContainer): Removed. + (ClassOrStruct.AddToContainer): Moved enclosing member name check here. + (StaticClass): Was merged with Class. + (Class.GetClassBases): class and static class bases are verified here. + (Class.TypeAttr): Added static attributes when class is static. + (Struct.RegisterFieldForInitialization): Moved from TypeContainer. + (MemberBase): In some cases we need to call parent container for partial + class. It should be eliminated but it's not easy now. + + * cs-parser.jay: Replaced all PartialContainer with AddPartial. + + * decls.cs (MemberCore.DocComment): Introduced new property as is used by + partial classed to accumulate class comments. + (MemberCore.GetClsCompliantAttributeValue): Moved from TypeContainer. + + * doc.cs (GenerateTypeDocComment): Partial classes clean up. + + * driver.cs (MainDriver): Tree.GetDecl was removed. + + * modifiers.cs (Modifiers): Add partial modifier. + + * tree.cs (Tree.decl): Removed. + (RootTypes): Started to use this class more often for root types + specializations. + +2006-02-22 Marek Safar + + A fix for #77615 + + * attribute.cs (AttributeTester.GetCoClassAttribute): Don't crash when + external interface does not have an attribute. + +2006-02-22 Marek Safar + + Another prerequisites for new partial classs implementation. + + * attribute.cs (Attribute.Equal): Implemented. + (Attribute.Emit): Changed as attributes can be applied more than twice. + (Attributes.Emit): Check for duplicate attributes here. + + * class.cs, decl.cs, delegate.cs, doc.cs, enum.cs: Don't pass DeclSpace + as a parameter, clean-up. + +2006-02-11 Marek Safar + + A fix for #77485 + + * class.cs (TypeContainer.DefineType): Cannot use ResolveType because it + contains obsolete attribute check which can in some cases look for base + type of current class which is not initialized yet. + (TypeContainer.BaseType): Replacement of ptype. + + * decl.cs (MemberCore.CheckObsoleteType): Reuse existing code. + +2006-02-11 Marek Safar + + First of prerequisites for new partial classs implemention. + + * attribute.cs (Attributable): Extended by ResolveContext; + Attributes finally have correct context for resolving in all cases. + (AttachTo): Attribute owner is assigned here. + + * codegen.cs (IResolveContext): Introduce new interface to hold + all information needed in resolving phase. + (EmitContext): Implements IResolveContext; more clean-up needed here. + + * decl.cs (MemberCore): Implemented IResolveContext. + + * anonymous.cs, attribute.cs, class.cs, codegen.cs, const.cs, + decl.cs, ecore.cs, enum.cs, expression.cs, iterators.cs, namespace.cs, + parameter.cs, statement.cs, tree.cs, typemanager.cs: + Refactored to use new IResolveContext instead of EmitContext; cleanup + +2006-02-06 Miguel de Icaza + + * codegen.cs (EmitScopeInitFromBlock): check here the + capture_context, there is no need to make two calls to the + EmitContext. + + * anonymous.cs: Add some debugging messages that might help me + track other instances of this problem in the future (the + regression of test 467). + + * cs-parser.jay: track the variable block, as we need to initalize + any captured variables declared in this block for the "catch" + portion of the "Try" statement. + + * statement.cs (Try.Emit): If the "Catch" has a VarBlock, emit any + scope initialization for captured variables. + + Also, move the emit for the variables after the block location has + been marked. + +2006-02-06 Marek Safar + + * ecore.cs (PropertyExpr.FindAccessors): Just made flags const. + +2006-02-02 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitInitScope): I was wrong in the + commit yesterday, the initialization for the roots is necessary. + What is not necessary is the scope activation. + +2006-02-02 Raja R Harinath + + * ecore.cs (PropertyExpr.DoResolveLValue): Add CS0206 check. + * expression.cs (IndexerAccess.DoResolveLValue): Add CS1612 and + CS0206 checks. + (Argument.Resolve): Remove CS0206 checks. + +2006-02-01 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitInitScope): Do not emit the + scopes for all the roots, the scopes will now be emitted when the + Blocks are entered. [This change was wrong, fixed on 2006-02-02] + + (CaptureContext.EmitScopeInitFromBlock): Simply emit the ScopeInfo + code. This reduces a lot of existing cruft. + + * statement.cs (Block.Emit): Call EmitScopeInitFromBlock here, so + that the ScopeInfo is generated as we enter the scope, not at the + time of use, which is what we used to do before. + + * codegen.cs (EmitScopeInitFromBlock): New routine, this is called + every time a Block is about to be emitted if we have a + CaptureContext. + +2006-02-01 Raja R Harinath + + * typemanager.cs (NoTypes, NoTypeExprs): Remove. + (Reset): Update. + * *.cs: Use Type.EmptyTypes instead of TypeManager.NoTypes. + + * typemanager.cs (cons_param_array_attribute): Make private. + (Reset): Set it to null. + (InitCoreHelpers): Don't initialize it. + (ConsParamArrayAttribute): New. Initialize it as needed. + * parameter.cs (ParamsParameter.ApplyAttribute): Update to change. + +2006-01-31 Miguel de Icaza + + * expression.cs: There might be errors reported during the + selection of applicable methods. If there are errors, do not + continue execution as it will lead the compiler to crash. + +2006-01-30 Miguel de Icaza + + * expression.cs: Member access is not allowed on anonymous + methods. Fixes #77402. + +2006-01-30 Raja R Harinath + + Fix #77401 + * cs-parser.jay (VariableDeclaration): Don't set + current_array_type to null. + (field_declaration, event_declaration, declaration_statement): + Set it to null here. + +2006-01-28 Raja R Harinath + + * typemanager.cs (GenericParameterPosition): New. + * doc.cs: Use it. + +2006-01-28 Atsushi Enomoto + + * doc.cs : To process "include" elements, first we should create + another list than XmlNodeList, because it could result in node + removal, which could result in that the XmlNodeList gives up + yielding next node. + + (Also made code identical to gmcs again.) + +2006-01-25 Miguel de Icaza + + * ecore.cs: Introduce an error report that we were not catching + before, if not silent, we must report the error. Gonzalo ran into + it. + +2006-01-23 Miguel de Icaza + + A fix for bug: #76957 + + * iterators.cs (MoveNextMethod.CreateMethodHost): call + ComputeMethodHost before creating the method, this is a new + requirement. + + * anonymous.cs (AnonymousContainer): Now we track all the scopes + that this method references (RegisterScope). The actual scope + where the method is hosted is computed with the ComputeMethodHost + before we create the method. + + Moved the Deepest routine here. + + (AnonymousContainer.ComputeMethodHost): New routine used to + compute the proper ScopeInfo that will host the anonymous method. + + (ScopeInfo): Deal with multiple roots. The problem was that we + did not have a unique root where all ScopeInfos could be hanged + from. Remove `topmost' ScopeInfo, and instead keep an arraylist + of roots. + + Remove AdjustMethodScope which is now computed at the end. Remove + LinkScope which did a partial link, instead link all ScopeInfos + before code generation from the new "LinkScopes" routine. + + Simplify all the Add* routines as they no longer need to maintain + the tree, they just need to record that they are using variables + from a ScopeInfo. + + (IsAncestor, GetAncestorScopes, GetParentScope, LinkScope): New + routines to produce the forest of ScopeInfo trees. + + * class.cs (TypeContainer.AppendMethod): This is just like + AddMethod, but ensures that an interface implementation method + (IEnumerable.XXX) is not inserted at the beginning of the queue of + methods, but at the end. + + We use this functionality to ensure that the generated MoveNext + method in the iterator class is resolved/emitted before the + enumerator methods created. + + This is required because the MoveNext method computes the right + ScopeInfo for the method. And the other methods will eventually + need to resolve and fetch information computed from the anonymous + method. + +2006-01-21 Raja R Harinath + Carlos Alberto Cortez + + Fix rest of #76995. + * namespace.cs (NamespaceEntry.UsingExternalAliases): Don't add to + the 'aliases' hash. + (NamespaceEntry.LookupAlias): Lookup 'extern_aliases' hash too. + (NamespaceEntry.VerifyUsing): Resolve external aliases too. + +2006-01-18 Raja R Harinath + + Fix #76656, cs0231-2.cs. + * cs-parser.jay (formal_parameter_list): Make error case catch + more issues. + (parenthesized_expression_0): Add CS1026 check. + (invocation_expression): Remove unused { $$ = lexer.Location }. + +2006-01-17 Raja R Harinath + + Fix #76824. + * cs-parser.jay (statement_expression): Don't list out the + individual statement-expressions. Convert syntax error into + CS0201 check. + +2006-01-16 Raja R Harinath + + Fix #76874. + * ecore.cs (MemberAccess.CheckIntermediateModification): Remove. + (UnboxCast.DoResolveLValue): New. Move CS0445 check from + CheckIntermediateModification. + (FieldExpr.DoResolve): Add new two-argument version that + allows us to resolve the InstanceExpression as an lvalue. + The one-argument variant is now just a wrapper. + (FieldExpr.DoResolveLValue): Use two-argument DoResolve. + Resolve the lhs as an lvalue if the it has a value type. + (FieldExpr.AssignToReadonly): Move CS1648 and CS1650 checks + from Assign.DoResolve. + (PropertyExpr.InstanceResolve): Allow InstanceExpression to be + resolved as an lvalue. + (PropertyExpr.DoResolve): Update. + (PropertyExpr.DoResolveLValue): Resolve the lhs as an lvalue if it + has a value type. Move CS1612 check here from + CheckIntermediateModification. + * assign.cs (Assign.DoResolve): Remove CS1648 and CS1650 checks. + * expression.cs (EmptyExpression.OutAccess): New. Used as the + 'right_side' of a ResolveLValue on an 'out' argument. + (EmptyExpression.LValueMemberAccess): New. Used as the + 'right_side' of a propagated ResolveLValue on a value type. + (LocalVariableReference.DoResolveBase): Recognize + EmptyExpression.OutAccess and EmptyExpression.LValueMemberAccess. + Add CS1654 check. + (Argument.Resolve): Use EmptyExpression.OutAccess rather than + EmptyExpression.Null. + +2006-01-16 Atsushi Enomoto + + * typemanager.cs : added IsGenericParameter(). In mcs it always + return false. + * doc.cs : for generic parameters, use GenericParameterPosition, + not FullName. + +2006-01-12 Ben Maurer + + * expression.cs: Fix Console.WriteLine ((this = x).foo); + +2006-01-12 Miguel de Icaza + + This fixes the problem where we used ldfld instead of ldflda to + load the "THIS" pointer on captured parameters, when THIS is a + value type. See bug #77205. + + * iterators.cs (CapturedThisReference.Emit): Pass false to + EmitThis (we do not need the address). + + * codegen.cs (EmitThis): it needs to know whether we need the + address of `this' or not. This is used by value types. + + * expression.cs (This.AddressOf): Pass true to the EmitThis call, + every other call passes false. + +2006-01-12 Raja R Harinath + + Fix #77221. + * typemanager.cs (TryGetBaseDefinition): Rename from the mis-named + GetOverride. + * expression.cs (Invocation.OverloadResolve): Update. + (Invocation.DoResolve): Avoid double resolution of invocation. + +2006-01-11 Raja R Harinath + + Fix #77180. + * expression.cs (Unary.Emit): When in /checked+ mode, don't emit + unary negation of floating point types as 0-expr; negation cannot + overflow in floating point types. + + Fix #77204. + * expression.cs (MemberAccess.DoResolve): Disallow the use of '.' + on operands of 'void' type. + + Fix #77200. + * cfold.cs (BinaryFold): Implement folding of BinaryOr, BinaryAnd + and ExclusiveOr for boolean constants too. + +2006-01-09 Raja R Harinath + + Fix #75636. + * expression.cs (Invocation.OverloadResolve): Replace reflected + override methods with their base virtual methods, rather than + skipping over them. + * typemanager.cs (TypeManager.GetOverride): New. + +2006-01-05 Jb Evain + + * class.cs (Property.Define, Indexer.Define): do not tag the + properties as SpecialName | RTSpecialName. + +2006-01-04 Miguel de Icaza + + * class.cs (MethodCore.IsDuplicateImplementation): This method was + doing a low-level comparission of parameter types. It was lacking + a check for __argslist. + +2005-12-30 Miguel de Icaza + + * expression.cs (ParameterReference.DoResolveBase): Allow + reference parameters if they are local to this block. + + This allows the ref and out parameters of a delegate to be used in + an anonymous method, for example: + + delegate void set (out int x); + + set s = delegate (out int x){ + x = 0; + }; + + This is used by functionality introduced late in the C# language. + + * anonymous.cs (AnonymousMethod.Compatible): Allow anonymous + method that take ref and out parameters. + + Fixes #77119 which was a late change in the spec. + +2005-12-23 Miguel de Icaza + + * anonymous.cs (ScopeInfo.LinkScope): Do not link the scope to its + parent if its the same scope. Fixes #77060. + +2005-12-21 Miguel de Icaza + + * driver.cs: Report the case of no source files and no -out: + argument provided. + +2005-12-20 Raja R Harinath + + Fix #77035. + * expression.cs (ComposedCast.GetSignatureForError): Define. + +2005-12-18 Carlos Alberto Cortez + + Fix #76995 + + * namespace.cs (NamespaceEntry): Add extern_aliases as a + ListDictionary, to contain the ExternAliasEntry entries (in + addition to the NamespaceEntry.aliases hashtable). This field is + shared between the original entry and its doppelganger (bodyless + copy of it). + (NamespaceEntry.UsingExternalAlias): Add the extern alias entry to + extern_aliases field. + (NamespaceEntry.Lookup): Move the IsImplicit check after the + lookup in extern_aliases. + +2005-12-16 Raja R Harinath + + Fix #77006. + * class.cs (TypeContainer.Mark_HasEquals): New. + (TypeContainer.Mark_HasGetHashCode): New. + (ClassPart): Override them. + (MethodCore.CheckBase): Use them instead of referring to Parent.Methods. + + Fix #77008. + * enum.cs (EnumMember.EnumMember): Pass the parent_enum as the + 'parent' argument to the base constructor. + + Remove all mention of TypeContainer from decl.cs. + * decl.cs (MemberCore.Parent): Change into a DeclSpace. + (MemberCore.MemberCore): Change type of 'parent' argument to DeclSpace. + (DeclSpace.DeclSpace): Likewise. + (DeclSpace.DefineMembers): Remove unused argument. + * cs-parser.jay (pop_current_class): Update to changes. Simplify + debugging check -- we don't care if the debug code throws an + InvalidCastException instead of an InternalErrorException. + * class.cs (TypeContainer.DefineMembers): Update to changes. + (TypeContainer.DoDefineMembers): Likewise. + (TypeContainer.GetMethods): Likewise. + (PropertyMember.Define): Likewise. + (MemberBase.Parent): New property that forwards to + MemberCore.Parent, but ensures that we get a TypeContainer. + * rootcontext.cs (RootContext.PopulateCoreType): Update to changes. + (RootContext.PopulateTypes): Likewise. Remove special case code + for !RootContext.StdLib: DefineMembers is idempotent. + +2005-12-14 Miguel de Icaza + + * convert.cs (ExplicitConversionCore): Check the return value from + ExplicitConversionCore which can return null on failure. Fixes #76914 + +2005-12-13 Marek Safar + + * class.cs (Method.ApplyAttributeBuilder): Test out modifier properly. + +2005-12-11 Atsushi Enomoto + + * doc.cs : The search for referenced namespace was insufficient to + get global one as it used to do. Fixed bug #76965. + +2005-12-10 Atsushi Enomoto + + * doc.cs : check name in cref in the last phase that whether it is + namespace or not. + +2005-12-09 Atsushi Enomoto + + * cs-tokenizer.cs : reverted the latest change: it somehow broke + Mono.C5. + +2005-12-09 Atsushi Enomoto + + * doc.cs : so it turned out that we cannot skip override check for + interface members. Fixed bug #76954. + +2005-12-09 Atsushi Enomoto + + * cs-tokenizer.cs : fixed bug #75984: + - #warning and #error should not be handled when the source line + is disabled. + - #line is not checked strictly when the source line is disabled. + - #define and #undef is on the other hand checked strictly at any + state. + +2005-12-08 Atsushi Enomoto + + * cs-tokenizer.cs : missing Location (actually, filename) in one of + CS1027 report. + +2005-12-05 Marek Safar + + * attribute.cs (GlobalAttribute.ctor): Pass NamespaceEntry only. + + * class.cs (EmitFieldInitializers): Simplified and fixed to work with + event initializers. + (FieldBase.EmitInitializer): Moved from TypeContainer and simplified. + (FieldBase.Initializer): Initializer is now optional. + (EventField.Define): Only event field can have initializer. + + * codegen.cs (EmitContext): DeclSpace is not readonly (small hack). + + * const.cs (Const): Reuse initializer. + + * cs-parser.jay: Updated after FieldBase changes. + Added current_array_type to simplify array initializers. + + * ecore.cs (NullCast.IsDefaultValue): Implemented. + + * expression.cs, iterators.cs: Updated. + + * namespace.cs (NamespaceEntry): Made UsingFound private. + +2005-12-05 Marek Safar + + * parameterCollection.cs: Obsolete, removed. + * parser.cs: Obsolete, removed. + +2005-12-05 Marek Safar + + Fix #76849. + * class.cs (Constructor.Emit): Set obsolete checking for whole context. + + * enum.cs (Enum.Define): Set obsolete context here. + +2005-12-05 Atsushi Enomoto + + * doc.cs : + - FindDocumentedMember() now expects 1) paramList as null + when "we don't have to check the number of parameters" and + 2) Type.EmptyTypes when "there is no arguments". + - Introduced FoundMember struct to hold the exact type which was + used to find the documented member (the above change broke + test-xml-044; it might be better just to use DeclaringType than + what MS does, like this change does, but it depends on usage.) + +2005-12-05 Atsushi Enomoto + + * doc.cs : documented member might be from DeclaringType for nested + types. Fixed bug #76782. + +2005-12-03 Ben Maurer + + * anonymous.cs: Have the param code handle leaving copies on the + stack etc. Allows anonymous params to take part in the assignment + code (++, +=, etc). Fixes bug #76550 + + * expression.cs: Handle the prepare_for_load/leave_copy by passing + it down to the anon code. + + * iterators.cs: Use dummy var here + + * codegen.cs: Handle new vars + +2005-12-01 Marek Safar + + Fix #76849. + * class.cs (MethodData.Define): Set proper Obsolete context. + + * ecore.cs (FieldExpr.ResolveMemberAccess): Don't check [Obsolete] in + obsolete context. + (FieldExpr.DoResolve): Ditto. + +2005-12-01 Marek Safar + + Fix #76849. + * class.cs (MethodCore.DoDefineParameters): Test [Obsolete] only when + parent is not obsolete. + +2005-12-01 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) find parameterless members first + and get CS0419 in the early stage. Fixed first case of bug #76727. + +2005-11-30 Marek Safar + + Fix #76859. + * ecore.cs (Expression.ResolveAsConstant): Report constant error only when + no error was reported. + + *expression.cs (Binary.DoResolve): left can be null. + +2005-11-22 Marek Safar + + Fix #76783. + * class.cs (MethodData.Emit): Parameters should be labeled first. + +2005-11-21 Marek Safar + + Fix #76761. + * parameter.cs (Parameter.ApplyAttributeBuilder): Fixed `ref' detection. + +2005-11-18 Marek Safar + + * attribute.cs (AreParametersCompliant): Moved to Parameter. + + * class.cs (MethodCore): Parameter clean up. + (IMethodData): Added ParameterInfo. + (MethodData): Parameter clean up. + (Indexer.Define): Parameter clean up. + + * anonymous.cs, + * codegen.cs, + * cs-parser.jay, + * decl.cs, + * doc.cs, + * ecore.cs, + * flowanalysis.cs, + * iterators.cs, + * pending.cs, + * statement.cs, + * typemanager.cs: Parameter clean up. + + * delegate.cs (Define): Get rid of duplicated code. + + * expression.cs (ParameterReference): Removed useless parameters + and simplified. + (Invocation): Ditto. + + * parameter.cs (ParamsParameter): New class, params specialization. + (ArglistParameter): Attemp to separate arglist. + (Parameter): Refactored to be reusable and faster. + (Parameter.Modifier): Made understandable. + (Parameters): Changed to be used as a class for `this' assembly + parameters. Refactored to use new specialized classes. + + * support.cs (ParameterData): Added Types property. + (InternalParameters): Deleted. + +2005-08-20 Martin Baulig + + Merging this patch from GMCS to fix #75867. + + * anonymous.cs (CaptureContext.CaptureThis): Create the topmost + scope if we don't already have it. + +2005-11-17 Martin Baulig + + * anonymous.cs + (CaptureContext.EmitMethodHostInstance): Use `Ldarg_0' if we + inherit the scope from our parent. Fixes #76653. + +2005-11-16 Atsushi Enomoto + + * doc.cs : the previous patch does not actually fix the bug. + PropertyInfo override check is now implemented and really fixed it. + * expression.cs : Invocation.IsAncestralType() is used from doc.cs. + +2005-11-16 Atsushi Enomoto + + * doc.cs : apply "override filter" also to properties. + Fixed bug #76730. + +2005-11-16 Atsushi Enomoto + + * doc.cs : renamed FindMembers() to FindMethodBase(). For interfaces, + no need to check overrides. For classes, omit those results from + interfaces since they must exist in the class. Fixed bug #76726. + +2005-11-15 Atsushi Enomoto + + * typemanager.cs : (GetFullNameSignature) differentiate indexers + with different parameters. Fixed the second problem in #76685. + +2005-11-15 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) pass invocation_type as well (to + get expected 'protected' access in CheckValidFamilyAccess()). + Fixed bug #76692. + +2005-11-15 Atsushi Enomoto + + * doc.cs : (GenerateTypeDocComment) Fields could be FixedField. + Fixed bug #76705. CS1569 was incorrectly commented out. + +2005-11-14 Atsushi Enomoto + + * doc.cs : use Invocation.IsOverride() to do real override check. + * expression.cs : made Invocation.IsOverride() internal. + +2005-11-14 Atsushi Enomoto + + * doc.cs : use TypeManager.FindMembers() instead of (possible) + TypeBuilder.FindMembers() and filter overriden base members out. + Fixed bug #76990. + +2005-11-13 Atsushi Enomoto + + * doc.cs : ref/out parameters are represented as '@' (instead of + '&' in type FullName). Fixed bug #76630 (additionally crefs). + +2005-11-13 Atsushi Enomoto + + * doc.cs : when there was no '.' in cref to methods in doc comment, + then parameters were missing in the output. Fixed bug #76691. + +2005-11-13 Atsushi Enomoto + + * driver.cs : don't output docs when there is an error. + Fixed bug #76693. + +2005-11-13 Atsushi Enomoto + + * doc.cs : + Now it should detect indexers. Fixed primary concern in bug #76685. + Fixed CS0419 message to not show the identical member signature in + the message. + +2005-11-13 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) use TypeManager.MemberLookup() + instead of Type.FindMembers() since it does not handle events. + Fixed bug #71604. + +2005-11-12 Gert Driesen + + * codegen.cs: Fixed typo (speficied -> specified). + +2005-11-11 Marek Safar + + Fix #76369. + * doc.cs (FindDocumentedTypeNonArray): Don't resolve again. + +2005-11-11 Marek Safar + + * attribute.cs: Changed error message. + + * cs-tokenizer.cs: One more check. + +2005-11-10 Marek Safar + + * statement.cs (Block.Resolve): Ignore empty statement. + +2005-11-10 Marek Safar + + * report.cs: Made error/warning methods more strict to avoid + their misuse. + + * anonymous.cs, attribute.cs, class.cs, codegen.cs, constant.cs, + convert.cs, cs-parser.jay, cs-tokenizer.cs, decl.cs, delegate.cs, + doc.cs, driver.cs, ecore.cs, expression.cs, location.cs, + namespace.cs, parameter.cs, statement.cs, typemanager.cs: Updated. + +2005-11-08 Marek Safar + + * attribute.cs (Attribute.GetCoClassAttributeValue): New method. + (AttributeTester.GetCoClassAttribute): Get CoClassAttribute. + + * class.cs (TypeContainer.IsComImport): New property. + (Constructor.Define): Create proper ctor for ComImport types. + + * expression.cs (New.CheckComImport): Fixed. + +2005-11-07 Miguel de Icaza + + * anonymous.cs (CaptureContext.AddParameterToContext): The fact + that a parameter has been captured does not mean that we do not + have to do the rest of the processing. This fixes the second part + of #76592. If there was another anonymous method capturing + values in the past, the Scope would never be set for the second + method that captured the same parameter. + + (CaptureContext.EmitAssignParameter): When `leave_copy' is passed, + properly manipulate the stack. Second part of fix for #76592. + + * expression.cs (New): Add support for invoking "new" on + interfaces that have been flagged with the ComImport attribute and + the CoClass. Fixes #76637 + + * statement.cs (Try.DoEmit): When a variable is captured, do not + try to emit the vi.LocalBuilder variable as it has been captured. + Create a temporary variable and store the results on the + FieldBuilder. Fixes #76642 + +2005-11-07 Marek Safar + + * class.cs (CheckPairedOperators): Made compilable with csc 2.0. + + * ecore.cs (InstanceResolve): Fixed CS1540 detection. + + * expression.cs (Binary.DoResolve): Added && optimalization. + + * typemanager.cs (AddUserType): Removed useless argument. + +2005-11-04 Marek Safar + + * statement.cs (Block.variables): Uses ListDictionary. + +2005-11-03 Marek Safar + + Fix #75969. + * class.cs (PartialContainer.EmitType): Customized to emit + security attributes. + (ClassPart.ApplyAttributeBuilder): Transform security attribute + for partial classes. + +2005-11-03 Marek Safar + + Fix #76599. + * expression.cs (ElementAccess.DoResolveLValue): Fixed buffer + access has to be fixed. + + * typemanager.cs (IsUnmanagedType): Wrong common field type. + +2005-11-01 Marek Safar + + Fix #76590. + * ecore.cs (NullCast.Reduce): Implemented. + + * expression.cs (ArrayCreation.CheckIndices): Correcly check + constant type. + + * statement.cs (SwitchLabel.ResolveAndReduce): Catch null + properly. + (Foreach.Resolve): Catch null properly. + +2005-10-29 Marek Safar + + * cs-tokenizer.cs: Warning text fix. + + * driver.cs: AllWarningNumbers exposed on public interface. + + * report.cs (): Reviewed warning numbers. + (IsValidWarning): Use binary search. + +2005-10-29 Marek Safar + + * driver.cs: Implemeted resource visibility. + (Resources): New class for code sharing between /res: and + /linkres: + +2005-10-28 Marek Safar + + Fix #76568. + * cfold.cs (ConstantFold.BinaryFold): Implemented null cast + folding. + + * convert (Convert.ImplicitReferenceConversion): NullCast holds + contants only. + + * ecore.cs (NullCast): Child is contant only. + + * literal.cs (NullLiteral.Reduce): null can be converted to any + reference type. + +2005-10-28 Kornél Pál + + * driver.cs: Use Encoding.Default as default code page instead + of ISO-28591. + +2005-10-27 Raja R Harinath + + Fix #76085. + * expression.cs (Invocation.Error_InvalidArguments): Handle + __arglist parameters. + (Invocation.VerifyArgumentsCompat): Likewise. + * support.cs (ReflectionParameters.GetSignatureForError): Print + __arglist parameters. + (InternalParamters.GetSignatureForError): Likewise. + * parameter.cs (Parameters.GetSignatureForError): Likewise. + +2005-10-26 Marek Safar + + * attribute.cs (GetPropertyValue): Made public. + + * codegen.cs (AssemblyClass): ResolveClsCompliance renamed to + Resolve. + Add new property WrapNonExceptionThrows to handle 2.0 assembly + attribute. + (AssemblyClass.Emit): Emit RuntimeCompatibilityAttribute when it + is not defined. + + * driver.cs: Reflect method name change. + + * statement.cs (Try.Resolve): Warn when try has both general + exception handlers. + + * typemanager.cs: runtime_compatibility_attr_type new predefined + type. + +2005-10-26 Raja R Harinath + + Fix #76419. + * pending.cs (InterfaceMethod): Allow tm.args [i] to be null -- + treat it as an empty parameter list. + +2005-10-26 Raja R Harinath + + Fix #76271. + * ecore.cs (SimpleName.DoSimpleNameResolve): Make fall-back + ResolveAsTypeStep silent. + * statement.cs (Block.AddConstant): Mark block as used. + (Block.ResolveMeta): Avoid piling on error messages + if a constant initializer resolution fails. + +2005-10-25 Raja R Harinath + + * namespace.cs (RootNamespace.VerifyUsingForAll, Namespace.VerifyUsing): + Remove. + (NamespaceEntry.VerifyAllUsing): New. + (NamespaceEntry.AliasEntry.Resolve): New. Handles common error + behaviour. Delegates actual resolution of alias to ... + (NamespaceEntry.DoResolve): ... this. Renamed from Resolve. + (NamespaceEntry.LocalAliasEntry, NamespaceEntry.ExternAliasEntry): + Update. + * driver.cs (Driver.MainDriver): Update. + + * namespace.cs (NamespaceEntry.DefineNamespace): Remove. + (NamespaceEntry.SymbolFileID): Make into a on-demand computed + property. + (Namespace.DefineNamespaces, RootNamespace.DefineNamespacesForAll): + Remove. + * symbolwriter.cs (SymbolWriter.Initialize): Don't call + RootNamespace.DefineNamespacesForAll. + +2005-10-24 Raja R Harinath + + * typemanager.cs (assemblies, external_aliases, modules) + (AddAssembly, AddExternAlias, AddModule GetAssemblies, Modules) + (ComputeNamespaces, GetRootNamespace): Remove extra staging + overhead. Move resposibility ... + * namespace.cs (GlobalRootNamespace): ... here. Update to changes. + * driver.cs, attribute.cs, codegen.cs: Update to changes. + +2005-10-23 Raja R Harinath + + * namespace.cs (RootNamespace.all_namespaces): Renamed from + cached_namespaces. Improve usage. + (RootNamespace.Reset, RootNamespace.RegisterNamespace) + (RootNamespace.VerifyUsingForAll, RootNamespace.DefineNamespacesForAll): + Move from GlobalRootNamespace and simplify. + (RootNamespace.Global): Make instance variable. + (RootNamespace.RootNamespace): Add "alias name" parameter. + (GlobalRootNamespace): Simplify drastically. + (Namespace.Lookup): Don't use GetNamespace. + * typemanager.cs (GetRootNamespace): Rename from + ComputeNamespaceForAlias. + (NamespaceClash): Use Global.IsNamespace instead of GetNamespace. + +2005-10-23 Marek Safar + + * anonymous.cs (AnonymousContainer): Don't crash when container + doesn't exist. + +2005-10-23 Marek Safar + + * expression.cs (Binary.DoResolve): Warn when comparing same + values. + +2005-10-23 Marek Safar + + Fix #76486. + * expression.cs (Binary.DoResolve): It looks like there are no + convetsion rules in enum context. + +2005-10-19 Carlos Alberto Cortez + + Add support for extern alias qualifiers. + * typemanager.cs: Move some LookupTypeReflection code + to namespace.cs, to have cleaner code. Added some methods + to help us keep track of the extern aliased references. + * driver.cs: Add suport for extern alias assemblies on command + line and check for their warnings/errors. Also keep track of the + extern aliased assemblies. + * namespace.cs: Move the global functionality of Namespace + to GlobalRootNamespace/RootNamespace. Now the global namespace + is GlobalRootNamespace.Globa. Also the code moved from + typemanager.cs lives in GlobalRootNames.cs/RootNamespace.cs. + Finally added LocalAliasEntry (AliasEntry before) and + ExternAliasEntry, to handle alias statements. + * cs-parser.jay: Add support in the grammar for extern alias + statement. + * doc.cs, delegate.cs, expression.cs ecore.cs, symbolwriter.cs: + Update callings to Namespace (now in GlobalRootNamespace). + +2005-10-18 Raja R Harinath + + Fix #76371. + * class.cs (TypeContainer.DefineType): Move updating of + topological sort earlier in the code. + * decl.cs (DeclSpace.ResolveBaseTypeExpr): Don't use TypeBuilder. + +2005-10-18 Marek Safar + + Fix #76273. + * cfold.cs (BinaryFold): Reduce constant in enum conversion. + + * constant.cs (Constant.TryReduce): Moved from Cast class. + (Reduce): Made little bit more OO and fixed missing conversions. + + * ecore.cs (Reduce): Implemented. + (Binary.EnumLiftUp): New method to upgrade values to enum values. + + * literal.cs (Reduce): Implemented. + + * class.cs: Reverted Miguel's wrong commit. + +2005-10-14 Miguel de Icaza + + * ecore.cs (GetMemberType): Report the correct mapping for the MemberCore + +2005-10-14 Atsushi Enomoto + + * cs-parser.jay, expression.cs : CS0214 was missing error location + for constants. Fixed bug #76404. + +2005-10-11 Marek Safar + + Fix #76370. + * convert.cs (ExplicitConversionCore): Fixed object->enum + conversion. + +2005-10-10 Raja R Harinath + + * ecore.cs (PropertyExpr.Emit): Use Invocation.EmitCall to emit + InstanceExpression. + (PropertyExpr.EmitCall): Likewise. + * expression.cs (Invocation.EmitArguments): Handle case where + arguments == null. + (Invocation.EmitCall): Avoid allocating temporary variable if + there are no arguments. + +2005-10-07 Raja R Harinath + + Fix #76323. + * convert.cs (ImplicitConversionStandard): Move conversion of + void* to arbitrary pointer types ... + (ExplicitConversionStandard): .. here. + * ecore.cs (Expression.Error_ValueCannotBeConverted): Fix CS0266 + error to always print typenames. + +2005-10-07 Raja R Harinath + + * convert.cs (GetConversionOperator): Rename from + GetConversionOperators. Move operator selection code from ... + (UserDefinedConversion): ... here. + +2005-10-06 Marek Safar + + * convert.cs (ExplicitConversionCore): Removed duplicate enum + conversion. + +2005-10-05 Marek Safar + + * assign.cs (Assign.DoResolve): Error method changed. + + * cfold.cs (DoConstantNumericPromotions): Error method changed. + + * const.cs (ResolveValue): Reset in_transit immediately. + + * constant.cs: Error method changed. + + * convert.cs: Removed useless location parameter. + (ExplicitNumericConversion): Don't do double enum check. + (ExplicitConversionCore): Renamed from ExplicitConversion. + (ExplicitUnsafe): Extracted from ExplicitConversion. + (ExplicitConversion): Uses for error reporting. + + * ecore.cs (Error_ValueCannotBeConverted): More logic for more + error messages. + (ResolveBoolean): Uses common error method. + (CastToDecimal): Get rid of ec. + (CastFromDecimal): Optimized. + (ConvCast): Get rid of ec. + + * enum.cs (ResolveValue): Reset in_transit immediately. + (Emit): Return after first error. + + * expression.cs: Convert changes. + + * literal.cs: Error method changed. + + * statement.cs: Error method changed. + +2005-10-03 Raja R Harinath + + * support.cs (SeekableStreamReader.Position): Don't error out when + the requested position is just beyond the end of the current + buffered data. + +2005-09-28 Raja R Harinath + + * support.cs (SeekableStreamReader): Simplify drastically. Don't + try to keep in sync with the byte count of the underlying Stream. + However, this limits us to a window size of 2048 characters: i.e., + the maximum lookahead of our lexer/parser can be 2048 characters. + +2005-09-28 Marek Safar + + Fix #76255. + * driver.cs: Fix compilation files with full root path. + +2005-09-25 Miguel de Icaza + + * report.cs (SymbolRelatedToPreviousError): Format the output so + it does not use an open parenthesis that is never closed. + + * driver.cs: Follow coding guidelines + +2005-09-27 Marek Safar + + Fix #72930. + * const.cs (Const.ResolveValue): Check for assigning non-null + value to reference type. + +2005-09-27 Marek Safar + + * anonymous.cs: Implemented ExprClassName. + + * assign.cs (Assign.DoResolve): Don't chrash when type is not + delegate. + + * attribute.cs (ResolveArguments): Enabled MethodImplOptions + check. + + * class.cs (StaticClass.DefineContainerMembers): Report protected + members as error. + + * codegen.cs: if(ed) PRODUCTION. + + * convert.cs (Error_CannotImplicitConversion): Better error + distinction. + + * cs-parser.jay: More error checks. + + * cs-tokenizer.cs (consume_identifier): Fixed Miguel's revert. + + * driver.cs (CSCParseOption): Enabled wrong option check. + + * ecore.cs (Expression.ExprClassName): Turned to property. + (MemberExpr.CheckIntermediateModification): For checking boxed + value types modification. + + * statement.cs (Fixed.Resolve): Expression type must be + convertible to fixed type. + (CollectionForeach.GetEnumeratorFilter,TryType): + Small refactoring for easier error checking. + +2005-09-26 Marek Safar + + * attribute.cs (Attribute.Resolve): Check Obsolete attribute for + attributes. + + * class.cs (GeneratedBaseInitializer): New class for customization + compiler generated initializers. + (MemberBase.DoDefine): Check Obsolete attribute here. + (FieldMember.DoDefine): Ditto. + + * const.cs (ExternalConstant.CreateDecimal): Builder for decimal + constants. + + * decl.cs (MemberCore.EmitContext): Returns valid current ec. + (MemberCore.GetObsoleteAttribute): Removed argument. + (MemberCore.CheckObsoleteness): Obsolete attributes are hierarchic. + (MemberCore.CheckObsoleteType): New helper. + + * delegate.cs, + * enum.cs, + * statement.cs: Updates after MemberCore changes. + + * ecore.cs (TypeExpr.ResolveType): Check type obsoleteness here. + (FieldExpr.ResolveMemberAccess): Fixed decimal constants checks. + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Don't check + obsolete attribute for compiler construct. + (As.DoResolve): Cache result. + + * iterators.cs (Define_Constructor): Use GeneratedBaseInitializer. + +2005-09-26 Raja R Harinath + + Fix #76133. + * expression.cs (This.VerifyFixed): In a value type T, the type of + 'this' is T&, iow, 'this' is either an out or ref parameter. In a + value type R, 'this' is treated as a value parameter. + +2005-09-22 Miguel de Icaza + + * statement.cs (Lock): Use the TemporaryVariable class instead of + manually using local variables as those do not work when variables + are captured. + + * ecore.cs: Moved the TemporaryVariable class from being a nested + class inside Foreach to be a public class that can be employed in + other places. + +2005-09-19 Marek Safar + + * cs-parser.jay: interface_accessors replaced by + accessor_declarations. + + * ecore.cs, literal.cs, statement.cs: NullLiteral holds null + location. + + * statement.cs (GotoCase.Resolve): Convert null constant to + null case. + (SwitchLabel.ResolveAndReduce): Ditto. + (SwitchLabel.NullStringCase): Custom null stamp. + (Switch.SimpleSwitchEmit): Fix from NullLiteral to NullStringCase. + + typemanager.cs (CSharpSignature): Don't skip first argument + for full names. + +2005-09-18 Miguel de Icaza + + * driver.cs: Set InEmacs based on the environment variable EMACS. + + * location.cs (InEmacs): in this mode, do not report column + location as it confuses Emacs. + +2005-09-16 Marek Safar + + * cfold.cs, constant.cs, convert.cs, ecore.cs, + expression.cs, iterators.cs, literal.cs: Store constants and + literals location. + + * class.cs (MemberBase.ShortName): Pass location. + + * cs-parser.jay: Some location fixes. + + * ecore.cs (Expression.Location): Made virtual. + +2005-09-05 Miguel de Icaza + + * expression.cs (Cast.TryReduce): Only reduce to an EnumConstant + if the underlying types are the same, otherwise we need to produce + code that will do the proper cast. + + This was exposed by Marek's constant rewrite which produced + invalid code for the call site: + + enum X : long { a } + void Method (X v) {} + + Method ((X) 5) + + This fixes test-49.cs + +2005-09-05 Atsushi Enomoto + + * attribute.cs : (Attribute.IsValidArgumentType): array of string/ + Type/Object should be allowed as well. Fixed bug #75968. + +2005-09-05 Atsushi Enomoto + + * expression.cs : (Binary.DoResolve): when one is enum constant and + another is constant 0, then return enum one *as enum type*. + Fixed bug 74846. + +2005-09-02 Raja R Harinath + + * attribute.cs (GetMarshal): Work even if "DefineCustom" is + internal. + + Fix #75941. + * ecore.cs (SimpleNameResolve.DoSimpleNameResolve): Disable + flow-branching for LocalVariableReferences in case we were invoked + from a MemberAccess. + * expression.cs (LocalVariableReference.VerifyAssigned): New. + Carved out of ... + (LocalVariableReference.DoResolveBase): ... this. + (MemberAccess.Resolve): Do the check that was disabled during + SimpleNameResolve. + +2005-09-01 Atsushi Enomoto + + * class.cs : + (PartialContainer.Create): check abstract/sealed/static strictly + but abstract/sealed can exist only at one side. Fixed bug #75883. + +2005-09-01 Kornél Pál + + Fix #75945. + * attribute.cs (Attribute.GetMarshal): If ArraySubType is not + specified, don't default to UnmanagedType.I4. + +2005-09-01 Atsushi Enomoto + + * expression.cs : conditional operator should check possibly + incorrect assign expression. Fixed bug #75946. + +2005-08-31 Atsushi Enomoto + + * cs-tokenizer.cs, cs-parser.jay, driver.cs, support.cs : + Reverting the change. gmcs is much complex than mcs on this matter. + +2005-08-31 Atsushi Enomoto + + * cs-tokenizer.cs : To read another token ahead of the actual + consumption, use new SavedToken and cache token instead of moving + back the stream with SeekableStreamReader (it seemed problematic). + * cs-parser.jay, + driver.cs : Thus use StreamReader directly. + * support.cs : Thus removed SeekableStreamReader. + +2005-08-30 Raja R Harinath + + Fix #75934. + * anonymous.cs (ScopeInfo.MakeFieldName): New helper. + (ScopeInfo.EmitScopeType): Use it to construct field names from + names of captured locals. + + Fix #75929. + * ecore.cs (BoxedCast.BoxedCast) [1-argument variant]: Remove. + * convert.cs (ImplicitReferenceConversion, TryImplicitIntConversion): + Pass 'target_type' to BoxedCast. Don't default to 'object'. + (ExplicitConversion): Remove enum cases already handled by + implicit conversion. Move implicit conversion check to the beginning. + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Update. + * expression.cs (ArrayCreation.EmitDynamicInitializers): + Don't treat System.Enum as a struct. + +2005-08-30 Jb Evain + + * attribute.cs: handles as expression in parameters. + +2005-08-30 Raja R Harinath + + Fix #75802. + * class.cs (TypeContainer.VerifyClsName): Don't use a + PartialContainer when verifying CLS compliance. + (AbstractPropertyEventMethod): Set Parent here, ... + (PropertyMethod): ... not here. + +2005-08-30 Atsushi Enomoto + + * attribute.cs : escaped attribute name should not be allowed to be + resolved (e.g. @class as classAttribute). Fixed bug #75930. + +2005-08-29 Raja R Harinath + + Fix #75927. + * convert.cs (ImplicitStandardConversionExists): Allow zero also + when converting a long constant to unsigned long. + * expression.cs (Invocation.OverloadResolve): Add sanity check to + detect where IsApplicable and VerifyArgumentsCompat disagree. + +2005-08-29 Raja R Harinath + and Carlos Alberto Cortez + + Fix #75848. + * class.cs (TypeContainer.CanElideInitializer): New helper. + (TypeContainer.EmitFieldInitializers): Use it to determine if we + can safely emitting the initializer of a field. + +2005-08-25 Atsushi Enomoto + + * statement.cs : (Continue.Resolve()) Unlike break, continue is not + allowed inside a switch (without loop). Fixed bug #75433. + +2005-08-26 Kornél Pál + + * AssemblyInfo.cs: Using Consts.MonoVersion instead of MonoVersion.cs. + * mcs.exe.sources: Using Consts.MonoVersion instead of MonoVersion.cs. + +2005-08-25 Atsushi Enomoto + + * driver.cs : kinda reverting the default encoding changes (not exact + revert since I noticed that "codepage:reset" might not work fine). + +2005-08-25 Atsushi Enomoto + + * class.cs : (AbstractPropertyEventMethod) SetupName() now takes + Location. Now getter and setter store location correctly. + (errors/cs0111-12.cs now reports the expected location.) + +2005-08-25 Atsushi Enomoto + + * driver.cs : Use default encoding on the environment. + Removed (now that) extra parameter for SeekableStreamReader. + * support.cs : (SeekableStreamReader) third .ctor() argument for + StreamReader is not required (always true). preamble size could + be acquired in simpler and safe way. + +2005-08-24 Atsushi Enomoto + + * cs-parser.jay: report CS0642 at warning level 3 + and report CS0642 for an if else statement also + fixes bug #74745. Patch by John Luke (and a bit + modified by me). + Removed extra CS0642 warning check for "while", + "for" and "fixed". + * statement.cs: In Block.Resolve(), CS0642 check + is reimplemented to check a sequence of an empty + statement and a block. + + Both fix bug #66777. + +2005-08-24 Marek Safar + + * attribute.cs (GetMethodObsoleteAttribute): Disabled obsolete properties + detection until I fix it. + + * cs-tokenizer.cs: Changed error message. + + * cs-parser.jay: Fixed 2 error locations. + + * ecore.cs (Error_TypeDoesNotContainDefinition): Share error message. + (PropertyExpr.Error_PropertyNotFound): First attempt to detect non C# + properties. + + * enum.cs (GetSignatureForError): Fixed. + + * expression.cs (Invocation.IsSpecialMethodInvocation): Improved special + method detection. + + * class.cs, + * typemanager.cs (RegisterProperty): Removed. + + * statement.cs (CheckInvariantMeaningInBlock): Changed error message. + +2005-08-24 Raja R Harinath + + Fix #75874. + * expression.cs (ArrayAccess.EmitLoadOpcode): Emit ldelem.i for pointers. + (ArrayAccess.GetStoreOpcode): Return stelem.i for pointers. + +2005-08-23 Atsushi Enomoto + + * expression.cs : tiny fix is required for not warning positive ulong. + See test-441.cs. + +2005-08-23 Atsushi Enomoto + + * expression.cs : add CS0652 check for constant and integral + expression. Fixed bug #53974. + +2005-08-23 Atsushi Enomoto + + * expression.cs : in DoNumericPromotions(), check if there is implicit + conversion overload for string (to check CS0034). Fixed bug #52492. + +2005-08-23 Atsushi Enomoto + + * cs-tokenizer.cs : Check newline in char constant. Fixed bug #75245. + +2005-08-23 Atsushi Enomoto + + * ecore.cs : report location when it is *not* Null. + +2005-08-23 Atsushi Enomoto + + * codegen.cs, + ecore.cs, + flowanalysis.cs, + expression.cs: + Added OmitStructFlowAnalysis to EmitContext to handle CS0165 check + correctly. Fixed bug #75721. + +2005-08-23 Raja R Harinath + + * support.cs (SeekableStreamReader.Position): Avoid an expensive + loop that performs 'min (pos, char_count)'. + + Fix #75862. + * expression.cs (Unary.ResolveOperator): Don't discard implicit + converted value in Operator.OnesComplement. + +2005-08-22 Ben Maurer + + * anonymous.cs: If the anon method is pulled into a helper class, + it needs to be `internal' not `private'. Fixes runtime behavior on + msft. bug #75704 + +2005-08-20 Martin Baulig + + * anonymous.cs (CaptureContext.CaptureThis): Create the topmost + scope if we don't already have it. + + * expression.cs (Invocation.EmitCall): Use `ec.EmitThis ()' rather + than `ig.Emit (OpCodes.Ldarg_0)' to make it work inside iterators; + fixes #75867. + +2005-08-17 Marek Safar + + Fix #75803 + * decl.cs (DeclSpace.VerifyClsCompliance): Skip when collision object + is a partial class. + +2005-08-16 Marek Safar + + The big constants rewrite + Fix #75746, #75685 and more + As a side effect saved 1MB for MWF ;-) + + * attribute.cs (GetAttributeArgumentExpression): Use ToType, GetTypedValue. + (GetMarshal, GetMethodImplOptions, GetLayoutKindValue): Values are not + enum based for corlib compilation. + + * cfold.cs (BinaryFold): Convert operand for enum additions. Fixed enum + subtractions. + + * class.cs (FixedField.Define): Use ResolveAsConstant. + + * const.cs (IConstant): Interface constants and enums. + (Const.ResolveValue): New method for constant resolvning. + (ExternalConstant): Constants from imported assemblies. + + * constant.cs (Constant.GetTypedValue): Used to get constant with forced + conversion; like enums. + (Constant.ToType): Converts this constant to different type. + (Constant.Increment): Adds 1. + + * convert.cs (ImplicitConversionRequired): Simplified. + + * cs-parser.jay: Create EnumMember directly. + + * decl.cs (MemberCore.CheckObsoleteness): Checks for ObsoleteAttribute presence. + + * doc.cs (GenerateEnumDocComment): Removed. + + * ecore.cs (Expression.ResolveAsConstant): New constant specific method. + (ConvertIntLiteral): Removed. + (FieldExpr.ResolveMemberAccess): Refactored to remove constant specific if(s). + + * enum.cs (EnumMember): Implement IConstant. + (Enum.IsValidEnumConstant): Removed. + (Enum.GetNextDefaultValue): Removed. + (Enum.FindMembers): Updated. + (Enum.GenerateDocComment): Iterate enum members. + + * expression.cs (Cast.TryReduce): Handle enums correctly. + (New.Constantify): Made public. + (MemberAccess.DoResolve): Removed contant specific if(s). + + * literal.cs (NullLiteral): Implement new abstract methods. + + * statement.cs (GotoCase.Resolve): Use new constant methods. + (SwitchLabel.ResolveAndReduce): Use new constant methods. + + * typemanager.cs (LookupEnum): Removed. + (IsEnumType): Fixed to work with corlib. + (RegisterConstant): Removed. + (LookupConstant): Removed. + (GetConstant): Changed to work with IConstant. + +2005-08-04 Atsushi Enomoto + + * location.cs : Fixed overflown (>255) column number. + +2005-08-03 Raja R Harinath + + First cut of the qualified-alias-member feature. + * cs-tokenizer.cs (Tokenizer.is_punct): Recognize the double-colon + token. + * cs-parser.jay (DOUBLE_COLON): New token. + (namespace_or_type_name): Add rule for recognizing + qualified-alias-members. + (primary_expression): Likewise. + (element_access): Allow QualifiedAliasMember as a possible + type-bearing expression. + (local_variable_type, local_variable_pointer_type): Likewise. + * namespace.cs (NamespaceEntry.LookupAlias): New. Looks up + aliases in the current and enclosing namespace declarations. + (NamespaceEntry.UsingAlias): Add CS0440 warning. + * decl.cs (MemberName.is_double_colon): New. + (MemberName.MemberName): Add new constructor for alias-member. + (MemberName.GetTypeExpression): Generate QualifiedAliasMember too. + * expression.cs (QualifiedAliasMember): New expression type. + +2005-08-02 Atsushi Enomoto + + * location.cs : it borked when no argument was specified. + +2005-08-02 Atsushi Enomoto + + * location.cs : tiny ToString() format fix. + +2005-08-02 Atsushi Enomoto + + * statement.cs : oops, it was missing. + +2005-08-02 Atsushi Enomoto + + A set of fixes for precise line/column location. + + * location.cs : + "token" field now holds a file/line "delta", a line number offset + from the segment, and a column number. See also: + http://lists.ximian.com/pipermail/mono-devel-list/2004- + December/009508.html + Removed static IsNull. Use instance IsNull property instead. + * cs-tokenizer.cs : + For some tokens it stores Location. For Identifier it stores + LocatedToken which is a pair of string name and location. + Column numbers are adjusted only at getChar(). + * report.cs : + Use Location.ToString() for reporting (it now contains column). + * cs-parser.jay : + Largely modified to use LocatedToken instead of + string (IDENTIFIER), and to acquire Location from some tokens. + * namespace.cs, decl.cs, ecore.cs, class.cs, delegate.cs, + iterators.cs, const.cs, anonymous.cs, tree.cs, enum.cs, + codegen.cs : + Now MemberName holds Location. DeclSpace.ctor() receives Location + as a parameter. Removed extra parameters to all derived classes. + Replaced Location.IsNull() with instance property. + * assign.cs, expression.cs : + Added .ctor() overload that omits Location. + * attribute.cs : + Added "nameEscaped" flag that indicates the identifier was escaped + in the source file. This fixes bug #57047. + +2005-08-02 Marek Safar + + * attribute.cs (AttributeTester.GetImportedIgnoreCaseClsType): + New method, looking for lo-case imported cls type. + + * decl.cs (DeclSpace.VerifyClsCompliance): Check CS3005 for types + here. + + * driver.cs: Removed VerifyTopLevelNameClsCompliance usage. + + * enum (Enum.VerifyClsCompliance): Hardcode non-compliant types. + + * typemanager.cs (TypeManager.AllClsTopLevelTypes): Renamed from + all_imported_types. + (TypeManager.LoadAllImportedTypes): Lo-case imported types. + + Optimized to save 3.5 MB for SWF compilation. + +2005-08-01 Marek Safar + + * class.cs (AddToTypeContainer): Use inheritance insted of if(s). + (PartialContainer.Create): Moved logic AddToContainer. + (PartialContainer.MarkForDuplicationCheck): Shares name. + + * decl.cs (DeclSpace.AddToContainer): Check name collisions at one + place. + + * namespace.cs (Namespace.AddDeclSpace): Lazy declspaces + initialization. + (Namespace.GetSignatureForError): New method. + + * tree.cs (Tree.RecordDecl): Moved to AddToContainer. + (RootTypes.AddToTypeContainer): se inheritance insted of if(s). + +2005-08-01 Raja R Harinath + + Fix #75669. + * ecore.cs (Expression.MemberLookupFailed): Use queried_type for + member lookup rather than qualifier_type, since qualifier_type can + be null. + +2005-08-01 Marek Safar + + * enum.cs (Enum.VerifyClsName): Fixed to allow not CLSCompliant + enum member. + +2005-07-31 Miguel de Icaza + + * statement.cs: Copy the local exception into the exception + captured local. Fixes 75674 + +2005-07-31 Raja R Harinath + + Fix #75658. + * expression.cs (Invocation.OverloadResolve): Don't report error + CS1501 if error CS1502 has been reported. + (New.DoResolve): Delegate CS1501 reporting to + Invocation.OverloadResolve. + + Fix #75656. + * statement.cs (Block.CheckInvariantMeaningInBlock): Verify + invariant-meaning-in-block property in an enclosing block if + necessary. + +2005-07-29 Marek Safar + + * statement.cs (SwitchLabel.ResolveAndReduce): Refactored. + (SwitchLabel.Erorr_AlreadyOccurs): Share error message. + (Switch.CheckSwitch): Just save 50kb for SWF. + +2005-07-27 Martin Baulig + + * anonymous.cs (CaptureContext.AddField): Added + `AnonymousContainer am' argument; compute its toplevel scope if + it's not already computed. Fixes #75649. + +2005-07-26 Raja R Harinath + + Fix #75628. + * class.cs (Constructor.Emit): Reset block to null if the block + resolve fails. + +2005-07-25 Marek Safar + + * class.cs (TypeContainer.VerifyMembers): Be compatible in warning 169. + +2005-07-25 Marek Safar + + * class.cs (MethodData.Define): Check whether accessor implementing + interface is public. + + * driver.cs (Driver.parse): Try to be smart and check for `MZ' header. + +2005-07-22 Marek Safar + + Fix #57245 + * namespace.cs (LookupType): Moved same type check to... + + * typemanager.cs (LookupTypeReflection): Don't allow to import more types + with the same name. + +2005-07-21 Raja R Harinath + + * namespace.cs (NamespaceLookupType): Avoid a string allocation when we + already found a typebuilder. + * class.cs (MethodCore.IsDuplicateImplementation): Compare + MemberNames, not strings. + + * const.cs (Error_ExpressionMustBeConst): + Rename from Error_EpressionMustBeConst. + * const.cs, class.cs, statement.cd: Update. + +2005-07-21 Marek Safar + + Fix #65573 + + * const.cs (Const.LookupConstantValue): Report missing contant expression + everytime. + (Error_EpressionMustBeConstant): Only one error method. + + * class.cs, statement.c: Updated. + +2005-07-20 Raja R Harinath + + * statement.cs (Block.Flags): Add back HasVarargs. + (Block.flags): Make protected. + (ToplevelBlock.HasVarargs): Convert to a property that updates flags. + + * typemanager.cs (types, typecontainers, user_types): Remove. + (UserTypes, TypeContainers): Likewise. + (HandleDuplicate, AddDelegateType, AddEnumType): Likewise. + (CleanUp, Reset): Update. + (AddUserType): Combine variants. Now, only updates builder_to_declspace. + (GetNestedType): Use Type.GetNestedType. + (CoreLookupType): Take two arguments, the namespace and the + basename of the type. Update to use the Namespace.Lookup + mechanism. + (InitEnumUnderlyingTypes, InitCoreTypes): Update. + (RealMemberLookup): Use IsNestedChildOf instead of playing with + string concatenation and substring matches. + * class.cs, enum.cs, delegate.cs: Update to changes. + +2005-07-20 Marek Safar + + * constant.cs (Constant.Error_ConstantValueCannotBeConverted): Moved from + Expression and made virtual. + + * convert.cs (ImplicitReferenceConversionExists): Skip for value types. + (ImplicitStandardConversionExists): Fixed `byte' typo ? + + * ecore.cs (Expression.Error_ConstantValueCannotBeConverted): Moved. + + * literal.cs (NullLiteral.Error_ConstantValueCannotBeConverted): Customize + error message. + + * convert.cs, ecore.cs, enum.cs: Reflect Error_ConstantValueCannotBeConverted + change. + +2005-07-18 Marek Safar + + Fix #57707 + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Check whether + AssemblyCultureAttribute is not used on executable. + + * rootcontext.cs, + * typemanager.cs: Add System.Reflection.AssemblyCultureAttribute. + +2005-07-16 Raja R Harinath + + Fix #60638. + * expression.cs (Binary.Warning_UnintendeReferenceComparison): + New. Reports CS0252/CS0253. + Mostly taken from preliminary patch by Duncak Mak. + (Binary.DoResolveOperator): Store results of operator lookup. + Use them to detect if we need to warn about unintended reference + comparisons. + +2005-07-15 Raja R Harinath + + Fix #72969. + * namespace.cs (Namespace.Lookup): Add back location parameter. + (Namespace.LookupType): Add CS0436 report. Add location parameter. + * delegate.cs, ecore.cs, expression.cs: Update to changes. + + * codegen.cs (EmitContext.DeclSpace): Make readonly. + * namespace.cs (Namespace.Lookup): Carve out type lookup into ... + (Namespace.LookupType): ... this. + (NamespaceEntry.GetUsingTable): Allocate only one zero-sized array + of namespaces. + * typemanager.cs (LookupTypeReflection): Remove buggy code that + purported to handle pointers. + (char_ptr_type, void_ptr_type): Use GetPointerType rather than + CoreLookupType. + +2005-07-15 Marek Safar + + * expression.cs (MemberAccess.ResolveNamespaceOrType): Don't report nested + type as namespace. + +2005-07-15 Raja R Harinath + + * namespace.cs (Namespace.Lookup): Drop location parameter. + (NamespaceEntry.LookupAlias): Remove. Merge into ... + (NamespaceEntry.Lookup): ... this. + (NamespaceEntry.Error_AmbiguousTypeReference): + Move here from DeclSpace. + (NamespaceEntry.LookupNamespaceOrType): Move support for dotted + names ... + * ecore.cs (TypeLookupExpression.DoResolveAsTypeStep): ... here. + * decl.cs (DeclSpace.ErrorAmbiguousTypeReference): + Move to NamespaceEntry. + * delegate.cs, expression.cs: Update to changes. + +2005-07-14 Marek Safar + + * attribute.cs (Attribute.ResolveAttributeType): Renamed from + CheckAttributeType and refactored. + (Attribute.ResolvePossibleAttributeType): Changed to reuse + ResolveAsTypeTerminal error handling. + (ResolveAsTypeTerminal): Introduced because of global attributes extra + handling. + (GetSignatureForError): Print errors in same way. + + * class.cs, + * codegen.cs: Reflect attribute GetSignatureForError change. + + * ecore.cs, + * expression.cs: Add silent parameter to ResolveAsTypeStep. + + * namespace.cs (UsingEntry): Refactored to make fields private. + + * assign.cs, + statement.cs: Error_UnexpectedKind has extra parameter. + +2005-07-14 Raja R Harinath + + * ecore.cs (IAlias): Remove. + * decl.cs (DeclSpace): Don't derive from IAlias. Remove members + that implement the interface. + * namespace.cs (Namespace): Likewise. + (Namespace.declspaces): Renamed from 'defined_names'. + (Namespace.AddDeclSpace): Renamed from 'DefineName'. Take a + DeclSpace instead of an IAlias. + * tree.cs (Tree.AddDecl): Update. + +2005-07-12 Raja R Harinath + + * statement.cs (Block.Flags); Remove HasVarargs. + (Block.HasVarargs): Move to ToplevelBlock. + (Block.ThisVariable, Block.AddThisVariable): Likewise. + (Block.Variables): Make protected. Initialize variable hashtable + if necessary. + (Block.AddVariable): Update. + (Block.Resolve): Update to changes. + (ToplevelBlock.HasVarargs): New boolean. + (ToplevelBlock.ThisVariable): Move here from Block. + (ToplevelBlock.AddThisVariable): Likewise. + (ToplevelBlock.IsThisAssigned): New. Forwards call to this_variable. + * expression.cs (This.ResolveBase): Update to changes. + (ArglistAccess.DoResolve): Likewise. + +2005-07-11 Marek Safar + + Fix #75321 + * ecore.cs, class.cs: Use SetAssigned instead of direct access. + + * class.cs (TypeContainer.VerifyMembers): Distinguish between + not used and not used & assigned. + (FieldBase.ASSIGNED): Moved to MemberCore.Flags. + +2005-07-11 Marek Safar + + Fix #75053 + * expression.cs (Is.DoResolve): null is never provided type. + +2005-07-08 Marek Safar + + Fix #52496 + * cs-parser.jay: Less strict event error rule to catch more errors. + +2005-07-08 Martin Baulig + + Fix test-iter-10.cs - distinguish whether we `yield' in a property + gettter (allowed) or setter (not allowed). + + * class.cs (Accessor): Implement IIteratorContainer. + (Accessor.Yields): New public field. + (PropertyBase.PropertyMethod.Define): Handle iterators on a + per-accessor basis. + + * cs-parser.jay + (get_accessor_declaration, set_accessor_declaration): Set the + `yields' flag on the accessor, not the property. + (property_declaration): Do the iterators check on a per-accessor + basis and not for the whole property. + +2005-07-08 Martin Baulig + + * anonymous.cs (CaptureContext.EmitParameterInstance): Correctly + handle parameters in nested scopes; fixes #74808; see gtest-188.cs. + +2005-07-07 Marek Safar + + Fix #74975 + * attribute.cs (orig_sec_assembly): Holds original version of assembly. + (ExtractSecurityPermissionSet): Cope with self referencing security + attributes properly. + + * driver.cs (SetOutputFile): Made public property OutputFile. + +2005-07-07 Raja R Harinath + + Fix #75486. + * class.cs (TypeContainer.first_nonstatic_field): Rename from + has_nonstatic_fields. Make into a FieldBase pointer. + (TypeContainer.AddField): Add CS0282 check. + (TypeContainer.EmitType): Update. + +2005-07-06 Miguel de Icaza + + * cs-tokenizer.cs (consume_identifier): Do not create strings to + compare if they start with __. + +2005-07-06 Raja R Harinath + + * statement.cs (Switch.SwitchGoverningType): Only look at + UserCasts that don't need implicit standard conversions to one of + the allowed switch types (Fixes test-322.cs). + (LocalInfo.Resolve): Re-enable sanity-test. + +2005-07-06 Marek Safar + + * cs-tokenizer.cs (consume_identifier): Detect double undescores + + * ecore.cs (FieldExpr.AddressOf): Changed volatile error to warning. + + * expression.cs (Invocation.DoResolve): Report error CS0245 here. + +2005-07-06 Raja R Harinath + + Fix #75472. + * ecore.cs (SimpleName.GetSignatureForError): Add. + * expression.cs (MemberAccess.DoResolve): Don't clobber 'expr' field. + (MemberAccess.GetSignatureForError): Add. + +2005-07-05 Marek Safar + + The big error and warning messages review. + + * anonymous.cs, + * assign.cs, + * attribute.cs, + * class.cs, + * codegen.cs, + * convert.cs, + * cs-parser.jay, + * cs-tokenizer.cs, + * decl.cs, + * delegate.cs, + * doc.cs, + * driver.cs, + * ecore.cs, + * enum.cs, + * expression.cs, + * flowanalysis.cs, + * iterators.cs, + * literal.cs, + * location.cs, + * modifiers.cs, + * namespace.cs, + * parameter.cs, + * pending.cs, + * report.cs, + * rootcontext.cs, + * statement.cs, + * support.cs, + * tree.cs, + * typemanager.cs: Updated. + + * class.cs: (MethodCore.SetYields): Moved here to share. + (PropertyMethod.Define): Moved iterator setup here. + + * iterators.cs: Add orig_method to have full access to parent + container. + +2005-07-05 Raja R Harinath + + Make 'fixed variable' handling standards compliant. Fix #70807, #72729. + * ecore.cs (IVariable.VerifyFixed): Remove 'is_expression' parameter. + (FieldExpr.VerifyFixed): Ensure that the field is part of a fixed + variable of struct type. + * expression.cs (Unary.ResolveOperator): Update to change. + (Indirection.VerifyFixed): Likewise. + (LocalVariableReference.VerifyFixed): A local variable is always fixed. + (ParameterReference.VerifyFixed): Value parameters are fixed. + (This.VerifyFixed): Treat 'this' as a value parameter. + * statement.cs (LocalInfo.IsFixed): Remove. + +2005-07-01 Martin Baulig + + * iterators.cs (Iterator.CapturedThisReference.Emit): Use + `ec.EmitThis ()' to get the correct scope. + +2005-07-01 Martin Baulig + + * ecore.cs (FieldExpr.DoResolve): Don't capture the field if it's + instance is a ParameterReference; fixes #75299. + +2005-07-01 Martin Baulig + + Reverted Marek's latest patch (r46725): + - it contains structural changes which are neither mentioned in + the ChangeLog nor explained anywhere; for example the additional + argument of EmitContext's and Iterator's .ctor's and the + TypeContainer.DefineMembers() change. + - structural changes like this should go in in seperate patches + and not be hidden in a huge patch which just seems to affect + warnings and errors. + a big and hard to understand patch. + - it breaks iterators and causes regressions, for instance in + test-iter-03.cs. + +2005-06-30 Raja R Harinath + + Fix #75412. + * expression.cs (Indexers.map): Remove. + (Indexers.Append): Filter out inaccessible setters and getters. + (IndexerAccess.DoResolve, IndexerAccess.DoResolveLValue): Update. + + Fix #75283. + * ecore.cs (MemberExpr.EmitInstance): New. Add CS0120 check. + Refactored from ... + (FieldExpr.EmitInstance, PropertyExpr.EmitInstance): ... these. + (FieldExpr.Emit, PropertyExpr.Emit): Update. + (FieldExpr.EmitAssign, PropertyExpr.EmitAssign): Update. + * expression.cs (Invocation.EmitCall): Add CS0120 check. + +2005-06-30 Marek Safar + + Fix #75322 + * class.cs (FieldBase.GetInitializerExpression): One more field + for backup. + +2005-06-28 Miguel de Icaza + + * pending.cs: Do not define a proxy if the base method is virtual, + it will be picked up by the runtime (bug 75270). + +2005-06-08 Martin Baulig + + The big Iterators rewrite :-) + + * iterators.cs: Rewrite this to use the anonymous methods framework. + + * rootcontext.cs (RootContext.DefineTypes): Define Delegates + before the TypeContainers; see 2test-21.cs. + + * class.cs + (TypeContainer.DefineType): Don't create a new EmitContext if we + already have one (this only happens if we're an Iterator). + (TypeContainer.Define): Also call Define() on all our iterators. + (Method.CreateEmitContext): Added support for iterators. + + * anonymous.cs + (AnonymousContainer): New abstract base class for `AnonymousMethod'. + (AnonymousContainer.CreateMethodHost): Moved here from + AnonymousMethod and made abstract. + (AnonymousContainer.CreateScopeType): New abstract method. + (AnonymousContainer.IsIterator): New public property. + (ScopeInfo.EmitScopeType): Call CreateScopeType() on our Host to + get the ScopeTypeBuilder rather than manually defining it here. + (ScopeInfo.EmitScopeInstance): New public method; correctly handle + iterators here. + + * driver.cs (Driver.MainDriver): Call TypeManager.InitCodeHelpers() + before RootContext.DefineTypes(). + + * codegen.cs (EmitContext.RemapToProxy): Removed. + (EmitContext.CurrentAnonymousMethod): Changed type from + AnonymousMethod -> AnonymousContainer. + (EmitContext.ResolveTopBlock): Protect from being called twice. + (EmitContext.MapVariable, RemapParameter(LValue)): Removed. + (EmitContext.EmitThis): Removed the iterators hacks; use the + anonymous methods framework for that. + + * statement.cs + (ToplevelBlock.Container): Make this a property, not a field. + (ToplevelBlock.ReParent): New public method; move the + ToplevelBlock into a new container. + (Foreach.TemporaryVariable): Simplify. + +2005-06-05 Martin Baulig + + * statement.cs (LocalInfo.CompilerGenerated): New flag. + (Block.AddTemporaryVariable): New public method; creates a new + `LocalInfo' for a temporary variable. + (Block.EmitMeta): Create the LocalBuilders for all the temporary + variables here. + (Foreach.TemporaryVariable): Use Block.AddTemporaryVariable() for + non-iterator variables. + +2005-06-05 Martin Baulig + + * statement.cs (Foreach.TemporaryVariable): Create the + LocalBuilder in the Emit phase and not in Resolve since in some + situations, we don't have an ILGenerator during Resolve; see + 2test-19.cs for an example. + +2005-06-04 Martin Baulig + + **** Merged r45395 from GCS **** + + The big Foreach rewrite - Part II. + + * typemanager.cs (TypeManager.object_getcurrent_void): Replaced + with `PropertyInfo ienumerator_getcurrent'. + + * codegen.cs (VariableStorage): Removed. + + * statement.cs + (Foreach): Derive from Statement, not ExceptionStatement. + (Foreach.CollectionForeach): New nested class. Moved all the code + dealing with collection foreach here. + (Foreach.ForeachHelperMethods): Removed. + (Foreach.TemporaryVariable): Implement IMemoryLocation. + +2005-05-23 Martin Baulig + + * statement.cs (Try.DoResolve): Don't create a `finally' if we + don't need to. Fix #75014. + +2005-05-20 Martin Baulig + + Merged r44808 from GMCS. + + * class.cs (TypeContainer.CircularDepException): Removed. + (TypeContainer.DefineType): Removed the `InTransit' stuff. + (TypeContainer.CheckRecursiveDefinition): Check for circular class + (CS0146) and interface (CS0529) dependencies here. + +2005-06-21 Raja R Harinath + + * expression.cs (Invocation.EmitCall): Fix initialization + 'this_call' to reflect current behaviour. Fix indentation. + + * convert.cs (FindMostEncompassedType): Add two trivial special + cases (number_of_types == 0 || number_of_types == 1). + (FindMostEncompasingType): Likewise. + +2005-06-17 Raja R Harinath + + Some cleanups preparing for the fix of #75283. + * ecore.cs (PropertyExpr.InstanceResolve): Tighten conditions for + error testing. + (EventExpr.InstanceResolve): Likewise. + (EventExpr.DoResolve): Remove redundant checks. + +2005-06-10 Duncan Mak + + * cs-tokenizer.cs (process_directives): New flag for controlling + the processing of preprocessor directives. + (x_token): After seeing a '#', return Token.NONE instead of going + to handle_preprocessing_directive() when not processing + directives. This avoids unnecessary processing during the token peek in + is_punct(). + + This fixes #74939. + + * cs-tokenizer.cs (handle_preprocessing_directive, xtoken): Use + the existing error reporting methods instead of Report.Error. + + * convert.cs (priv_fmt_expr): Remove. It's not needed anymore + after Raja's rewrite. + +2005-06-08 Miguel de Icaza + + * class.cs: Small fix. + +2005-06-08 Raja R Harinath + + Fix #75160. + * class.cs (GetPartialBases): Fix return value check of + part.GetClassBases. + +2005-06-07 Raja R Harinath + + Ensure that partial classes are registered in their enclosing + namespace. Initial part of fix of #75160. + * tree.cs (Tree.RecordDecl): Add new namespace argument. + Register declspace with namespace here, not in + DeclSpace.RecordDecl. + * cs-parser.jay: Pass namespace to RecordDecl. + * class.cs (PartialContainer.Create): Likewise. + (ClassPart.DefineType): New sanity-check. Throws an exception if + called. + * decl.cs (Declspace.RecordDecl): Remove. + * namespace.cs (NamespaceEntry.DefineName): Remove. + +2005-06-06 Marek Safar + + * rootcontext.cs: Reset TargetExt as well. + +2005-06-03 Raja R Harinath + + * ecore.cs (Expression.Resolve): Emit CS0654 error when + -langversion:ISO-1. + +2005-06-02 Raja R Harinath + + Fix #75080, cs0119.cs. + * ecore.cs (Expression.ExprClassToResolveFlags): New. Broken out + of ... + (Expression.Resolve): ... this. Use it. Remove bogus code + allowing ExprClass.Type and ExprClass.Namespace for + ResolveFlags.VariableOrValue. + (Expression.Resolve) [1-argument variant]: Change default resolve + flags based on language version. + (Expression.Error_UnexpectedKind): Use a simple string array + rather than an ArrayList. + * expression.cs (TypeOf.DoResolve): Set eclass to ExprClass.Value, + not ExprClass.Type. + (TypeOfVoid.DoResolve): Likewise. + (MemberAccess.DoResolve) [3-argument variant]: Make private. Drop + flags argument -- it always has the same value. + +2005-05-31 Raja R Harinath + + Fix #75081. + * ecore.cs (Expression.ResolveLValue): Add a Location parameter. + Use it in the error message. + * assign.cs, expression.cs, statement.cs: Update. + +2005-05-30 Raja R Harinath + + Fix #75088. + * ecore.cs (Expression.MemberLookupFailed): Add CS0122 check in + the "almostMatchedMember" case too. + * typemanager.cs (Closure.CheckValidFamilyAccess): Add anything + that failed the accessibility checks to 'almost_match'. + +2005-05-27 Vladimir Vukicevic + + * attribute.cs: Use internal MethodBuilder methods to set + ExactSpelling and SetLastError on PInvoke methods, instead + of passing them via charset. Fixes #75060. + +2005-05-27 Raja R Harinath + + * parameter.cs (Parameter): Remove TODO comment. + (Parameter.DefineParameter): Remove Location parameter. + (Parameters.LabelParameters): Likewise. + * class.cs (Constructor.Emit): Update to change. + (MethodData.Emit): Likewise. + * anonymous.cs (AnonymousMethod.EmitMethod): Likewise. + * delegate.cs (Delegate.Define, Delegate.Emit): Likewise. + +2005-05-27 Atsushi Enomoto + + * parameter.cs, + Removed Parameters.Location and added Parameter.Location instead. + Removed Location parameter from Emit() and GetSignature(). + * anonymous.cs, + class.cs, + cs-parser.jay, + delegate.cs, + iterators.cs, + statement.cs : + Modified all related calls. + +2005-05-26 Raja R Harinath + + Improve user-defined conversion handling. + * convert.cs (GetConversionOperators): Rewrite. Return only the + applicable operators. + (AddConversionOperators): New. Helper for GetConversionOperators. + (FindMostEncompassedType, FindMostEncompassingType): Verify that + there is only one most encompassed/encompassing type. + (FindMostSpecificSource, FindMostSpecificTarget): Remove + "applicable operator" handling. + (UserConversion): Move cache here from GetConversionOperators. + Directly cache the chosen operator, rather than the whole + MethodGroup. + (ExplicitNumericConversion): Fix buggy implementation of Decimal + case. Allow conversion of decimal to sbyte and byte too. + * expression.cs (EmptyExpression.Grab, EmptyExpression.Release): + New static methods. Used to avoid allocating EmptyExpressions in + convert.cs. + +2005-05-24 Duncan Mak + + * ecore.cs (CastFromDecimal): New class for casting a decimal to + another class, used in Convert.ExplicitNumericConversion. + (CastToDecimal): New class, similar to above, but casts to + System.Decimal, used in Convert.ImplicitNumericConversion and also + in explicit convesion from double/float to decimal. + + * convert.cs (ImplicitNumericConversion): Handle implicit + conversions to System.Decimal. + (ExplicitNumericConversion): handle explicit conversions to + System.Decimal. + + This fixes #68711. + +2005-05-20 Miguel de Icaza + + * typemanager.cs (EnumToUnderlying): Do not throw if we do not + know the type at this stage, just break through. Fixes #75008 + +2005-05-19 Martin Baulig + + * delegate.cs + (ImplicitDelegateCreation.Check): Added `bool check_only' argument + to disable error reporting. + + * convert.cs (Convert.ImplicitStandardConversionExists): Use it + here since we don't want to report an error; see the new test-336.cs. + +2005-05-19 Raja R Harinath + + * statement.cs (ToplevelBlock.GetParameterReference) + (ToplevelBlock.IsParameterReference,ToplevelBlock.IsLocalParameter): + Move here from class Block. + * ecore.cs (SimpleName.SimpleNameResolve): Update to changes. + * expression.cs (ParameterReference.DoResolveBase): Likewise. + +2005-05-18 Martin Baulig + + Fix #74978. + + * flowanalysis.cs + (FlowBranching.Reachability): Add non-static public And() and Or() + methods. + (FlowBranchingSwitch): New class; do the `break_origins' thing + like in FlowBranchingLoop. + (FlowBranching.UsageVector.MergeBreakOrigins): Also merge the + reachability, not just locals and parameters. + (FlowBranching.MergeChild): Remove some of the hacks for loop and + switch; MergeBreakOrigins() now takes care of that. + +2005-05-18 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a loop and may leave it, reset the barrier; fixes #74974. + +2005-05-17 Marek Safar + + * attribute.cs (Attribute.ResolveArguments): GuidAttribute check + is back. + + * cs-parser.jay: Catch more lexical errors. + + * report.cs: Add one more Error method. + + * rootcontext.cs, + * typemanager.cs: Register System.Runtime.InteropServices.GuidAttribute + +2005-05-17 Martin Baulig + + * expression.cs (Argument.Resolve): Turn on flow analysis; fix + #70970. + +2005-05-16 Raja R Harinath + + Fix test-382.cs. Emit values of decimal constants. + * class.cs (TypeContainer.RegisterFieldForInitialization): New. + Carved out of ... + (TypeContainer.AddField): ... this. + (TypeContainer.EmitFieldInitializers): Allow the list of fields + with initializers to include 'Const's. + (ClassPart.RegisterFieldForInitialization): Forward to + PartialContainer. + * const.cs (Const.Const): Pass initializer to base class. + (Const.Define): In case of decimal constants, register them for + initialization in a static constructor. + +2005-05-14 Martin Baulig + + * statement.cs (Block.Resolve): Correctly handle unreachable code; + do not call ResolveUnreachable() on unreachable statements in + here, see the comment in the source code. + +2005-05-13 Raja R Harinath + + Fix #74934. + * expression.cs (BinaryResolveOperator): If one of the operands of + an equality comparison is 'null' and the other is a pointer type, + convert the null to a NullPointer. + * convert.cs (ImplicitReferenceConversion): If the expression is a + NullLiteral and the target type is a pointer type, return a + NullPointer instead. + (ImplicitConversionStandard): Likewise. + +2005-05-13 Marek Safar + + * cs-parser.jay: Set readonly context based on special constructs. + + * expression.cs (LocalVariableReference.DoResolveBase): Improved + readonly variable error handling. + + * rootcontext.cs (EmitCode): Don't verify members when error + occurred. + + * statement.cs (LocalInfo): Add reaodnly context information. + (SetReadOnlyContext, GetReadOnlyContext): New methods. + +2005-05-13 Raja R Harinath + + * statement.cs (Block.Resolve): Revert change below. Modify fix + for #74041 to initialize 'resolved' to false only for explicit + blocks. Fixes #74873. + +2005-05-12 Raja R Harinath + + Fix #74920. + * typemanager.cs (unmanaged_enclosing_types): New. + (IsUnmanagedType): Avoid infloops by using + 'unmanaged_enclosing_types' to talk with recursive invocations. + +2005-05-13 Martin Baulig + + * statement.cs (Block.Resolve): Make the `bool unresolved' flag an + instance variable, not a local. Fix #74873. + (Block.ResolveUnreachable): Set it to true here. + +2005-05-11 Duncan Mak + + * cs-tokenizer.cs (get_cmd_arg): Check that 'c' is not -1 before + continuing to process for 'arg'. + (handle_preprocessing_directive): Check the argument of the #endif + directive and report error CS1025 if there are any trailing + characters. + + According to the C# spec, having even whitespace after the #endif + directive is illegal; however, because we call arg.TrimEnd () + beforehand, we have the same behavior as csc, allowing whitespace + after the directive. + + Fixes #74892. + +2005-05-11 Marek Safar + + Fix #74863. + + * class.cs (ConstructorInitializer.GetOverloadedConstructor): Removed. + (Constructor.GetObsoleteAttribute): Implemented correctly. + +2005-05-10 Martin Baulig + + * support.cs (ReflectionParameters.ParameterModifier): Use + `Parameter.Modifier.REF' if we both have `ParameterAttributes.Out' + and `ParameterAttributes.In'. Fixes #74884. + +2005-05-10 Marek Safar + + * class.cs (Method.Define): Catch attempt for Finalizer declaration. + + * expression.cs (Argument.GetParameterModifier): Turned to property. + (Invocation.Error_InvalidArguments): Add more descriptive errors. + + * parameter.cs (Parameter.GetModifierSignature): Translates modifier to + its C# equivalent. + +2005-05-09 Raja R Harinath + + Fix #74852. + * decl.cs (MemberCache.AddMethods): Register override methods, + rather than non-override methods. + * typemanager.cs (RegisterOverride): New. + (IsOverride): Update. + +2005-05-09 Marek Safar + + Fix #73105. + + * ecore.cs (SimpleName.SimpleNameResolve): Add in_transit to catch + recursive declaration. + + * statement.cs (Block.ResolveMeta): Report any error in resolving. + +2005-05-06 Marek Safar + + * cfold (DoConstantNumericPromotions): Don't try to convert 0 enum. + + * expression.cs (Binary.DoResolve): (x && 0) is always 0. + +2005-05-05 Raja R Harinath + + Fix #74797. + * decl.cs (DeclSpace.FamilyAccessible): + Use TypeManager.IsNestedFamilyAccessible. + + Fix reopened #64812. + * typemanager.cs (Closure.Filter): Introduce checks for 'protected + internal'. + +2005-05-04 Raja R Harinath + Abin Thomas + Anoob V E + Harilal P R + + Fix #64812. + * typemanager.cs (Closure.CheckValidFamilyAccess): Don't blindly + allow access to all static members. + +2005-05-04 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Always call fb.SetAssigned(). + +2005-05-04 Martin Baulig + + Fix #74655. + + * statement.cs (Switch.SimpleSwitchEmit): Always emit the default + section at the end; make things work if `default' is not the last + section. + +2005-05-04 Martin Baulig + + Fix #70400. + + * statement.cs (Switch): Replaced the `got_default' field with a + `default_section' one. + (Switch.CheckSwitch): Set `default_section' here. + (Switch.Resolve): If we're a constant switch and the constant is + not found, use the default section. + +2005-05-03 Martin Baulig + + * expression.cs (ArrayAccess.EmitGetLength): New public method. + + * statement.cs (Foreach.ArrayForeach): New nested class. + (Foreach.TemporaryVariable): New nested class. + (Foreach.EmitArrayForeach): Removed; this is now in the new + ArrayForeach class. + +2005-05-03 Raja R Harinath + + * pending.cs (BaseImplements): Move the #74773 fix here. This is + more conservative. + (VerifyPendingMethods): Revert change below. + + * typemanager.cs (IsOverride, RegisterNonOverride): New. + * decl.cs (MemberCache.AddMethod): Register "non-override" methods + that used to trigger warning -28. Remove warning -28. + * expression.cs (Invocation.OverloadResolve): Use + TypeManager.IsOverride to distinguish override methods. + + Fix #74773. + * pending.cs (VerifyPendingMethods): If a base type implements the + requested interface, don't bother checking individual methods of + the base type. As a side-effect, this prevents the creation of + unnecessary proxies. + +2005-05-02 Martin Baulig + + Fix #70182. + + * flowanalysis.cs (FlowBranching.UsageVector.MergeJumpOrigins): + Also `And' the locals if the old vector is null. + (FlowBranching.UsageVector.BitVector.And): Allow `vector' being + null; in this case we basically reset all the variables. + +2005-05-02 Martin Baulig + + Fix #74529. + + * flowanalysis.cs (FlowBranching.UsageVector.MergeBreakOrigins): + Added `FlowBranching branching' argument; always `and' the + variables instead of `or'ing them unless we're an infinite loop. + + * statement.cs (While.Resolve): Create a new sibling unless we're + infinite. + +2005-05-02 Martin Baulig + + Fix #70140. + + * class.cs (ConstructorInitializer.Resolve): Added `Block block' + arguments; use it instead of creating a new TopLevelBlock. + (Constructor.Emit): Call `block.ResolveMeta ()' before resolving + our ConstructorInitializer. + + * statement.cs + (TopLevelBlock.TopLevelBranching): New public property. + (TopLevelBlock.ResolveMeta): New public method; call ResolveMeta() + and create our `TopLevelBranching'. + + * codegen.cs (EmitContext.ResolveTopBlock): If we're not an + anonymous method host, use `block.TopLevelBranching' rather than + creating a new branching. + +2005-04-20 Miguel de Icaza + + * anonymous.cs (ScopeInfo.AddChild): when adding a new child to + a ScopeInfo, if any of the current children is a child of the new + entry, move those children there. + +2005-04-30 Martin Baulig + + * statement.cs (Switch.SimpleSwitchEmit): Reset `default_at_end' + at the beginning of a SwitchSection. Fix #73335. + +2005-04-27 Marek Safar + + Fix #74378 + * class.cs (EmitFieldInitializers): Use FieldExpr in initializer. + + * ecore.cs (FieldExpr): Add a new ctor with in_initializer. + (FieldExpr.DoResolve): Obsolete members are ignored for field + initializers. + +2005-04-26 Marek Safar + + * attribute.cs (AreOverloadedMethodParamsClsCompliant): Add array + of arrays detection. + + * class.cs (Interface.VerifyClsCompliance): Add base interfaces + verification. + (Field.VerifyClsCompliance): Volatile fields are not compliant. + + * decl.cs (MemberCache.VerifyClsParameterConflict): Add array of + arrays report. + +2005-04-25 Ben Maurer + + * cs-parser.jay: Use the prefered version of -unsafe in error + message. + +2005-04-22 Marek Safar + + * driver.cs (CompilerCallableEntryPoint.Invoke): Reset under any + circumstances. + +2005-04-20 John Luke + + * driver.cs: fix typo in error message, --outout to --output + +2005-04-20 Marek Safar + + * codegen.cs (InRefOutArgumentResolving): New field. + + * ecore.cs (FieldExpr.DoResolve): Check for assigning to readonly + fields outside contructor. + + * expression.cs (Argument.Resolve): Set InRefOutArgumentResolving. + +2005-04-19 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitParameterInstance): The + parameter code was not completed ever, so it was not as up-to-date + as local variables. Must finish it. + + The bug fix was to compare the Toplevel of the block, not the + current block. Thanks for Ben for pointing this out. + +2005-04-19 Raja R Harinath + + * decl.cs (AddMethods): Use the declaring type of the problem + method to determine if we want to squash a warning. + +2005-04-19 Marek Safar + + * attribute.cs: Removed debug output. + + * decl.cs (MemberCache.AddMethods): Fixed Finalize ignoring. + + * driver.cs (Driver.parse): Synchronize parser ErrorOutput with + Report.Stderr. + +2005-04-18 Raja R Harinath + + Fix #74481. + * expression.cs (Binary.EqualsNullIsReferenceEquals): New. + (Binary.DoResolveOperator): Use it to avoid blindly optimizing out + all null comparisons against reference types. + +2005-04-18 Marek Safar + + Fix# 74565 + * class.cs (TypeContainer.CircularDepException) New nested + exception class. + (GetPartialBases, GetNormalBases, GetClassBases): Removed error. + (TypeContainer.DefineType): Removed error, reset InTransit before + exit. + (Class.DefineType): Throw exception when is in Transit. + Catch exception and report error. + (Struct.DefineType): Throw exception when is in Transit. + Catch exception and report error. + (Interface.DefineType): Throw exception when is in Transit. + Catch exception and report error. + + * codegen.cs: Add InCatch,InFinally to EmitContext to easily + handle nested exception handlers. + + * flowanalysis.cs (InTryWithCatch): New method, search for try with + a catch. + + * iterators.cs (Yield.CheckContext): Add CS1626 report. Updated + InFinally and InCatch storage. + + * statement.cs (Throw.Resolve): Use InCatch, InFinally from ec. + (Catch.Resolve): Set and Restore ec.InCatch. + (Try.Resolve): Set and Restore ec.InFinally. + (Try.HasCatch): True when try has catch. + +2005-04-17 Atsushi Enomoto + + * doc.cs : In some cases FilterName returns MonoEvent and MonoField + for the same event member, so exclude such cases from warning 419. + Fixed bug #74633. + +2005-04-16 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Apply patch from John + Luke to fix bug 59864: operators &, | and ^ on enumerations + require that the same enum type on both sides. + + * driver.cs: Add warnings to old flag usage, this is to assist + people who produce Makefiles and hope that the Makefiles will be + used on Windows. + + * class.cs (TypeContainer.EmitType): Moved the definition of the + special $PRIVATE$ field from the resolve phase to the Emit phase. + During resolve we do not know if we are a struct with + HasExplicitLayout, we know this only after the attributes for the + type are emitted. + + Set the FieldOffset to zero on the dummy field that we create for + the class. Fixes 74590. + +2005-04-16 Raja R Harinath + + Fix #73834. + * ecore.cs (PropertyExpr.resolved): New. + (DoResolve): Use it to handle a case of double resolution here. + Handle a case of identical-name-and-type-name. + * expression.cs (ArrayCreation.CheckIndices): Avoid double + resolution by storing the results of expression resolution back + into the "probes" array. + +2005-04-15 Raja R Harinath + + Fix cs0208-7.cs and cs0208-8.cs. + * typemanager.cs (IsUnmanagedType): Arrays are not allowed + (cf. ECMA standard, behaviour of CSC 1.1 and CSC 2.0). Improve + error reporting to point out the reason a struct is not unmanaged. + +2005-04-13 Atsushi Enomoto + + * doc.cs : In FindDocumentedType(), avoid TypeExpr.ResolveType() and + just use TypeExpr.Type. This fixes bug #74595 when merged to gmcs. + +2005-04-13 Raja R Harinath + + Fix #74528. + * ecore.cs (PropertyExpr.InstanceResolve): Handle a case of + IdenticalNameAndTypeName here. + (EventExpr.InstanceResolve): Likewise. + +2005-04-13 Marek Safar + + C# 2.0 DefaultCharSetAttribute implementation + + * attribute.cs (Attribute.ResolveAsTypeStep): New protected method + which allows us to set GlobalNamespace for every resolve. + (Attribute.ResolveArguments): Cut from Resolve. + (Attribute.GetCharSetValue): Returns CharSet named argument. + (Attribute.DefinePInvokeMethod): Gets default charset from + module settings. + (GlobalAttribute.ResolveAsTypeStep): Override. + (GlobalAttribute.ResolveArguments): Override. + + * class.cs (TypeAttr): Is protected. + + * codegen.cs (ModuleClass.DefaultCharSet): New member. + (ModuleClass.DefaultCharSetType): New memeber. + (ModuleClass.ResolveAttributes): Resolves DefaultCharSetAttribute. + + * decl.cs (Decl.TypeAttr): New protected virtual. Returns default + charset from module. + + * delegate.cs (TypeAttr): Override. + (Delegate.DefineType): Use this TypeAttr. + + * driver.cs (Driver.MainDriver): Call Module.ResolveAttributes + at very early stage (before types are defined) to resolve model + module attributes. It will probably not work with corlib but it + should be ok. + + * enum.cs (Enum.TypeAttr): New protected virtual. Returns default + charset from module. + + * typemanager.cs (default_charset_type): New type. + +2005-04-13 Raja R Harinath + + * decl.cs (MemberCache.AddMethods): Don't warn if + System.Object.Finalize has buggy MethodAttributes. + + * typemanager.cs (IsUnmanagedType): Restore !IsValueType check + removed below. + +2005-04-13 Atsushi Enomoto + + * doc.cs : detect ambiguous reference to overloaded members. + Fixed bug #71603. MS 1.1 csc does not detect it. + +2005-04-13 Atsushi Enomoto + + * doc.cs : delegates must not be referenced with parameters. + Fixed bug #71605. + +2005-04-12 Miguel de Icaza + + * typemanager.cs (IsUnmanagedType): Arrays are allowed. + +2005-04-10 Miguel de Icaza + + * driver.cs (MainDriver): Stop processing if the CLS stage found + errors. + + (CompilerCallableEntryPoint.InvokeCompiler): Always + reset after execution; Take a TextWriter argument for the + output. + + * report.cs: Use the error stream instead of hardcoding stderr. + +2005-04-09 Miguel de Icaza + + * class.cs: Reduce code paths to test, too small of an + optimization to make it worth the extra testing. Always perform + it. + +2005-04-08 Raja R Harinath + + Fix #74510. + * class.cs (OperatorArrayList.CheckPairedOperators): Skip + operators that had errors reported on them. + +2005-04-08 Marek Safar + + * attribute.cs (Attribute.IsValidArgumentType): Test valid named + argument types. + (Attribute.Resolve): Add named argument type checking. + + * class.cs (FixedField.Define): Use IsPrimitiveType + + * expression.cs (Binary.ResolveOperator): Reflect IsCLRType renaming. + + * iterators.cs (Iterator.DefineIterator): Add check for arglist and + unsafe parameter types. + + * statement.cs (Using.ResolveExpression): Add better error description. + + * typemanager.cs (IsCLRType): Renamed to IsPrimitiveType. + +2005-04-08 Raja R Harinath + + Fix #74484. + * attribute.cs (Attribute.GetAttributeUsage): Resolve + AttributeUsageAttribute in the emitcontext of the attribute class, + not in the emitcontext of the attributable entity it was attached to. + * cs-parser.jay: Use 'current_class', not 'current_container', + when creating a GlobalAttribute. + +2005-04-08 Alp Toker + + * pending.cs: The fix to #58413 failed to compile methods implementing + interfaces with/without params modifiers and vice versa, even though + params modifiers aren't part of the signature. Make the modifier check + less strict as in csc. + +2005-04-07 Abin Thomas + Anoob V E + Harilal P R + + Fix #58413. + * pending.cs (TypeAndMethods.mods): New. Store the parameter + modifiers of pending methods. + (PendingImplementation.PendingImplementation): Initialize it. + Add Parameter.Modifier [][] mods and initialize it with ParameterData. + (PendingImplementation.InterFaceMethod): Repalce Type[] argument + with ParameterData. Add check for modifiers. + * class.cs (MethodData.Define): Update to changes. + +2005-04-07 Raja R Harinath + + * ecore.cs (Expression.IsAccessorAccessible): Clarify code somewhat. + +2005-04-07 Marek Safar + + * class.cs (PropertyMethod.Define): Check private accessor in abstract + property. + + * decl.cs (DeclSpace.ApplyAttributeBuilder): Don't allow RequiredAttribute + + * rootcontext.cs, + * typemanager.cs: Registered RequiredAttributeAttribute. + +2005-04-06 Marek Safar + + * class.cs (VerifyMembers): Doesn't need EmitContext argument. + Warning CS0169 is back at level 3. + (IMethodData.SetMemberIsUsed): New method. + + * decl.cs (IsUsed): New value; moved from FieldBase.Status + (SetMemberIsUsed, IsUsed): New methods, encapsulate IsUsed. + + * delegate.cs (ResolveMethodGroupExpr): Call SetMemberIsUsed. + + * ecore.cs (FieldExpr.ResolveMemberAccess): Call SetMemberIsUsed for + contants. + (PropertyExpr.ResolveAccessors): Call SetMemberIsUsed when delegate + is used. + + * expression.cs (OverloadResolve): Call SetMemberIsUsed. when method + is used. + + * rootcontext.cs (RootContext.EmitCode): Call VerifyMembers in extra run + to avoid the problems with nested types. + +2005-04-05 Abin Thomas + Anoob V.E + Harilal P.R + Raja R Harinath + + Fix #73820. + * delegate.cs (Define): Emit ParamArrayAttribute for 'params' + attribute. + * typemanager (GetConstructor): Make public. + +2005-04-05 John Luke + Raja R Harinath + + Fix #62232. + * typemanager.cs (IsUnmanagedType): Check non-public fields of a + struct too. Return false quicker in a few cases. + (VerifyUnManaged): Use it. + +2005-04-05 Raja R Harinath + + Fix #74041. + * statement.cs (Block.Resolve): Initialize 'unreachable' to false, + not 'unreachable_seen'. + +2005-04-04 Marek Safar + + * attribute.cs (Attribute.GetValue): Removed unused. + + * codegen.cs (CodeGen.TrimExt): Removed unused. + + * cs-parser.jay (output): Removed unused. + + * cs-tokenizer.cs (hex_digits): Removed unused. + + * enum.cs (MapToInternalType, GetEnumeratorName): Removed unused. + + * expression.cs (Indirection.LoadExprValue): Removed unused. + (ArrayCreation.ExpressionToArrayArgument): Removed unused. + + * iterators.cs (Iterator.param_types): Removed unused. + + * statement.cs (Goto.block): Removed unused. + (ToplevelBlock.did): Removed unused. + (Switch.ResolveConstantSwitch): Removed unused. + +2005-04-01 Ben Maurer + + * rootcontext.cs: Allow mcs to bootstrap with the compilation + resetting thingy. + +2005-04-01 Raja R Harinath + + Fix #74232 and cs0208-3.cs. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add CS0208 check. + * typemanager.cs (IsUnmanagedType): Don't allow 'object' as an + unmanaged type. Don't use FieldBuilders when 't' is a + TypeBuilder. Use ModFlags and MemberType fields. + * class.cs (MemberBase.member_type): Rename from MemberType. + (MemberBase.MemberType): New property. Determines member_type on + demand. + (MemberBase.DoDefine): Don't initialize MemberType here. + (FieldMember.Define): Likewise. + +2005-04-01 Marek Safar + + Fix #74241 + * class.cs (Event.Emit): Call Add/Remove emit even for interfaces. + Attributes are emitted there. + +2005-04-01 Raja R Harinath + + * cs-tokenizer.cs (consume_identifier): Treat 'partial' as a + keyword in 'partial enum' too. + * cs-parser.jay (enum_declaration): Add CS0267 check ('partial enum' + is not allowed). + Report from Kamil Skalski . + + Fix #74309. + * rootcontext.cs (ResolveTree): The 'root.Interfaces' list can + have partial containers too. + + * ecore.cs (SimpleName.SimpleNameResolve): Move 'invariant meaning + in block' checks to Block.CheckInvariantMeaningInBlock. + * statement.cs (Block.GetKnownVariableInfo): Make private. + (Block.IsVariableUsedInChildBlock): Remove. + (Block.IsVariableUsedInBlock): Likewise. + (Block.CheckInvariantMeaningInBlock): New. Show location of + conflicting declaration. + (Block.AddVariable): Make error messages less long-winded and more + specific. Show location of conflicting declaration. + * parameter.cs (Parameters.Location): New readonly property. + +2005-03-31 Raja R Harinath + + Clean up semantics of invoking ResolveMemberAccess. + * ecore.cs (SimpleName.DoSimpleNameResolve): If a MemberExpression + can have an instance, ensure that we pass in a non-TypeExpression + to ResolveMemberAccess. Tighten up IdenticalNameAndTypeName checks. + (MemberExpr.DoSimpleNameResolve): Remove type_is_inferred + argument. Update to changes and simplify. + (FieldExpr.Emitinstance): Remove CS0120 check. + (PropertyExpr.EmitInstance): Likewise. + * expression.cs (Argument.Resolve): Likewise. + (Invocation.DoResolve): Update to changes in semantics of + InstanceExpression. + +2005-03-31 Marek Safar + + Fix #74241 + * class.cs (AbstractPropertyEventMethod.EmitMethod): Enable emit method + customization. + + * decl.cs (MemberCache.AddMethods): Fix infinite loop. + +2005-03-31 Raja R Harinath + + Fix difference in behaviour with commandline invocation. + * driver.cs (Driver.Reset): New. + (CompilerCallableEntryPoint): Call it. + + * statement.cs (If.Resolve): Avoid spurious "uninitialized + variable" warnings if the boolean expression failed to resolve. + +2005-03-30 Sebastien Pouliot + + * attribute.cs: Fix the union of several permissions when some of them + are unrestricted (so the result isn't an unrestricted permission set). + Fix #74036. + +2005-03-30 Raja R Harinath + + * ecore.cs (MemberExpr): New class. Convert from interface + IMemberExpr. + (MemberExpr.ResolveMemberAccess): Refactor and move here from + MemberAccess.ResolveMemberAccess. Tighten up pre-conditions and + error checks. + (MethodGroupExpr, FieldExpr, PropertyExpr, EventExpr): Update. + (MethodGroupExpr.IsExplicitImpl): Remove. + (Expression.GetFieldFromEvent): Remove. + (SimpleName.MemberStaticCheck): Remove. + (SimpleName.DoSimpleNameResolve): Update to changes. + * expression.cs (MemberAccess.ResolveMemberAccess): Refactor. + (MemberAccess.IdenticalNameAndTypeName): Remove. + (MemberAccess.error176): Move to MemberExpr. + (MemberAccess.DoResolve): Update to changes. + (BaseAccess.DoResolve): Likewise. + +2005-03-30 Marek Safar + + C# 2.0 Conditional attribute class implementation + + * attribute.cs (AttributeTester.IsAttributeExcluded): New method. + Analyzes class whether it has attribute which has ConditionalAttribute + and its condition is not defined. + + * class.cs (Class.ApplyAttributeBuilder): Add IsAttributeExcluded check. + (Class.IsExcluded): New method. Search for at least one defined + condition in ConditionalAttribute of attribute class. + +2005-03-30 Raja R Harinath + + * ecore.cs (PropertyExpr): Derive from Expression, not + ExpressionStatement. + (PropertyExpr.EmitStatement): Remove. + +2005-03-29 Raja R Harinath + + Fix #74060. + * expression.cs (MemberAccess.ResolveMemberAccess): Allow the + internal field "value__" of an enum be private. The examples for + "value__" that I found on MSDN all used FieldAttributes.Private. + + * decl.cs (MemberCache.AddMethods): Use C# terminology in warning. + Don't mention IL method attribute names. + + Fix #47991. Remove a TODO. + * statement.cs (Block.Toplevel): Make into a field. + (Block.Parameters): Move into ToplevelBlock. + (Block.known_variables): Rename from child_variable_names. + (Block.Block): Remove variants that take Parameters. Initialize + 'Toplevel' with the immediately surrounding toplevel block. + (Block.AddKnownVariable): Rename from AddChildVariableName. Add a + LocalInfo parameter. + (Block.GetKnownVariableInfo): New. + (Block.IsVariableNameUsedInChildBlock): Update. + (Block.IsVariableNameUsedInBlock): New. Checks if a name is used in + the block, even though it may not be in scope. + (Block.AddVariable): Remove Parameters parameter. Use + Toplevel.Parameters instead. + (Block.AddConstant): Remove Parameters parameter. + (Block.GetParameterReference): Update to use Toplevel.Parameters. + (Block.IsParamaterReference): Likewise. + (Block.IsLocalParameter): Likewise. Simplify a lot. + (ToplevelBlock.Parameters): New. Moved from Block. + (ToplevelBlock.ToplevelBlock): Update to changes. Always + initialize Parameters to a non-null value. + * cs-parser.jay: Update to changes. + * ecore.cs (SimpleName.SimpleNameResolve): Emit cs0136 error for + simple names that mean different things in the same block. Use + Block.IsVariableNameUsedInBlock. + +2005-03-28 Raja R Harinath + + * typemanager.cs (TypeHandle.BaseType): Make into an IMemberContainer. + (TypeHandle.TypeHandle): Use LookupMemberCache rather than + GetTypeHandle. It is possible for a reflected type to derive from + a TypeBuilder (e.g., int[] derives from the TypeBuilder + System.Array during mscorlib compilation). + * decl.cs (MemberCache.MemberCache): If the base cache doesn't + contain a method_hash, don't create one either. Don't create a + deep copy of the base cache's method_hash. + (MemberCache.SetupCache): Rename back from DeepCopy. + (MemberCache.AddMethods): Rewrite, now that method_hash isn't + already initialized. If we see an override function, add its + underlying base virtual function to the member_hash too. + + * enum.cs (Enum.LookupEnumValue): Remove debugging code. + +2005-03-26 Raja R Harinath + + Fix #73038. + * assign.cs (Assign.DoResolve): When the RHS of an assignment + fails to resolve, ensure that the LHS is still resolved as an + lvalue. + +2005-03-25 Raja R Harinath + + * enum.cs (Enum.DefineType): Set ec.InEnumContext and + ec.ContainerType. + (Enum.current_ec): Remove. + (Enum.LookupEnumValue): Remove EmitContext argument. + Just uses the one created during DefineType. + (Enum.FindMembers): Update. + * expression.cs (MemberAccess.DoResolve): Update. + +2005-03-22 Marek Safar + + * assign.cs (Assign.DoResolve): Check for CS1717 when + source and target are same (uses Equals). + + * expression.cs (LocalVariableReference, ParameterReference, + This): Implemented Equals, GetHashCode. + + * statement.cs (Block.GetParameterReference): Removed useless + local variable. + +2005-03-22 Raja R Harinath + + Fix cs0128.cs + * statement.cs (Block.AddVariable): Ensure that we skip implicit + blocks before deciding whether the error is cs0136 or cs0128. + + * cs-parser.jay: Pass MemberName to RootContext.Tree.RecordDecl. + (using_alias_directive, using_namespace_directive): Pass + MemberName, not an expression to Namespace.UsingAlias and + Namespace.Using. + (MakeName): Use the MemberName of the namespace. + * namespace.cs (Namespace.MemberName): New. + (UsingEntry.UsingEntry): Take a MemberName, not an expression. + (AliasEntry.AliasEntry, Namespace.Using, Namespace.UsingAlias): + Likewise. + * decl.cs (MemberName.Name): Make readonly. + (MemberName.FromDotted): New "constructor". + (MemberName.Equals, MemberName.GetHashCode): Implement overrides. + (MemberCore.Name): Compute from MemberName on demand. + (MemberCore.SetMemberName): Provide a way to change the + MemberName. + (MemberCore.AddToContainer): Don't take a fullname parameter. + * class.cs (TypeContainer.AddToMemberContainer): Don't add the + fully qualified name of the container to the member name. + (TypeContainer.AddToTypeContainer): Use a fully qualified name + only if the type is a member of the root container. + (TypeContainer.AddMethod, TypeContainer.AddProperty): Use + MemberName.Left rather than searching for an embedded ".". + (PartialContainer.CreatePart): Update to changes in RootContext. + (MemberBase.ShortName): Turn into a property. Use + MemberCore.SetMemberName. + (MemberBase.ExplicitInterfaceName): Remove. + (MemberBase.UpdateMemberName): Remove. + (AbstractPropertyEventMethod.UpdateName): Use SetMemberName. + (PropertyBase.SetMemberName): New override. + * tree.cs (Tree.RecordDecl): Take a MemberName and use it as hash key. + (Tree.GetDecl): New. + (Tree.AllDecls): Rename from Decls. + * attribute.cs, enum.cs, report.cs: Update to changes. + * driver.cs (MainDriver): Use MemberName.FromDotted on + RootContext.MainClass. + +2005-03-21 Marek Safar + + * class.cs (FixedField.Define): Check for CS1664 and more sanity + checks. + + * expression.cs (ElementAccess.DoResolveLValue): Check for CS1708. + +2005-03-18 Marek Safar + + * modifiers.cs (Modifiers.PROPERTY_CUSTOM): New constant for + property accessor modifiers. + + * class.cs (FieldMember.ApplyAttributeBuilder): Don't allow apply + fixed buffer attribute (CS1716). + (PropertyMethod.HasCustomAccessModifier): When property accessor + has custom modifier. + + * ecore (PropertyExpr.DoResolve): Add CS0271 for custom accessor + modifiers. + (PropertyExpr.DoResolveLValue): Add CS0272. + +2005-03-17 Miguel de Icaza + + * convert.cs: When converting to a pointer, use the proper Conv.U + or Conv.I depending on the source data type. + + * cs-tokenizer.cs: Make the size for large decimal constants, + fixes #72957. + +2005-03-17 Martin Baulig + + * anonymous.cs (AnonymousMethod.method_modifiers): Change default + from `Modifiers.INTERNAL' to `Modifiers.PRIVATE'. Fixes #73260. + +2005-03-17 Martin Baulig + + * anonymous.cs (AnonymousMethod.EmitMethod): Changed return type + to bool so we can return an error condition. + (AnonymousDelegate.Emit): Check whether AnonymousMethod.EmitMethod() + returned an error. + +2005-03-16 Zoltan Varga + + * attribute.cs: Encode ThrowOnUnmappableChar and BestFitMapping + attributes. + +2005-03-16 Raja R Harinath + + Remove TypeManager.LookupType and TypeManager.LookupTypeDirect. + Refactor to avoid traversing the list of assemblies, and to avoid + string concatenation. + * typemanager.cs (guid_attr_type): Remove. + (negative_hits, pointers, references): Remove hashes. + (type_hash): New. + (GetConstructedType): New. Uses type_hash to handle constructed + types (arrays, references, pointers). + (GetReferenceType, GetPointerType): Use it. + (GetNestedType): New. Uses type_hash to handle nested types of + reflected types. + (LookupType, LookupTypeDirect): Remove. + (CoreLookupType): Inline parts of old LookupTypeDirect code. Use + 'types' hash and LookupTypeReflection directly. + (params_string, params_object): Use GetConstructedType. + * namespace.cs (Namespace.cached_types): New. Cache of reflected + top-level types. + (Namespace.Lookup): Use cached_types. + (NamespaceEntry.LookupNamespaceOrType): Inline the functionality + provided by old TypeManager.LookupType. + * rootcontext.cs (MakeFQN): Remove. + * decl.cs (DeclSpace.MakeFQN): Likewise. + (DeclSpace.LookupType): Use TypeManager.GetNestedType. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Use + TypeManager.GetConstructedType. + * tree.cs (decl_ns_hash, LookupByNamespace): Remove. + +2005-03-15 Marek Safar + + * class.cs (MethodCore.CheckBase): Report CS1715 for properties and + indexers. + + * cs-parser.jay: Reports CS1527 for any namespace element. + + * delegate.cs (DelegateCreation.Error_NoMatchingMethodForDelegate): + Added CS0407. + + * expression.cs (ParameterReference.IsAssigned): Changed error to + CS0269. + (Error_WrongNumArguments): Moved CS0245 detection here. + + * statement.cs (Return.Resolve): Add CS1622 report. + +2005-03-11 Marek Safar + + * class.cs (StaticClass.DefineContainerMembers): Added CS0720. + +2005-03-11 Zoltan Varga + + * attribute.cs expression.cs: Get rid of some allocations. + +2004-03-11 Atsushi Enomoto + + * doc.cs : just eliminate the latest change. + +2004-03-10 Atsushi Enomoto + + * doc.cs : commented out the latest change. It breaks xml-030.cs + +2004-03-10 Atsushi Enomoto + + * doc.cs : When TypeBuilder did not create Type yet, GetEvents() will + fail. So invoke CreateType() in FindDocumentedType(). + +2004-03-10 Atsushi Enomoto + + * cs-tokenizer.cs : added IsKeyword(). + * doc.cs : Detect keyword incorrectly used as identifier. + Allow identifiers prefixed by @. + +2005-03-10 Marek Safar + + * attributes.cs (Attributes.Emit): Continue after CheckTargets. + It caused exception in namespace resolving (again!). + + * class.cs (Class.ctor): Removed exit. + (PropertyMethod.ctor): ditto. + + * codegen.cs (Codegen.Reset): Reset static data. + (Codegen.ResolveTopBlock): Forward error status from ResolveMeta. + + * cs-tokenizer.cs (Cleanup): Removed. + + * driver.cs (GetSystemDir): Rewrote to one line command. + It caused problem with unloaded dynamic modules. + (UnixParseOption): Removed Exit. + (CompilerCallableEntryPoint.InvokeCompiler): Make static. + (CompilerCallableEntryPoint.Reset): Reset suitable static data. + Now can be mcs used as library. + + * ecore.cs (Expression.ResolveBoolean): Use Location.Null for + empty location. + + * location.cs (Reset): Reset static data. + + * namespace.cs (Reset): Reset static data. + + * report.cs (Report.Reset): Reset static data. + + * rootcontext.cs (RootContext.Reset): Reset static data. + + * tree.cs (RootTypes.ctor): Use Location.Null + + * typemanager.cs (TypeManager.Reset): Reset static data. + (CoreLookupType): Removed Exit. + (TypeHandle.Reset): Reset static data. + +2005-03-10 Raja R Harinath + + Fix #73516. + * typemanager.cs (ComputeNamespaces): Import namespaces from + referenced modules too. + +2005-03-09 Raja R Harinath + + * class.cs (TypeContainer.AddToMemberContainer): Use "." rather + than '.'. + +2005-03-09 Raja R Harinath + + * decl.cs (DeclSpace.LookupType): Don't loop but recurse into + enclosing DeclSpace. This ensures that a name-lookup populates + more caches and there are fewer 'TypeExpression's. Carve out + nested type lookup into ... + (LookupNestedTypeInHierarchy): ... this. + +2005-03-09 Raja R Harinath + + Clean up a few partial-class semantics. + Fixes test-357.cs and cs1618-2.cs. + * cs-parser.jay (struct_declaration): Use 'current_class' as + parent of newly-created struct. Remove call to Register (). + Use 'pop_current_class' to complete handing the current struct. + (interface_declaration): Likewise. + (class_declaration): Likewise. + (enum_declaration): Use 'current_class' as parent of newly created + enum. + (delegate_declaration): Likewise. + (pop_current_class): New function. This is used to handle closing + up the 'current_class' and 'current_container', and pointing them + to the enclosing class/container. + (CSharpParser): Initialize 'current_class' too. + * decl.cs (MemberCore): Add check for invariant: a partial + container is not a parsed entity, and thus does not enclose any + parsed members. + (DeclSpace.TypeResolveEmitContext): Expose 'type_resolve_ec'. + (DeclSpace.BaseTypeExpr): Use it. + (DeclSpace.LookupType): Add check for invariant. + * class.cs (TypeContainer): Add check for invariant: a nested + class should have the same NamespaceEntry as its enclosing class. + (TypeContainer.EmitFieldInitializers): Make virtual. + (TypeContainer.DefineDefaultConstructor): Adhere to invariant in + MemberCore. + (TypeContainer.Register): Remove. + (TypeContainer.DefineType): Set the 'ec' of a PartialContainer to + null. Use TypeResolveEmitContext for resolving base types and + interfaces. Move initialization of Parts.TypeBuilder here from + ... + (TypeContainer.DefineNestedTypes): ... here. + (PartialContainer): Take a Namespace not a NamespaceEntry. + (PartialContainer.Create): Don't use Register. Call the + appropriate Add... function directly. + (ClassPart): Take both the PartialContainer and the enclosing + class as constructor arguments. + (ClassPart.EmitFieldInitializers): Override. + (ClassPart.PartFindNestedTypes): Remove. + (FieldBase.GetInitializerExpression): Resolve the initializer + expression in the emit context of the enclosing class. + * tree.cs (RootTypes): Remove Register (). + +2005-03-08 Marek Safar + + * cs-parser.jay: Removed CS0134. + + * driver.cs: Removed CS1901. + + * expression.cs (SizeOf.DoResolve): Don't report CS0233 + for predefined types. + +2005-03-07 Duncan Mak + + * codegen.cs (Save): Catch UnauthorizedAccessException as + well. Fixes bug #73454. + +2005-03-07 Marek Safar + + * cs-tokenizer.cs (xtoken): Add CS1035. + + * class.cs (MethodData.Define): Add CS0683. + (FieldMember.ctor): Add CS0681. + +2005-03-07 Raja R Harinath + + * ecore.cs (SimpleName.DoResolve): Rename from + SimpleName.DoResolveAllowStatic. + (SimpleName.DoSimpleNameResolve): Remove 'allow_static' argument. + Pass 'intermediate' flag to MemberStaticCheck. + (SimpleName.MemberStaticCheck): Skip "static check" only in case + of "intermediate" lookups via MemberAccess. + (SimpleName.IdenticalNameAndTypeName): New. Carved out of ... + * expression.cs (MemberAccess.IdenticalNameAndTypeName): ... this. + +2005-03-07 Raja R Harinath + + Fix #73394. + * ecore.cs (FieldExpr.EmitInstance): Catch cases of CS0120 that + slipped in because of variable names that are identical to a + builtin type's BCL equivalent ('string String;', 'int Int32;'). + (PropertyExpr.EmitInstance): Likewise. + +2005-03-04 Marek Safar + + * cs-tokenizer.cs (PreProcessPragma): Add warning 1633, 1635. + + * report.cs (warning_ignore_table): Made public. + +2005-03-04 Raja R Harinath + + Fix #73282. + * class.cs (MethodData.Emit): Pass 'container' to + container.GetObsoleteAttribute instead of 'container.Parent'. + +2005-03-03 Marek Safar + + * cs-parser.jay: Add 1534 error test. + + * iterators.cs (Yield.CheckContext): Add error 1629. + (Iterator.ctor): Save unsafe modifier. + (MoveNextMethod.DoEmit): Restore unsafe context. + + * namespace.cs (UsingAlias): Better error message. + +2005-03-03 Dan Winship + + * convert.cs (Error_CannotImplicitConversion): fix two bugs in + the warning message [#73219] + +2005-03-03 Raja R Harinath + + Fix compile with MCS 1.0.0.0. + * cs-tokenizer.cs (PreProcessPragma): Simplify w_disable and + w_restore to not depend on string constant folding. + +2005-03-03 Raja R Harinath + + * decl.cs (DeclSpace.LookupType): Remove 'silent' argument. Move + CS0246 check to users who passed 'silent = false'. + * ecore.cs (TypeLookupExpression.DoResolveAsTypeStep): Add CS0246 + check. + (SimpleName.SimpleNameResolve): Update. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add CS0246 check. + (MemberAccess.IdenticalNameAndTypeName): Update. + * doc.cs (FindDocumentedTypeNonArray): Update. + +2005-03-03 Raja R Harinath + + * codegen.cs (EmitContext): Remove ResolvingTypeTree. + * parameters.cs (ComputeAndDefineParameters): Remove. + * decl.cs (ResolveBaseTypeExpr): Don't set ResolvingTypeTree. + * delegate.cs (Define): Don't invoke ComputeAndDefineParameters. + Use GetParameterInfo. + +2005-03-02 Marek Safar + + * report.cs (StaticClass.DefineContainerMembers): Add warning 628. + +2005-03-02 Raja R Harinath + + Unify DeclSpace.LookupType and DeclSpace.FindType. + * decl.cs (DeclSpace.FindNestedType): New virtual function. This + is in charge of defining nested types on demand. + (DeclSpace.LookupType): Use it when the current_type is a + TypeBuilder. Use LookupTypeDirect for reflected types. + (DeclSpace.FindType): Remove. + (DeclSpace.LookupInterfaceOrClass): Likewise. + (DeclSpace.DefineTypeAndParents): Likewise. + * ecore.cs (SimpleName.ResolveAsTypeStep): Just call + DeclSpace.LookupType. + * doc.cs (FindDocumentedTypeNonArray): Use DeclSpace.LookupType. + * typemanager.cs (LookupType): Simplify. + (AddUserType): Remove type from negative_hits. + * namespace.cs (Namespace.Lookup): Use TypeManager.LookupTypeDirect. + * class.cs (TypeContainer.FindMembers): Move handling of nested + types ... + (TypeContainer.FindMembers_NestedTypes): ... here. + (TypeContainer.FindNestedType): Implement override. + (ClassPart.FindNestedType): Delegate to PartialContainer. + (ClassPart.PartFindNestedType): Looks up the nested types of the + part alone. + +2005-03-02 Martin Baulig + + * class.cs (TypeContainer.DoDefineMembers): We also need a default + static constructor in static classes. + +2005-03-01 Zoltan Varga + + * attribute.cs: Pass -1 to DefineLPArrayInternal if sizeConst or + sizeParamIndex is not specified. + +2005-03-01 Marek Safar + + Fix #73117 + * report.cs (WarningMessage.IsEnabled): Missing null check. + +2005-02-28 Marek Safar + + * attribute.cs (DefinePInvokeMethod): Fix, all data are stored + in the fields and not in the properties. + +2005-02-28 Zoltan Varga + + * attribute.cs (GetMarshal): Marshal SizeConst and SizeParamIndex + fields as well. + +2005-02-28 Marek Safar + + * attribute.cs: Small refactoring (improved robustness). + (ImplOptions, UnmanagedType, UsageAttribute): Removed members. + (ValidateGuid): Removed. + (Resolve): Removed referenced to above mentioned. + (GetAttributeUsage): Made private and changed to work without + class assistance. + (GetIndexerAttributeValue): Don't crash. + (GetConditionalAttributeValue): Ditto. + (GetClsCompliantAttributeValue): Ditto. + (ExtractSecurityPermissionSet): All attributes exceptions are + error 648. + (GetPropertyValue): New helper. + (GetMethodImplOptions): New method. + (DefinePInvokeMethod): Reuse common code. Implemented handling of + some missing properties. + + * class.cs (ClassOrStruct.ApplyAttributeBuilder): Updated. + (Method.ApplyAttributeBuilder): Updated. + + * decl.cs (DeclSpace.ApplyAttributeBuilder): Don't catch shared + exception. + +2005-02-28 Raja R Harinath + + Fix #73052. + * report.cs (Report.SymbolRelatedToPreviousError): Handle + non-simple types (array, pointer, reference). + +2005-02-28 Marek Safar + + * cs-parser.jay: Add errors 1617, 650, 1007, 531, 547, 548 + + * class.cs (MethodCore.IsDuplicateImplementation): Special error + for operators. + (Method.CheckBase): Catch wrong destructor here. + (MethodData.Define): Add errors 550, 668. + + * cs-tokenizer.cs (PreProcessPragma): Add warning 1634. + + * ecore.cs (PropertyExpr.DoResolveLValue): Fixed wrong error code. + + * pending.cs (VerifyPendingMethods): Add error 551. + + * typemanager.cs (CSharpName): Next error report helper. + +2005-02-25 Marek Safar + + * attribute.cs (Atttribute.Resolve): Add cache for parameter-less + attributes. Removed useless attribute double check. + It saves almost 2MBs for corlib. + +2005-02-25 Raja R Harinath + + Fix #72924. + * statement.cs (ExpressionStatement.Resolve): Make robust to being + called twice in case of error. + +2005-02-23 Chris Toshok + + Fix compiler portions of #72827. + * statement.cs (Block.Emit): call Begin/EndScope on the + EmitContext instead of the ILGenerator. + + * codegen.cs (EmitContext.BeginScope): new method, call + ILGenerator.BeginScope as well as the SymbolWriter's OpenScope (if + we have one.) + (EmitContext.BeginScope): same, but EndScope and CloseScope + + * symbolwriter.cs (SymbolWriter.OpenScope): get the current il + offset and call the superclass's OpenScope(int) with it. + (SymbolWriter.CloseScope): get the current il + offset and call superclass's CloseScope(int) with it. + +2005-02-23 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Fixed to report + CS1677 for out and ref as well. + + * class.cs (Method.Define): Add error CS1599 detection. + + * cs-parser.jay: Add CS1609, CS1670, CS1627 detection. + + * cs-tokenizer.cs (xtoken): Add error CS1646 detection. + + * delegate.cs (Delegate.Define): Add error CS1599 detection. + + * support.cs.cs (ModifierDesc): New helper method. + +2005-02-23 Raja R Harinath + Abin Thomas + Anoob V E + Harilal P R + + Fix #57851, #72718. + * class.cs (ConstructorBuilder.Resolve): Make sure that the second + MemberLookup (used for error reporting) actually returns a result. + Fix error report number (122, not 112). + +2005-02-22 Abin Thomas + Anoob V E + Harilal P R + + Fix #71134. + * pending.cs (PendingImplementation.GetAbstractMethods): + Find NonPublic members too. + +2005-02-22 Marek Safar + + * expression.cs.cs (ConditionalLogicalOperator.DoResolve): + Fixed error 217. + + * class.cs (MethodCore.CheckMethodAgainstBase): + Add error 239 report. + +2005-02-21 Raja R Harinath + + Fix #68955. + * expression.cs (Invocation.IsApplicable): Make public. + (Invocation.IsParamsMethodApplicable): Likewise. + * delegate.cs (Delegate.VerifyApplicability): Don't use + Invocation.VerifyArgumentCompat for parameter applicability + testing. Use Invocation.IsApplicable and + Invocation.IsParamsMethodApplicable. + +2005-02-21 Marek Safar + + * ecore.cs (PropertyExpr.DoResolve): Add error 214 report. + + * class.cs (Operator.Define): Add error 217 report. + +2005-02-21 Raja R Harinath + + * namespace.cs (UsingEntry.Resolve): Undo change below. + +2005-02-21 Raja R Harinath + + Fix #72756. + * ecore.cs (Expression.MemberLookupFailed): Add argument to + disable the error message when the extended MemberLookup also + fails. + (Expression.MemberLookupFinal): Update. + (SimpleName.DoSimpleNameResolve): Update. + * expression.cs (MemberAccess.ResolveNamespaceOrType): + Don't use MemberLookupFinal. + (New.DoResolve): Update. + (BaseAccess.CommonResolve): Update. + +2005-02-21 Raja R Harinath + + Fix #72732. + * attribute.cs (Attribute.ResolveType): If a 'resolve_error' had + occured previously, don't resolve again. + +2005-02-21 Marek Safar + + Fix #69949 + * attribute.cs (Attribute.GetAttributeUsage): Add EmitContext + argument. Call ResolveAttributeUsage for unresolved. + when types doesn't match ctor arguments. + + * class.cs (DoDefineMembers.TypeContainer): Removed safety check + for nested attribute classes. + (Class.attribute_usage): Removed. + (Class.ResolveAttributeUsage): Resolves AttributeUsageAttribute + for attribute class. + + * ecore.cs (IsAttribute): Removed. + + * namespace.cs (UsingEntry.Resolve): Don't destroy NamespaceEntry. + + * rootcontext.cs (RegisterAttribute): Removed, attributes are + now normal types. + (attribute_types): Removed. + (EmitCode): Global attributes are emited as the latest. + +2005-02-18 Marek Safar + + * class.cs (EmitFieldInitializers): Don't emit field initializer + for default values when optimilization is on. + + * constant.cs (Constant.IsDefaultValue): New property. + + * driver.cs: Add /optimize handling. + + * constant.cs, + * ecore.cs, + * literal.cs: Implement new IsDefaultValue property. + + * rootcontext.cs (Optimize): New field, holds /optimize option. + +2005-02-18 Raja R Harinath + + Fix crasher in re-opened #72347. + * namespace.cs (Namespace.Lookup): Return null if + DeclSpace.DefineType returns null. + + Fix #72678. + * expression.cs (Argument.Resolve): Handle a case of CS0120 here. + +2005-02-18 Raja R Harinath + + Fix remainder of #63202. Change semantics of DoResolveLValue: it + now returns null if it cannot resolve to an lvalue. + * ecore.cs (Expression.DoResolveLValue): Return 'null' by default. + (Expression.ResolveLValue): Emit CS0131 error if DoResolveLValue + returned null. Remove check for SimpleName. + (EventExpr.DoResolveLValue): New. + * iterators.cs (Iterator.FieldExpression.DoResolveLValue): New. + * expression.cs (Argument.Error_LValueRequired): New. Move CS1510 + error from ... + (Argument.Resolve): ... here. Use it. Use DoResolveLValue to + avoid CS0131 error. + (Unary.ResolveOperator): Move CS0211 check ... + (Unary.DoResolve): ... here. Use DoResolveLValue to avoid + CS0131 error. + (Unary.DoResolveLValue): Simplify. + (AddressOf.DoResolveLValue): New. + (ArrayAccess.DoResolveLValue): New. + +2005-02-16 Marek Safar + + * attribute.cs (Attribute.Resolve): Add arguments casting for + when types doesn't match ctor arguments. + +2005-02-16 Raja R Harinath + + Fix parts of #63202. + * expression.cs (UnaryMutator.ResolveOperator): Remove redundant + lookup of operator in base type. Ensure that all checks happen + when the operator resolves to an "op_..." method. + +2005-02-15 Raja R Harinath + + Fix #71992. + * namespace.cs (NamespaceEntry.LookupNamespaceOrType): Add + 'ignore_cs0104' parameter. Pass it to ... + (NamespaceEntry.Lookup): ... this. + * decl.cs (DeclSpace.LookupType): Add 'ignore_cs0104' parameter. + * ecore.cs (SimpleName.ResolveAsTypeStep): Update. + (TypeLookupExpression.DoResolveAsTypeStep): Update. + * expression.cs (MemberAccess.IdenticalNameAndTypeName): + Update. Request that cs0104 errors be ignored. + (ComposedCast.ResolveAsTypeStep): Update. + +2005-02-14 Raja R Harinath + + Fix #59209. + * expression.cs (Invocation.BetterFunction): Remove support for + comparing virtual functions and their overrides. + (Invocation.IsOverride): New. + (Invocation.OverloadResolve): Don't consider 'override' functions + during candidate selection. Store them in a lookaside list. + If the selected method is a 'virtual' function, use the list to + find any overrides that are closer to the LHS type. + +2005-02-14 Marek Safar + + * expression.cs (New.DoResolve): Add complex core type reduction. + (New.Constantify): Converts complex core type syntax like 'new int ()' + to simple constant. + +2005-02-14 Raja R Harinath + + * decl.cs (EntryType.EntryType): New constructor to create an + updated copy of a cache entry. + (MemberCache.AddMethods): Use it. + (MemberCache.ClearDeclaredOnly): Remove. + (MemberCache.MemberCache): Update. + +2005-02-11 Miguel de Icaza + + * codegen.cs (EmitContext): Introduce the `MethodIsStatic' + variable. This one is represents the actual low-level declaration + of the method, as opposed to the semantic level `IsStatic'. + + An anonymous method which is hosted into a static method might be + actually an instance method. IsStatic would reflect the + container, while MethodIsStatic represents the actual code + generated. + + * expression.cs (ParameterReference): Use the new MethodIsStatic + instead of IsStatic. + + * anonymous.cs (AnonymousMethod.Compatible): Pass the + Modifiers.STATIC to the Anonymous' Method EmitContext if static is + set on the current EmitContext. + + * expression.cs (Cast): Overload DoResolveLValue so we can pass + resolve our casted expression as an LValue. This triggers the + proper LValue processing that is later required by Assign. + + This fixes 72347. + + * cs-tokenizer.cs (pp_and): recurse on pp_and, fixes #61903. + +2005-02-11 Marek Safar + + C# 2.0 Fixed buffer implementation + + * anonymous.cs: Update after RegisterHelperClass renaming. + + * attribute.cs (AttributeTester.fixed_buffer_cache): + Cache of external fixed buffers. + (AttributeTester.GetFixedBuffer): Returns IFixedBuffer + implementation if field is fixed buffer else null. + + * class.cs + (TypeContainer.AddField): Accept FieldMember instead of Field. + (FieldBase.IsFieldClsCompliant): Extracted code from + VerifyClsCompliance descendant customization. + (FixedField): New class handles fixed buffer fields. + (FixedFieldExternal): Keeps information about imported fixed + buffer. + (IFixedField): Make access to internal or external fixed buffer + same. + + * cs-parser.jay: Add fixed buffer parsing. + + * ecore.cs (FieldExpr.Emit): Add special emit case for fixed + buffer. + + * expression.cs (Indirection): Extended implementation to accept + fixed buffer field. + (PointerArithmetic.Emit): Get element from fixed buffer as well. + (ElementAccess.MakePointerAccess): Get type as parameter. + (DoResolve): Add fixed buffer field expression conversion. + (DoResolveLValue): Ditto. + (FixedBufferPtr): New class. Moved most of original ArrayPtr. + (ArrayPtr): Derives from FixedBufferPtr. + (ArrayPtr.Emit): Add extra emit for array elements. + + * flowanalysis.cs.cs (StructInfo): Use FieldMember. + + * rootcontext.cs (CloseTypes): Emit CompilerGenerated attribute + for compiler generated types. + (RegisterCompilerGeneratedType): Renamed from RegisterHelperClass. + + * statement.cs (Fixed): Refactored to be easier add fixed buffer + and consume less memory. + (Fixed.Resolve): Add fixed buffer case. + + * typemanager.cs (compiler_generated_attr_ctor, + fixed_buffer_attr_ctor): Add new 2.0 compiler attributes. + (HasElementType): Add our own implementation to work on every + runtime. + +2005-02-11 Miguel de Icaza + + * anonymous.cs (CaptureContext): Track whether `this' has been + referenced. + + * expression.cs (This.ResolveBase): Call CaptureThis. Before we + only captured `this' if it was implicitly done (instance + methods/variables were used). + + * codegen.cs (EmitContext.CaptureThis): New method to flag that + `this' must be captured. + +2005-01-30 Miguel de Icaza + + * anonymous.cs (CreateMethodHost): If there Scope.ScopeTypeBuilder + is null it means that there has been no need to capture anything, + so we just create a sibling. + + Renamed `EmitHelperClasses' to `EmitAnonymousHelperClasses' + + Just a partial fix. The other half is fairly elusive. + +2005-02-10 Raja R Harinath + + Fix #52586, cs0121-4.cs. + * decl.cs (MemberCache.DeepCopy): Rename from SetupCache. Take + and return a hashtable. + (MemberCache.ClearDeclaredOnly): New. + (MemberCache.MemberCache): Update to change. Make a deep copy of + the method_hash of a base type too. + (MemberCache.AddMethods): Adapt to having a deep copy of the base + type methods. Overwrite entries with the same MethodHandle so + that the ReflectedType is correct. The process leaves in base + virtual functions and their overrides as distinct entries. + (CacheEntry): Now a class instead of a struct. It shouldn't alter + matters since it was boxed in a ArrayList before. + (CacheEntry.Member, CacheEntry.EntryType): Remove 'readonly' + modifier. + * expression.cs (Invocation.BetterFunction): Simplify. Handle the + case of a virtual function and its override (choose the overload + as better). + (Invocation.OverloadResolve): Avoid 'override' members during + 'applicable_type' calculation. + +2005-02-09 Raja R Harinath + + Combine two near-redundant caches. + * typemanager.cs (method_params): Rename from method_internal_params. + (TypeManager.GetParameterData): New. Replace + Invocation.GetParameterData. + (TypeManager.LookupParametersByBuilder): Remove. + * expression.cs (Invocation.method_parameter_cache): Remove. + (Invocation.GetParameterData): Remove. + Update to changes. + * anonymous.cs, attribute.cs, convert.cs, delegate.cs: + Update to changes. + +2005-02-08 Raja R Harinath + + Fix #72015. + * delegate.cs (Delegate.DefineType): When bootstrapping corlib, if + TypeManager.multicast_delegate_type is null, resolve it by looking + up "System.MulticastDelegate". + * rootcontext.cs (RootContext.ResolveCore): Simplify. + +2005-02-07 Abin Thomas (NOSIP) + Anoob V.E (NOSIP) + Harilal P.R (NOSIP) + + Fix cs0164.cs. + * statement.cs (LabeledStatement.Resolve): Don't set 'referenced'. + (LabeledStatement.AddReference): New. Set 'referenced'. + (Goto.Resolve): Use it. + +2005-02-05 John Luke + + * driver.cs: remove duplicate -doc line in Usage () + +2005-02-04 Raja R Harinath + + * location.cs (Location.AddFile): Fix CS2002 error report. + +2005-02-02 Martin Baulig + + * delegate.cs (Delegate.DefineType): Report an internal error if + TypeManager.multicast_delegate_type is null. See bug #72015 for + details. + +2005-02-02 Raja R Harinath + + Fix a crasher in a variant of #31984. + * const.cs (Constant.CheckBase): New override that defers the + new-or-override check in case the base type hasn't been populated + yet. + (Constant.Define): Ensure the new-or-override check is performed. + +2005-02-01 Duncan Mak + + * const.cs (LookupConstantValue): Check that `ce' is not null + before calling GetValue (). + +2005-02-01 Raja R Harinath + + Fix test-334.cs (#69519). + * cs-parser.jay (using_alias_directive): Pass in an expression to + NamespaceEntry.UsingAlias. + (using_namespace_directive): Pass in an expression to + NamespaceEntry.Using. + (namespace_name): Don't flatten to a string. + * namespace.cs (NamespaceEntry.AliasEntry): Store an expression. + (NamespaceEntry.AliasEntry.Resolve): Lookup using + ResolveAsTypeStep. + (NamespaceEntry.UsingEntry): Likewise. + (NamespaceEntry.Using,NamespaceEntry.UsingAlias): Update to + changes. + (NamespaceEntry.LookupForUsing): Remove. + (NamespaceEntry.LookupNamespaceOrType): Add support for dotted + names. + (NamespaceEntry.Lookup): Remove support for dotted names. + +2005-02-01 Raja R Harinath + + * namespace.cs (NamespaceEntry.NamespaceEntry): Simplify, and + split into two. + (NamespaceEntry.ImplicitParent): Compute on demand. + (NamespaceEntry.Doppelganger): New implicit namespace-entry that + parallels the current. + (NamespaceEntry.LookupForUsing): Use it. + (NamespaceEntry.Lookup): If the current namespace-entry is + implicit, don't search aliases and using tables. + +2005-02-01 Raja R Harinath + + Fix #31984. + * class.cs (TypeContainer.DoDefineMembers): Don't initialize + BaseCache here. + (TypeContainer.BaseCache): Compute on demand. + (TypeContainer.FindMembers): Define constants and types if they're + not already created. + (FieldMember.Define): Move resetting of ec.InUnsafe before error + check. + * const.cs (Constant.Define): Make idempotent. + +2005-01-29 Miguel de Icaza + + * pending.cs: Produce better code (no nops produced by using Ldarg + + value). + + * pending.cs (PendingImplementation.DefineProxy): It was not `arg + i - 1' it should be arg + 1. + + Fixes bug #71819. + +2005-01-28 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Make private + non-virtual. + (Attribute.ResolveType): Make virtual. + (GlobalAttribute.ResolveType,GlobalAttribute.Resolve): Simplify + handling of RootContext.Tree.Types. + +2005-01-27 Raja R Harinath + + Update attribute-handling to use the SimpleName/MemberAccess + mechanisms. + * cs-parser.jay (attribute): Pass in an expression to the + constructors of Attribute and GlobalAttribute. + * attribute.cs (Attribute): Take an expression for the name. + (Attribute.ResolvePossibleAttributeTypes): New. Resolves the + passed in attribute name expression. + (Attribute.CheckAttributeType): Use it. + * ecore.cs (FullNamedExpression.ResolveAsTypeStep): New. + * expression.cs (MemberAccess.ResolveAsTypeStep): Move body to ... + (MemberAccess.ResolveNamespaceOrType): ... here. Add 'silent' + argument to prevent error messages if the lookup fails. + +2005-01-27 Marek Safar + + * expression.cs (Indirection): Implemented IVariable interface + to support indirection in AddressOf operator. + (PointerArithmetic.Emit): Add optimalization for case where + result can be precomputed. + +2005-01-26 Martin Baulig + + * class.cs (TypeContainer.AttributeTargets): Return the correct + AttributeTargets depending on our `Kind' instead of throwing an + exception; fixes #71632. + +2005-01-26 Marek Safar + + Fix #71257 + * expression.cs (MemberAccess.ResolveMemberAccess): Add CS0176 test for + constant members. + +2005-01-25 Raja R Harinath + + Fix #71602. + * expression.cs (MemberAccess.DoResolve): Don't complain with + cs0572 when the LHS of a member access has identical name and type + name. + +2005-01-25 Marek Safar + + Fix #71651, #71675 + * attribute.cs (ExtractSecurityPermissionSet): Catch exceptions from + CreatePermission. + Create custom PermissionSet only for PermissionSetAttribute. + +2005-01-24 Marek Safar + + Fix #71649 + * class.cs (StaticClass.DefineContainerMembers): Enable enums and + delegates in static class. + +2005-01-24 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + merging an implicit block, just use its reachability. + + * statement.cs (Block.Resolve): Make the unreachable code check + work wrt. implicit blocks; see test-337 from #63842. + +2005-01-21 Alp Toker + + * cs-parser.jay: destructor_declaration's container is PartialContainer + not Class when partial types are used, so use Kind prop instead of + 'is'. + +2005-01-22 Miguel de Icaza + + * cs-parser.jay: Improve error reporting when an interface + declares new types. + +2005-01-20 Dick Porter + + * support.cs: SeekableStreamReader fix from Sandor Dobos + (dobos_s@ibcnet.hu) to cope with Position setting when multibyte + chars are read. Fixes bug 70369. + +2005-01-20 Raja R Harinath + + * cs-parser.jay (catch_clause): Simplify current_block handling + somewhat. + +2005-01-17 Miguel de Icaza + + * convert.cs (ImplicitStandardConversionExists): Synchronize the + code with ImplicitStandardConversion to handle the implicit + conversion of method groups into valid delegate invocations. + + The problem is that in parameter handling we were using this code + path. Fixes bug #64698 + +2005-01-19 Raja R Harinath + + * cs-parser.jay: Fix several infelicities. + - Avoid assigning to the parser value stack. Code like + '$3 = null' is unclean. Synthesize a value for the code block + instead. + - Avoid using oob_stack for storing location information. Use ... + (_mark_): ... this. New (empty) rule. Saves the current location + in $$. + (foreach_statement): Avoid using oob_stack for current_block + handling. Use technique used in for_statement and + using_statement. Synthesize a value for the code block to store + additional intermediate information. + +2005-01-13 Miguel de Icaza + + * ecore.cs (IsAccessorAccessible): Accessibility to private fields + of a different type is only allowed to private fields of a + containing type, not on fields of a base class. + + See test-174.cs and error cs0122-9.cs + +2005-01-13 Raja R Harinath + + Fix test-335.cs (bug #58126). + * cs-parser.jay (argument): Split out non-expression parts of the + rule into 'non_simple_argument'. + (invocation_expression): Support parenthesized invocations with + multiple arguments, and with single non-simple arguments. + +2005-01-13 Raja R Harinath + + * cs-tokenizer.cs (xtoken): Reset 'comments_seen' in a couple more + places. + +2005-01-12 Raja R Harinath + + Fix cs0038-1.cs, cs1640-6.cs. + * ecore.cs (Expression.Resolve): Remove special-case for + SimpleName in error-handling. + (Expression.almostMatchedMembers): Relax access permission to + protected. + (Expression.MemberLookupFailed): Handle duplicates in + almostMatchedMembers list. + (SimpleName.DoSimpleNameResolve): Catch CS0038 errors earlier. + * expression.cs (New.DoResolve): Report CS1540 for more cases. + * typemanager.cs (GetFullNameSignature): Use the MethodBase + overload if the passed in MemberInfo is a MethodBase. + +2005-01-12 Marek Safar + + Fix #70749 + * attribute.cs (ExtractSecurityPermissionSet): Don't report error + for non-CAS & merge permission sets properly. + +2005-01-11 Raja R Harinath + + Improve standard-compliance of simple name and member access + resolution. Fixes bugs #52697, #57200, #67520, #69519. + * ecore.cs (FullNamedExpression): New abstract base class + for Namespaces and TypeExpressions. + (ResolveFlags.SimpleName): Remove. + (SimpleName): Remove support for dotted names. + (SimpleName.ResolveAsTypeStep): Simplify. Now just a wrapper to + DeclSpace.FindType and DeclSpace.LookupType. + (SimpleName.DoSimpleNameResolve): Remove support for dotted names. + (Expression.ExprClassName): Make member function. + * expression.cs (MemberAccess.ResolveAsTypeStep): Support LHS being + a namespace. Remove creation of dotted "SimpleName"s. + (MemberAccess.DoResolve): Likewise. + * decl.cs (DeclSpace.Cache): Make private. + (DeclSpace.LookupInterfaceOrClass): Return a FullNamedExpression. + (DeclSpace.FindType): Update. + (DeclSpace.LookupType): Move here from RootContext. Return a + FullNamedExpression. + * namespace.cs (Namespace): Derive from FullNamedExpression + so that it can be part of expression resolution. + (Namespace.Lookup): Return an FullNamedExpression. + (NamespaceEntry.LookupAlias): Lookup aliases only in current + namespace. + * rootcontext.cs (NamespaceLookup): Remove. + (LookupType): Move to DeclSpace. + * attribute.cs (CheckAttributeType): Update. + * doc.cs (FindDocumentedType): Remove allowAlias argument. + (FindDocumentedTypeNonArray): Likewise. + +2005-01-11 Raja R Harinath + + Fix cs0509.cs, cs1632.cs. + * class.cs (TypeContainer.GetNormalBases): Don't assume !IsClass + is the same as IsInterface. + (TypeContainer.GetClassBases): Likewise. + * statement.cs (LabeledStatement.ig): New field. + (LabeledStatement.LabelTarget): Save ILGenerator which created the + label. + (LabeledStatement.DoEmit): Check that the label was created with + the same ILGenerator. + +2005-01-10 Marek Safar + + Fix #71058 + * attribute.cs (GetMethodObsoleteAttribute): Need to transform + accessors to its properties. + + * ecore.cs (PropertyExpr): Add AccessorTable to help track back + from accessors to property. + +2005-01-10 Marek Safar + + Fix #70722 + * class.cs (MethodCore.CheckBase): Test base method obsoleteness + only for overrides. + +2005-01-08 Miguel de Icaza + + * attribute.cs: Check for null and empty strings. + + I have lost another battle to Paolo. + +2005-01-07 Marek Safar + + Fix #70942 + * class.cs (PropertyMethod): Set Parent field in ctors. + (SetMethod.InternalParameters): Add unsafe switch hack. + Override MarkForDuplicationCheck where it is appropriate. + + * decl.cs (MemberCore.MarkForDuplicationCheck): New method. + It says whether container allows members with the same name. + Base default is no. + (DeclSpace.AddToContainer): Use MarkForDuplicationCheck. + Removed is_method parameter. + +2005-01-06 Duncan Mak + + * cs-tokenizer.cs (xtoken): Redo the work for signaling CS1040 + because the previous change led to incorrect reporting of CS1032 + ("Cannot define/undefine preprocessor symbols after first token in + file"). Instead of using `tokens_seen' as the only flag that + triggers CS1040, introduce `comments_seen'. This new flag is used + to signify having seen comments on the current line, so it is + unset after a newline. + +2005-01-06 Atsushi Enomoto + + * doc.cs : When searching for a type, find nested type too. + This fixes bug #71040. + +2005-01-06 Atsushi Enomoto + + * doc.cs : + - Warn missing member comment on those classes which also does not + have doc comments. Fixed bug #71041. + - Don't warn missing doc comment on default constructor. + Fixed bug #71042. + +2005-01-06 Duncan Mak + + * cs-tokenizer.cs (xtoken): After handling traditional C-style + comments, set `tokens_seen' to true. This allows us to detect + misplaced preprocessor directives (i.e. not at the beginning of + the a line, nor after whitespaces). In that case, report error + CS1040. This fixes bug #56460. + + * cs-parser.jay (interface_member_declaration): Add checks for + IsExplicitImpl, and report CS0541 error if an interface member is + defined as an explicit interface declaration. + +2005-01-06 Marek Safar + + Fix #70817 + * class.cs (PropertyMethod): Set Parent field in ctors. + (SetMethod.InternalParameters): Add unsafe switch hack. + + * decl.cs (MemberCore.Parent): Cannot be readonly. + +2005-01-06 Raja R Harinath + + * decl.cs (DeclSpace.ResolveType): Remove. + (DeclSpace.ResolveBaseTypeExpr): Rename from ResolveTypeExpr. + Merge in code from ... + (DeclSpace.GetTypeResolvingEmitContext): ... here. Remove. + * class.cs, enum.cs: Update to changes. + +2005-01-06 Miguel de Icaza + + * anonymous.cs: Ensure that we init the scope of our parent if it + has not been initialized yet. + +2004-12-30 Duncan Mak + + * typemanager.cs (TypeManager.CheckStructCycles): Don't crash here + if field.FieldBuilder is null. Fixes #70758. + + * convert.cs: Fixed some typos and updated some of the comments. + (ImplicitStandardConversionExists): + (TryImplicitIntConversion): If `target_type' is an interface and + the type of `ic' implements this interface, return true or a new + BoxedCast instead of null. This fixes #70468. + +2004-12-29 Duncan Mak + + * expression.cs (Argument.Emit): Check that Expr is + IMemoryLocation before casting to it, and report CS1510 otherwise. + + This fixes #70402. + +2004-12-21 Ben Maurer + + * statement.cs (Block.ThisVariable): remove the recursion here, to + make the --profile more sane. + +2004-12-17 Carlos Cortez + + * driver.cs: Patch to handle a xsp bug that prevents to reference an .exe + assembly, by JB Evain. + +2004-12-17 Raja R Harinath + + * class.cs, decl.cs, ecore.cs, iterators.cs, pending.cs, + rootcontext.cs, typemanager.cs: Make nomenclature consistent. + "parent" refers to enclosing type/class. "base" refers to superclass. + +2004-12-17 Raja R Harinath + + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Ensure that we only have GlobalAttributes. + * attribute.cs (Attribute.Emit): Make non-virtual. + (GlobalAttribute.Emit): Remove. + (Attribute.Resolve): Make virtual. + (GlobalAttribute.Resolve): New. Set Rootcontext.Tree.Types.NamespaceEntry. + (Attribute.GetConditionalAttributeValue): Take an EmitContext as + the argument. Don't create one. + (Attribute.GetObsoleteAttribute): Likewise. + (Attribute.GetClsCompliantAttributeValue): Likewise. + * class.cs, decl.cs: Update to changes. + +2004-12-17 Marek Safar + + * delegate.cs (NewDelegate.DoResolve): Add error 149 report. + + * ecore.cs (Expression.MemberLookupFailed): Fixed error 143. + + * statement.cs (Foreach.Resolve): Add error 186 report. + +2004-12-16 Marek Safar + + * expression.cs (Conditional.DoResolve): Add warning 429. + + * statement.cs (If.Resolve): Add warning 665. + +2004-12-16 Raja R Harinath + + New invariant: RootContext.Tree.Types.NamespaceEntry == null + except when in the parser, and in GlobalAttribute. + * driver.cs (MainDriver): Reset RootContext.Tree.Types.NamespaceEntry. + * attribute.cs (GlobalAttribute.CheckAttributeType): Reset + RootContext.Tree.Types.NamespaceEntry once work is done. + (GlobalAttribute.Emit): New. Wrapper for Attribute.Emit, but sets + and resets RootContext.Tree.Types.NamespaceEntry. + +2004-12-15 Marek Safar + + * cs-parser.jay: Don't create a block for every variable. + +2004-12-14 Miguel de Icaza + + * location.cs: Provide extra information. + + * statement.cs: The instance is not `ldarg_0.THIS' when accessing + variables from the captured environment, it is the ldarg_0. + +2004-12-14 Marek Safar + + * cs-parser.jay: Changed warning level for 642 to 4 until Miguel + find a conclusion. + + * class.cs: Changed warning level for 169 to avoid developer + displeasure from warning flooding. It will be changed back when they + fix most of current BCL warnings. + + * RootContext.cs: Pushed default WarningLevel to 3. + + * statement.cs: Removed unused variable. + +2004-12-14 Marek Safar + + * class.cs (TypeContainer.GetClassBases): Add error 1521 report. + (TypeContainer.MethodModifiersValid): Refactored to use MemberCore. + Add error 502 report. + (StaticClass.DefineType): Add error 441 report. + (Class.AllowedModifiersProp): New virtual property as temporary + extension to AllowedModifiers. + (Class.DefineType): Add error 418 report. Moved ModFlags check here + to share implementation with StaticClass and don't call virtual + methods from ctor. + + * driver.cs (MainDriver): Add error 1558 test. + + * parameter.cs (Parameter.ApplyAttributeBuilder): Add error 662 + report. Moved error 36 test here. + + * statement.cs (Throw.Resolve): Add error 724 report. + + * typemanager.cs: Add out_attribute_type core type. + +2004-12-13 Marek Safar + + * class.cs (TypeContainer.VerifyClsCompliance): Add error + 3018 report. + (PropertyBase.VerifyClsCompliance): Add errror 3025 report. + + * codegen.cs (ModuleClass.ApplyAttributeBuilder): Add error + 3017 report. + + * decl.cs (MemberCore.VerifyClsCompliance): Add warning 3021. + + * parameter.cs (ReturnParameter.ApplyAttributeBuilder): + Add error 3023 report. + (Parameter.ApplyAttributeBuilder): Add error 3022 report. + + * tree.cs (RootTypes.IsClsCompliaceRequired): Add fake + implementation. + +2004-12-12 John Luke + + * driver.cs (AddArgs): take -- into account when + adding arguments, fixes bug 65710 + +2004-12-12 Martin Baulig + + * expression.cs (Unary.TryReduceNegative): Added support for + SByteConstant and ByteConstant. + (Unary.Reduce): Check error values from TryReduceNegative(). + +2004-12-10 Marek Safar + + * attributes.cs (Attribute.Resolve): Avoid multiple error report + and report exception as error 182. + +2004-12-10 Raja R Harinath + + * driver.cs (Main): Fix message when there are warnings. + +2004-12-09 Miguel de Icaza + + * delegate.cs: Fixed my fix from yesterday, sorry about that. + +2004-12-09 Marek Safar + + * anonymous.cs, class.cs, convert.cs, doc.cs, support.cs: + Reduced number of warnings. + + * class.cs (TypeContainer.VerifyClsCompliance): One if is enough. + +2004-12-08 Miguel de Icaza + + * driver.cs: Removed message. + + * delegate.cs: Fix bug introduced in 1.1.x: 70219. + +2004-12-08 + + * cs-tokenizer.cs: Add workaround for NET 2.0 beta 1 csc bug. + +2004-12-08 Martin Baulig + + * class.cs (TypeContainer.VerifyClsCompliance): Report a CS3003 + instead of a CS3002 for properties and indexer. + +2004-12-08 Martin Baulig + + * decl.cs (MemberName.ToString): Make this work again. + +2004-12-08 Marek Safar + + * attribute.cs (Resolve): Add error 591 detection. + + * class.cs (FieldMember.Define): Add error 1547 detection. + (Indexer.Define): Add error 620 detection. + (Operator.Define): Add error 590 detection. + + * ecore.cs: Missing argument for error 79. + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add error 611 + detection. + +2004-12-07 Marek Safar + + Fix #70106 + * assign.cs.cs (Assign.DoResolve): Reports error 1648 for value types + only. + +2004-12-07 Atsushi Enomoto + + * cs-parser.jay : handle doc comments on implicit/explicit operators. + Some operator comments were suppressed. + * doc.cs : Implicit/explicit operator name in doc comments are like + "op_Explicit(type)~returnType", so added suffix handling. + +2004-12-07 Martin Baulig + + * decl.cs + (MemberCore.GetObsoleteAttribute): Don't create a new EmitContext. + (MemberCore.GetClsCompliantAttributeValue): Likewise. + (DeclSpace.ec): New protected field; store the EmitContext here. + (DeclSpace.EmitContext): New public property; moved here from + `TypeContainer'. + (DeclSpace.GetClsCompliantAttributeValue): Don't create a new + EmitContext. + + * enum.cs (Enum.Define): Store the EmitContext in the `ec' field. + (Enum.Emit): Don't create a new EmitContext. + + * delegate.cs (Delegate.DefineType): Always create the + EmitContext. + + * iterators.cs (Iterators.DefineIterator): Create a new + EmitContext and store it in `ec'. + +2004-08-24 Martin Baulig + + * typemanager.cs + (TypeManager.IsSubclassOf): Renamed to IsFamilyAccessible; use + this for accessibility checks. + (TypeManager.IsSubclassOrNestedChildOf): Renamed to + IsNestedFamilyAccessible. + (TypeManager.IsSubclassOf): New method, do what the name actually + says. + +2004-12-06 Raja R Harinath + + Fix crash on cs0657-17.cs. + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Use RootContext.Tree.Types, not 'new RootTypes ()'. + * attribute.cs (GlobalAttribute.CheckAttributeType): Narrow down + the case where the NamespaceEntry gets overwritten. + +2004-12-06 Marek Safar + + Fixed #69195, #56821 + * ecore.cs (ResolveBoolean): Tiny refactoring. + + * expression.cs (Binary.DoResolve): Add warning 429 and skipping + of right expression resolving when left is false constant and + operator is LogicalAnd OR true constant and operator is LogicalOr. + + * statement.cs (ResolveUnreachable): Always reports warning. + +2004-12-05 Miguel de Icaza + + * class.cs: Distinguish between 1721 and 1722 (just a little help + for the programmer). + +2004-12-03 Miguel de Icaza + + * delegate.cs: Only allow this on new versions of the language. + +2004-12-02 Duncan Mak + + * ecore.cs (PropertyExpr.IsAccessorAccessible): Moved to + Expression class. + (Expression.IsAccessorAccessible): Moved from the PropertyExpr to + here as a static method. Take an additional bool out parameter + `must_do_cs1540_check' for signaling to InstanceResolve. + (PropertyExpr.InstanceResolve): Removed the `must_do_cs1540_check' + member field from PropertyExpr class and made it an argument of + the method instead. + (EventExpr.InstanceResolve): Copied from PropertyExpr, removed the + check for MarshalByRefObject, and report CS0122 instead of CS1540. + (EventExpr.DoResolve): Call IsAccessorAccessible on `add_accessor' + and `remove_accessor' as well as InstanceResolve: report CS0122 + where applicable. + + Fixes #70129. + +2004-12-03 Raja R Harinath + + Fix test-327.cs, test-328.cs, and put in early infrastructure + for eventually fixing #52697. + * namespace.cs (NamespaceEntry.LookupForUsing): New method. + (NamespaceEntry.LookupNamespaceOrType): New method, refactored + from other methods. + (NamespaceEntry.Lookup): Remove 'ignore_using' flag. + (AliasEntry.Resolve, UsingEntry.Resolve): Use 'LookupForUsing'. + (VerifyUsing, error246): Update. + * rootcontext.cs (RootContext.NamespaceLookup): Just use + 'NamespaceEntry.LookupNamespaceOrType'. + +2004-12-03 Martin Baulig + + * delegate.cs (NewDelegate.DoResolve): If we have an anonymous + method as our child, call AnonymousMethod.Compatible() on it. + +2004-12-03 Raja R Harinath + + Disable XML documentation support in 'basic' profile. + * decl.cs, class.cs [BOOTSTRAP_WITH_OLDLIB]: Don't import System.Xml. + Redirect XmlElement to System.Object. + * driver.cs, enum.cs, rootcontext.cs: Don't reference System.Xml. + * doc.cs [BOOTSTRAP_WITH_OLDLIB]: Disable compile. + * mcs.exe.sources: Add doc-bootstrap.cs. + * doc-bootstrap.cs: New file. Contains empty stub implementation + of doc.cs. + +2004-12-03 Atsushi Enomoto + + * cs-tokenizer.cs : Only '////' is rejected. Other non-whitespace + comments are allowed. + +2004-12-03 Carlos Alberto Cortez + + * delegate.cs: Add checks for subtypes in paramaters and return values + in VerifyMethod () to add support for Covariance/Contravariance + in delegates. + +2004-12-02 Miguel de Icaza + + * report.cs: Remove extra closing parenthesis. + + * convert.cs (Error_CannotImplicitConversion): If the name of the + types are the same, provide some extra information. + + * class.cs (FieldBase): Use an unused bit field from the field to + encode the `has_offset' property from the FieldMember. This saves + a couple of Ks on bootstrap compilation. + + * delegate.cs (NewDelegate.DoResolve): If we have an anonymous + method as our child, return the AnonymousMethod resolved + expression. + + * expression.cs (New.DoResolve): Allow return values from + NewDelegate to also include AnonymousMethods. + + Fixes #70150. + +2004-12-02 Marek Safar + + Fix bug #70102 + * attribute.cs (Resolve): Improved implementation of params + attribute arguments. + + * support.cs (ParameterData): Add HasParams to be faster. + +2004-12-02 Atsushi Enomoto + + all things are for /doc support: + + * doc.cs: new file that supports XML documentation generation. + * mcs.exe.sources: added doc.cs. + * driver.cs: + Handle /doc command line option. + Report error 2006 instead of 5 for missing file name for /doc. + Generate XML documentation when required, after type resolution. + * cs-tokenizer.cs: + Added support for picking up documentation (/// and /** ... */), + including a new XmlCommentState enumeration. + * cs-parser.jay: + Added lines to fill Documentation element for field, constant, + property, indexer, method, constructor, destructor, operator, event + and class, struct, interface, delegate, enum. + Added lines to warn incorrect comment. + * rootcontext.cs : + Added Documentation field (passed only when /doc was specified). + * decl.cs: + Added DocComment, DocCommentHeader, GenerateDocComment() and + OnGenerateDocComment() and some supporting private members for + /doc feature to MemberCore. + * class.cs: + Added GenerateDocComment() on TypeContainer, MethodCore and Operator. + * delegate.cs: + Added overriden DocCommentHeader. + * enum.cs: + Added overriden DocCommentHeader and GenerateDocComment(). + +2004-12-01 Miguel de Icaza + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): After + unwrapping the enumeration values, chain to + DoConstantNumericPromotions again, so we can promote things to the + fundamental types (takes care of enums that are bytes, sbytes). + + Fixes bug #62054. + +2004-12-01 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Remove complain flag. + Fix long-standing bug in type-lookup. Use FindType instead of + LookupType when ec.ResolvingTypeTree. + (Attribute.ResolveType, Attribute.Resolve) + (Attribute.DefinePInvokeMethod,GlobalAttribute.CheckAttributeType): + Update to changes. + (Attributes.Search): Remove internal version. Update. + (Attributes.SearchMulti): Update. + (Attributes.GetClsCompliantAttribute): Remove. + (Attributes.GetIndexerNameAttribute): Remove. + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Update to changes. + (DeclSpace.GetClsCompliantAttributeValue): Likewise. + * class.cs (Indexer.Define): Likewise. + +2004-12-01 Marek Safar + + Fix bug #68790 + * ecore.cs: CheckMarshallByRefAccess new virtual method for testing + MarshallByReference members access. + + * expression.cs: Use CheckMarshallByRefAccess; + Better error CS0197 message. + + * report.cs: Print whole related error message. + +2004-11-30 Raja R Harinath + + * Makefile (mcs.exe) [PROFILE=default]: Keep a copy of mcs.exe in + the current directory to help debugging. + +2004-11-29 Marek Safar + + * class (GetClassBases): Better error 60 report. + (EventProperty): Disabled warning 67 detection. + +2004-11-29 Marek Safar + + Fix bug #60324 + * cfold.cs (Assign.DoResolve): Add subtraction for DecimalConstant. + + * constant.cs (DecimalConstant.Emit): Don't use int ctor for + precise values. + +2004-11-29 Marek Safar + + Fix bug #49488 + * assign.cs (Assign.DoResolve): Add error 1648, 1650 report. + + * decl.cs (MemberCore.MemberName): Error 1648 in compiler. + +2004-11-26 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Refine error reporting and + report a cs0117 if the identifier does not exist, to distinguish + from 0617 which is a miss-use of the actual identifier. + + * ecore.cs (EventExpr.Emit): Refine error report and distinguish + between cs0070 and cs0079. + + * class.cs (MemberBase.DoDefine): When reporting a wrong + accessibility level, we use MethodCore to compare instead of + Method (this was a regression in some refactoring effort). + + So now we correctly report cs0056 again. + + * convert.cs (ImplicitReferenceConversion): Corrected typo, I was + testing the target_type (which was known to be object_type) and + not the source type (which is anonymous_method). + + Fixed reporting of error cs1660. + + * expression.cs (UserCast.Source): Expose the underlying cast. + + * statement.cs (Switch.SwitchGoverningType): Sort the list of + allowed types to find a match to int32 first (most common). + + In addition, it ignores any ImplicitUserConversions that did an + internal implicit conversion (as the switch statement allows only + one integral conversion to exist). + + * class.cs (PartialContainer.Create): rename `name' to + `member_name' for clarity. Then replace the string calls with a + call to MemberName.GetPartialName, as now using + MemberName.ToString is an error (this is due to the side effects + it had, that were fixed in the past). + + This will restore the error reporting on a number of partial class + errors that were missusing this (and getting an exception as a + results, which is now just a plain textual warning, because + yyparse debug output would crash otherwise). + +2004-11-26 Raja R Harinath + + * Makefile (PROGRAM_INSTALL_DIR): Remove. + +2004-11-25 Ben Maurer + + * rootcontext.cs (LookupType): Make sure to cache lookups that + don't give us a negative result. This saves about 5% of corlib + compilation time. + +2004-11-25 Miguel de Icaza + + * report.cs (AbstractMessage.Print): messages are sent to stderr + + * class.cs (TypeContainer.GetClassBases): It is an error to have a + non-interface in the list of interfaces (at this point, either + parent was properly set, or a base class is being listed in the + interfaces section). + + This flags error 1722, and resolves the crash from bug 69259. + +2004-11-25 Ben Maurer + + * statement.cs (Using.EmitExpressionFinally): make this work right + for valuetypes. Fixes 69926. + +2004-11-25 Miguel de Icaza + + * const.cs (Const.ChangeType): Cope with the "0 literal can be + converted to an enum" here, before we try to change the underlying + type. This code exists, but it is a different code path than the + one used while encoding constants. + + * convert.cs (ImplicitReferenceConversionExists): A surprisingly + old bug: when converting from the null literal to a pointer, + return an EmptyCast, not the NullLiteral. + + This fixes #69921, the recent null_type changes probably made this + bug more prominent. + + (ImplicitReferenceConversionExists): In addition, resynchronized + the code here, so it matches the same code in + ImplicitReferenceConversionExists for the `from any class-type S + to any interface-type T'. + + +2004-11-25 Marek Safar + + * cfold.cs (BinaryFold): Add addition for DecimalConstant. + +2004-11-24 Miguel de Icaza + + * cs-parser.jay: Use verbosity accordingly. + +2004-11-24 Marek Safar + + * expression.cs (Unary.ResolveOperator): Do not report warning; + AddressOf reads from variable. + + (LocalVariableReferences.DoResolveBase): Improved my previous fix. + +2004-11-24 Marek Safar + + Fix bug #69462 + + * attribute.cs (Attributable): Removed CheckTargets. + (Attributes.Emit): Explicit attribute targets are tested here. + + * class.cs (EventField.ValidAttributeTargets): Explicit target "field" is + not enabled for interfaces. + + * codegen.cs (CommonAssemblyModulClass.AddAttributes): Removed CheckTargets. + (GetAssemblyName): Ouch next bug there. + +2004-11-23 Carlos Alberto Cortez + + * expression.cs: Error 275 added. + +2004-11-23 Marek Safar + + Fix bug #69177 (Implemented decimal constant support) + + * cfold.cs (DoConstantNumericPromotions: Add DecimalConstant. + (BinaryFold): Add DecimalConstant. + + * const.cs (Define): Decimal constant + (is not constant. + (ChangeType): Add decimal type handling. + (LookupConstantValue): Don't set value for decimal type but + emit DecimalConstantAttribute. Needed for constant optimization. + + * constant.cs (ToDecimal): New method. + (ConvertToDecimal): New method. + (IntConstant): Implemented ConvertToDecimal. + (DecimalConstant.Emit): Emit optimized version for decimals in + int range. + + * expression.cs (ResolveOperator): Changed order of constant + reduction to work correctly with native types which have + overloaded operators. + (ResolveMemberAccess): Extract constant value from attribute + for decimal type. + + * rootcontext.cs (ResolveCore): Add DecimalConstantAttribute. + + * typemanager.cs (TypeManager): Add decimal_constant_attribute_type, + void_decimal_ctor_int_arg, decimal_constant_attribute_ctor. + (ChangeType): Decimal is special. + (TypeToCoreType): Add decimal type. + +2004-11-22 Marek Safar + + * convert.cs (ImplicitConversionRequired): Add error cs0642 for + decimal types. + +2004-11-22 Marek Safar + + * class.cs (EventField.ApplyAttributeBuilder): Fix error + test cs1667-5.cs. + +2004-11-19 Marek Safar + + * class.cs (MemberBase.DoDefine): Fix error cs0508 report. + + * pending.cs (PendingImplementation): Grab only interfaces. + +2004-11-19 Marek Safar + + * statement.cs (ForeachHelperMethods): Add location member and + error 202 detection. + +2004-11-19 Raja R Harinath + + * Makefile (EXTRA_DISTFILES): Remove mcs.exe.config. It's + automatically handled by executable.make. + (PROGRAM): Make profile-specific. + +2004-11-18 Marek Safar + + * expression.cs (DoResolveBase): Fixed wrong warning for out + variables. + +2004-11-18 Martin Baulig + + Merged latest changes into gmcs. Please keep this comment in + here, it makes it easier for me to see what changed in MCS since + the last time I merged. + +2004-11-17 Raja R Harinath + + * typemanager.cs (TypeHandle.GetTypeHandle): Make private. + (TypeHandle.GetMemberCache): New. + (TypeHandle.TypeHandle): Update. + (TypeManager.LookupMemberCache): Rewritten from LookupMemberContainer. + (TypeManager.LookupParentInterfacesCache): + Rename from LookupInterfaceCache. Optimize slightly. + (TypeManager.MemberLookup_FindMembers): Update. + * decl.cs (MemberCache.MemberCache): Set Container to null in the + multi-type variant. + (AddCacheContents): Rename from AddHashtable. + * class.cs (TypeContainer.parent_container): Remove. + (TypeContainer.VerifyClsCompliance): Don't use parent_container. + (TypeContainer.DoDefineMembers): Don't initialize it. + Update to name changes. + +2004-11-17 Miguel de Icaza + + * class.cs (MethodCore.CheckAccessModifiers): New helper routine + that factors the code to check access modifiers on override. + + (PropertyBase): Use the code here. + + Patch from Lluis S'anchez, fixes bug #69361. + +2004-11-15 Miguel de Icaza + + * anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New + routine that is used to report the use of a captured variable + whose address has been taken. + + There are two checks: one when variables are being captured and + the other check is when the address of a variable is taken. + + (because an anonymous methods might be resolved before *or* after + the address has been taken) and + + * expression.cs (Conditional.DoResolve): Remove the special + casing that Martin added to trueExpr and falseExpr being both + NullLiteral. We get the right behavior now just by introducing + the null_type into the compiler. + + * convert.cs (ExplicitConversion): Change the code to use + null_type instead of testing `expr is NullLiteral'. + (ImplicitConversionStandard): use null_type too. + (ImplicitReferenceConversionExists): use null_type too. + (ImplicitReferenceConversion): use null_type too. + + * literal.cs: The type of `NullLiteral' is now null_type instead + of object_type. + (Resolve): Set the type here. + + * typemanager.cs: Introduce null_type. + +2004-11-17 Martin Baulig + + * decl.cs (MemberCache.AddHashtable): Add entries in the opposite + direction, like FindMembers() does. Fixes #69546, testcase is in + test-315.cs. + +2004-11-16 Martin Baulig + + This is based on a patch from Marek Safar, see bug #69082. + Fixes bugs #63705 and #67130. + + * typemanager.cs (TypeManager.LookupInterfaceCache): New public + method; create a MemberCache for an interface type and cache the + result. + + * decl.cs (IMemberContainer.ParentContainer): Removed. + (IMemberContainer.ParentCache): New property. + (MemberCache.SetupCacheForInterface): Removed. + (MemberCache..ctor): Added .ctor which takes a `Type[]'; use this + to create a cache for an interface's "parent". + + * class.cs (TypeContainer.DoDefineMembers): Setup cache for + interfaces too. + +2004-11-16 Martin Baulig + + Merged back from gmcs; these changes already went into gmcs a + couple of weeks ago. + + * typemanager.cs + (TypeManager.AddUserType): Removed the `ifaces' argument. + (TypeManager.RegisterBuilder): Take a `Type []' instead of a + `TypeExpr []'. + (TypeManager.AddUserInterface): Removed. + (TypeManager.ExpandInterfaces): Return a `Type []' instead of a + `TypeExpr []'. + (TypeManager.GetInterfaces): Likewise. + (TypeManager.GetExplicitInterfaces): Likewise. + + * ecore.cs (TypeExpr.GetInterfaces): Removed. + + * class.cs (TypeContainer.base_class_type): Replaced with `ptype'. + (TypeContainer.base_inteface_types): Replaced with `ifaces'. + +2004-11-14 Ben Maurer + + * statement.cs: Avoid adding bools to a hashtable. + +2004-11-07 Miguel de Icaza + + * expression.cs (Invocation.OverloadResolve): Flag error if we are + calling an unsafe method from a safe location. + +2004-11-06 Marek Safar + + Fix #69167 + * codegen.cs (ApplyAttributeBuilder): Do not return; it is only warning. + +2004-11-06 Miguel de Icaza + + * namespace.cs (VerifyUsing): use GetPartialName instead of + ToString. + +2004-11-05 Miguel de Icaza + + * statement.cs (Return.Resolve): Fix regression in typo: if + `in_exc', we have to request a NeedReturnLabel, this was a typo + introduced in the anonymous method check-in. Fixes #69131. + + * Indexers were using the ShortName when defining themselves, + causing a regression in the compiler bootstrap when applying the + patch from 2004-11-02 (first part), now they use their full name + and the bug is gone. + +2004-11-04 Zoltan Varga + + * driver.cs: Strip the path from the names of embedded resources. Fixes + #68519. + +2004-11-04 Raja R Harinath + + Fix error message regression: cs0104-2.cs. + * namespace.cs (NamespaceEntry.Lookup): Remove 'silent' flag. + (AliasEntry.Resolve): Update. + * rootcontext.cs (RootContext.NamespaceLookup): Update. Remove + 'silent' flag. + (RootContext.LookupType): Update. + +2004-11-03 Carlos Alberto Cortez + + * cs-parser.jay: Add support for handling accessor modifiers + * class: Add support port accessor modifiers and error checking, + define PropertyMethod.Define as virtual (not abstract anymore) + * ecore.cs: Add checking for proeprties access with access modifiers + * iterators.cs: Modify Accessor constructor call based in the modified + constructor +2004-11-02 Ben Maurer + + * expression.cs (StringConcat): Handle being called twice, + as when we have a concat in a field init with more than two + ctors in the class + +2004-11-02 Miguel de Icaza + + * class.cs (Event.Define, Indexer.Define, Property.Define): Do not + special case explicit implementations, we should always produce + the .property or .event declaration. + + * decl.cs (MemberName): Renamed GetFullName to GetPartialName + since it will not return correct data if people use this + unresolved in the presence of using statements (see test-313). + + * class.cs (MethodData.Define): If we are an explicit interface + implementation, set the method name to the full name of the + interface plus the name of the method. + + Notice that using the method.MethodName.GetFullName() does not + work, as it will only contain the name as declared on the source + file (it can be a shorthand in the presence of using statements) + and not the fully qualifed type name, for example: + + using System; + + class D : ICloneable { + object ICloneable.Clone () { + } + } + + Would produce a method called `ICloneable.Clone' instead of + `System.ICloneable.Clone'. + + * namespace.cs (Alias.Resolve): Use GetPartialName. + +2004-11-01 Marek Safar + + * cs-parser.jay: Add error 1055 report. + +2004-11-01 Miguel de Icaza + + * assign.cs (Assign.DoResolve): Only do the transform of + assignment into a New if the types are compatible, if not, fall + through and let the implicit code deal with the errors and with + the necessary conversions. + +2004-11-01 Marek Safar + + * cs-parser.jay: Add error 1031 report. + + * cs-tokenizer.cs: Add location for error 1038. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add error 1016 report. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add errors 1575,1611 report. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add error 1001 report. + +2004-10-31 Marek Safar + + Fix #68850 + * attribute.cs (GetMarshal): Add method argument for + caller identification. + + * class.cs, codegen.cs, enum.cs, parameter.cs: Added + agument for GetMarshal and RuntimeMissingSupport. + +2004-10-31 Marek Safar + + * attribute.cs (ExtractSecurityPermissionSet): Removed + TypeManager.code_access_permission_type. + + * typemanager.cs: Removed TypeManager.code_access_permission_type. + +2004-10-27 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolveLValue): Check + for obsolete use of a variable here. Fixes regression on errors + cs0619-25 and cs0619-26. + +2004-10-27 Marek Safar + + Fix #62358, implemented security attribute encoding. + + * attribute.cs (Attribute.CheckSecurityActionValididy): New method. + Tests permitted SecurityAction for assembly or other types. + (Assembly.ExtractSecurityPermissionSet): New method. Transforms + data from SecurityPermissionAttribute to PermisionSet class. + + * class.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Added + special handling for System.Security.Permissions.SecurityAttribute + based types. + + * enum.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * parameter.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * rootcontext.cs: Next 2 core types. + + * typemanager.cs (TypeManager.security_permission_attr_type): + Built in type for the SecurityPermission Attribute. + (code_access_permission_type): Build in type. + +2004-10-17 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolveBase, Emit): + Remove the tests for `ec.RemapToProxy' from here, and encapsulate + all of this information into + EmitContext.EmitCapturedVariableInstance. + + * codegen.cs (EmitCapturedVariableInstance): move here the + funcionality of emitting an ldarg.0 in the presence of a + remapping. This centralizes the instance emit code. + + (EmitContext.EmitThis): If the ScopeInfo contains a THIS field, + then emit a load of this: it means that we have reached the + topmost ScopeInfo: the one that contains the pointer to the + instance of the class hosting the anonymous method. + + * anonymous.cs (AddField, HaveCapturedFields): Propagate field + captures to the topmost CaptureContext. + +2004-10-12 Miguel de Icaza + + * expression.cs (LocalVariableReference): Move the knowledge about + the iterators into codegen's EmitCapturedVariableInstance. + +2004-10-11 Miguel de Icaza + + * codegen.cs (EmitContext.ResolveTopBlock): Emit a 1643 when not + all code paths return a value from an anonymous method (it is the + same as the 161 error, but for anonymous methods). + +2004-10-08 Miguel de Icaza + + The introduction of anonymous methods in the compiler changed + various ways of doing things in the compiler. The most + significant one is the hard split between the resolution phase + and the emission phases of the compiler. + + For instance, routines that referenced local variables no + longer can safely create temporary variables during the + resolution phase: they must do so from the emission phase, + since the variable might have been "captured", hence access to + it can not be done with the local-variable operations from the runtime. + + * statement.cs + + (Block.Flags): New flag `IsTopLevel' to indicate that this block + is a toplevel block. + + (ToplevelBlock): A new kind of Block, these are the blocks that + are created by the parser for all toplevel method bodies. These + include methods, accessors and anonymous methods. + + These contain some extra information not found in regular blocks: + A pointer to an optional CaptureContext (for tracking captured + local variables and parameters). A pointer to the parent + ToplevelBlock. + + (Return.Resolve): Catch missmatches when returning a value from an + anonymous method (error 1662). + Invoke NeedReturnLabel from the Resolve phase instead of the emit + phase. + + (Break.Resolve): ditto. + + (SwitchLabel): instead of defining the labels during the + resolution phase, we now turned the public ILLabel and ILLabelCode + labels into methods called GetILLabelCode() and GetILLabel() that + only define the label during the Emit phase. + + (GotoCase): Track the SwitchLabel instead of the computed label + (its contained therein). Emit the code by using + SwitchLabel.GetILLabelCode (). + + (LocalInfo.Flags.Captured): A new flag has been introduce to track + whether the Local has been captured or not. + + (LocalInfo.IsCaptured): New property, used to tell whether the + local has been captured. + + * anonymous.cs: Vastly updated to contain the anonymous method + support. + + The main classes here are: CaptureContext which tracks any + captured information for a toplevel block and ScopeInfo used to + track the activation frames for various local variables. + + Each toplevel block has an optional capture context associated + with it. When a method contains an anonymous method both the + toplevel method and the anonymous method will create a capture + context. When variables or parameters are captured, they are + recorded on the CaptureContext that owns them, for example: + + void Demo () { + int a; + MyDelegate d = delegate { + a = 1; + } + } + + Here `a' will be recorded as captured on the toplevel + CapturedContext, the inner captured context will not have anything + (it will only have data if local variables or parameters from it + are captured in a nested anonymous method. + + The ScopeInfo is used to track the activation frames for local + variables, for example: + + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j++){ + MyDelegate d = delegate { + call (i, j); + } + } + + At runtime this captures a single captured variable `i', but it + captures 10 different versions of the variable `j'. The variable + `i' will be recorded on the toplevel ScopeInfo, while `j' will be + recorded on a child. + + The toplevel ScopeInfo will also track information like the `this' + pointer if instance variables were referenced (this is necessary + as the anonymous method lives inside a nested class in the host + type of the method). + + (AnonymousMethod): Expanded to track the Toplevel, implement + `AnonymousMethod.Compatible' to tell whether an anonymous method + can be converted to a target delegate type. + + The routine now also produces the anonymous method content + + (AnonymousDelegate): A helper class that derives from + DelegateCreation, this is used to generate the code necessary to + produce the delegate for the anonymous method that was created. + + * assign.cs: API adjustments for new changes in + Convert.ImplicitStandardConversionExists. + + * class.cs: Adjustments to cope with the fact that now toplevel + blocks are of type `ToplevelBlock'. + + * cs-parser.jay: Now we produce ToplevelBlocks for toplevel blocks + insteda of standard blocks. + + Flag errors if params arguments are passed to anonymous methods. + + * codegen.cs (EmitContext): Replace `InAnonymousMethod' with + `CurrentAnonymousMethod' which points to the current Anonymous + Method. The variable points to the AnonymousMethod class that + holds the code being compiled. It is set in the new EmitContext + created for the anonymous method. + + (EmitContext.Phase): Introduce a variable and an enumeration to + assist in enforcing some rules about when and where we are allowed + to invoke certain methods (EmitContext.NeedsReturnLabel is the + only one that enfonces this right now). + + (EmitContext.HaveCaptureInfo): new helper method that returns + whether we have a CapturedContext initialized. + + (EmitContext.CaptureVariable): New method used to register that a + LocalInfo must be flagged for capturing. + + (EmitContext.CapturedParameter): New method used to register that a + parameters must be flagged for capturing. + + (EmitContext.CapturedField): New method used to register that a + field must be flagged for capturing. + + (EmitContext.HaveCapturedVariables, + EmitContext.HaveCapturedFields): Return whether there are captured + variables or fields. + + (EmitContext.EmitMethodHostInstance): This is used to emit the + instance for the anonymous method. The instance might be null + (static methods), this (for anonymous methods that capture nothing + and happen to live side-by-side with the current method body) or a + more complicated expression if the method has a CaptureContext. + + (EmitContext.EmitTopBlock): Routine that drives the emission of + code: it will first resolve the top block, then emit any metadata + and then emit the code. The split is done so that we can extract + any anonymous methods and flag any captured variables/parameters. + + (EmitContext.ResolveTopBlock): Triggers the resolution phase, + during this phase, the ILGenerator should not be used as labels + and local variables declared here might not be accessible to any + code that is part of an anonymous method. + + Exceptions to this include the temporary variables that are + created by some statements internally for holding temporary + variables. + + (EmitContext.EmitMeta): New routine, in charge of emitting all the + metadata for a cb + + (EmitContext.TemporaryReturn): This method is typically called + from the Emit phase, and its the only place where we allow the + ReturnLabel to be defined other than the EmitMeta. The reason is + that otherwise we would have to duplicate a lot of logic in the + Resolve phases of various methods that today is on the Emit + phase. + + (EmitContext.NeedReturnLabel): This no longer creates the label, + as the ILGenerator is not valid during the resolve phase. + + (EmitContext.EmitThis): Extended the knowledge in this class to + work in anonymous methods in addition to iterators. + + (EmitContext.EmitCapturedVariableInstance): This emits whatever + code is necessary on the stack to access the instance to a local + variable (the variable will be accessed as a field). + + (EmitContext.EmitParameter, EmitContext.EmitAssignParameter, + EmitContext.EmitAddressOfParameter): Routines to support + parameters (not completed at this point). + + Removals: Removed RemapLocal and RemapLocalLValue. We probably + will also remove the parameters. + + * convert.cs (Convert): Define a `ConstantEC' which points to a + null. This is just to prefity some code that uses + ImplicitStandardConversion code and do not have an EmitContext + handy. + + The idea is to flag explicitly that at that point in time, it is + known that the conversion will not trigger the delegate checking + code in implicit conversions (which requires a valid + EmitContext). + + Everywhere: pass new EmitContext parameter since + ImplicitStandardConversionExists now requires it to check for + anonymous method conversions. + + (Convert.ImplicitStandardConversionExists): If the type of an + expression is the anonymous_method_type, and the type is a + delegate, we invoke the AnonymousMethod.Compatible method to check + whether an implicit conversion is possible. + + (Convert.ImplicitConversionStandard): Only do implicit method + group conversions if the language level is not ISO_1. + + * delegate.cs (Delegate.GetInvokeMethod): Common method to get the + MethodInfo for the Invoke method. used by Delegate and + AnonymousDelegate. + + * expression.cs (Binary.DoNumericPromotions): only allow anonymous + method conversions if the target type is a delegate. + + Removed extra debugging nops. + + (LocalVariableReference): Turn the `local_info' into a public + field. + + Add `prepared' field, the same hack used for FieldExprs to cope + with composed assignments, as Local variables do not necessarily + operate purely on the stack as they used to: they can be captured + fields. + + Add `temp' for a temporary result, like fields. + + Refactor DoResolve and DoResolveLValue into DoResolveBase. + + It now copes with Local variables that are captured and emits the + proper instance variable to load it from a field in the captured + case. + + (ParameterReference.DoResolveBase): During the resolve phase, + capture parameters if we are in an anonymous method. + + (ParameterReference.Emit, ParameterReference.AddressOf): If in an + anonymous method, use the EmitContext helper routines to emit the + parameter reference. + + * iterators.cs: Set RemapToProxy to true/false during the + EmitDispose class. + + * parameters.cs (GetParameterByName): New helper method. + + * typemanager.cs (anonymous_method_type) a new type that + represents an anonyous method. This is always an internal type, + used as a fencepost to test against the anonymous-methodness of an + expression. + +2004-10-20 Marek Safar + + * class.cs (MethodCore.CheckBase): Add errors 505, 533, 544, + 561 report. + (PropertyBase.FindOutParentMethod): Add errors 545, 546 report. + +2004-10-18 Martin Baulig + + * statement.cs (Fixed.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (Catch.Resolve): Likewise. + (Foreach.Resolve): Likewise. + +2004-10-18 Martin Baulig + + * expression.cs (Cast.DoResolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (Probe.DoResolve): Likewise. + (ArrayCreation.LookupType): Likewise. + (TypeOf.DoResolve): Likewise. + (SizeOf.DoResolve): Likewise. + +2004-10-18 Martin Baulig + + * expression.cs (Invocation.BetterFunction): Put back + TypeManager.TypeToCoreType(). + +2004-10-18 Raja R Harinath + + * class.cs (FieldMember.DoDefine): Reset ec.InUnsafe after doing + the ResolveType. + +2004-10-18 Martin Baulig + + * parameter.cs (Parameter.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + +2004-10-18 Martin Baulig + + * class.cs (FieldMember.Define): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (MemberBase.DoDefine): Likewise. + + * expression.cs (New.DoResolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (ComposedCast.DoResolveAsTypeStep): Likewise. + + * statement.cs (LocalInfo.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + +2004-10-17 John Luke + + * class.cs (Operator.GetSignatureForError): use CSharpName + + * parameter.cs (Parameter.GetSignatureForError): Returns + correct name even if was not defined. + +2004-10-13 Raja R Harinath + + Fix #65816. + * class.cs (TypeContainer.EmitContext): New property. + (DefineNestedTypes): Create an emitcontext for each part. + (MethodCore.DoDefineParameters): Use container's emitcontext. + Pass type array to InternalParameters. + (MemberBase.DoDefine): Use container's emitcontext. + (FieldMember.Define): Likewise. + (Event.Define): Likewise. + (SetMethod.GetParameterInfo): Change argument to EmitContext. + Pass type array to InternalParameters. + (SetIndexerMethod.GetParameterInfo): Likewise. + (SetMethod.Define): Pass emitcontext to GetParameterInfo. + * delegate.cs (Define): Pass emitcontext to + ComputeAndDefineParameterTypes and GetParameterInfo. Pass type + array to InternalParameters. + * expression.cs (ParameterReference.DoResolveBase): Pass + emitcontext to GetParameterInfo. + (ComposedCast.DoResolveAsTypeStep): Remove check on + ec.ResolvingTypeTree. + * parameter.cs (Parameter.Resolve): Change argument to + EmitContext. Use ResolveAsTypeTerminal. + (Parameter.GetSignature): Change argument to EmitContext. + (Parameters.ComputeSignature): Likewise. + (Parameters.ComputeParameterTypes): Likewise. + (Parameters.GetParameterInfo): Likewise. + (Parameters.ComputeAndDefineParameterTypes): Likewise. + Re-use ComputeParameterTypes. Set ec.ResolvingTypeTree. + * support.cs (InternalParameters..ctor): Remove variant that takes + a DeclSpace. + * typemanager.cs (system_intptr_expr): New. + (InitExpressionTypes): Initialize it. + +2004-10-12 Chris Toshok + + * cs-parser.jay: fix location for try_statement and catch_clause. + +2004-10-11 Martin Baulig + + * report.cs: Don't make --fatal abort on warnings, we have + -warnaserror for that. + +2004-10-07 Raja R Harinath + + More DeclSpace.ResolveType avoidance. + * decl.cs (MemberCore.InUnsafe): New property. + * class.cs (MemberBase.DoDefine): Use ResolveAsTypeTerminal + with newly created EmitContext. + (FieldMember.Define): Likewise. + * delegate.cs (Delegate.Define): Likewise. + * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup with alias + only if normal name-lookup fails. + (TypeExpr.DoResolve): Enable error-checking. + * expression.cs (ArrayCreation.DoResolve): Use ResolveAsTypeTerminal. + (SizeOf.DoResolve): Likewise. + (ComposedCast.DoResolveAsTypeStep): Likewise. + (StackAlloc.DoResolve): Likewise. + * statement.cs (Block.Flags): Add new flag 'Unsafe'. + (Block.Unsafe): New property. + (Block.EmitMeta): Set ec.InUnsafe as appropriate. + (Unsafe): Set 'unsafe' flag of contained block. + (LocalInfo.Resolve): Use ResolveAsTypeTerminal. + (Fixed.Resolve): Likewise. + (Catch.Resolve): Likewise. + (Using.ResolveLocalVariableDecls): Likewise. + (Foreach.Resolve): Likewise. + +2004-10-05 John Luke + + * cs-parser.jay: add location to error CS0175 + +2004-10-04 Miguel de Icaza + + * ecore.cs (Expression.Constantity): Add support for turning null + into a constant. + + * const.cs (Const.Define): Allow constants to be reference types + as long as the value is Null. + +2004-10-04 Juraj Skripsky + + * namespace.cs (NamespaceEntry.Using): No matter which warning + level is set, check if this namespace name has already been added. + +2004-10-03 Ben Maurer + + * expression.cs: reftype [!=]= null should always use br[true,false]. + # 67410 + +2004-10-03 Marek Safar + + Fix #67108 + * attribute.cs: Enum conversion moved to + GetAttributeArgumentExpression to be applied to the all + expressions. + +2004-10-01 Raja R Harinath + + Fix #65833, test-300.cs, cs0122-5.cs, cs0122-6.cs. + * class.c (TypeContainer.DefineType): Flag error if + base types aren't accessible due to access permissions. + * decl.cs (DeclSpace.ResolveType): Move logic to + Expression.ResolveAsTypeTerminal. + (DeclSpace.ResolveTypeExpr): Thin layer over + Expression.ResolveAsTypeTerminal. + (DeclSpace.CheckAccessLevel, DeclSpace.FamilyAccess): + Refactor code into NestedAccess. Use it. + (DeclSpace.NestedAccess): New. + * ecore.cs (Expression.ResolveAsTypeTerminal): Add new + argument to silence errors. Check access permissions. + (TypeExpr.DoResolve, TypeExpr.ResolveType): Update. + * expression.cs (ProbeExpr.DoResolve): Use ResolveAsTypeTerminal. + (Cast.DoResolve): Likewise. + (New.DoResolve): Likewise. + (InvocationOrCast.DoResolve,ResolveStatement): Likewise. + (TypeOf.DoResolve): Likewise. + + * expression.cs (Invocation.BetterConversion): Return the Type of + the better conversion. Implement section 14.4.2.3 more faithfully. + (Invocation.BetterFunction): Make boolean. Make correspondence to + section 14.4.2.2 explicit. + (Invocation.OverloadResolve): Update. + (Invocation): Remove is_base field. + (Invocation.DoResolve): Don't use is_base. Use mg.IsBase. + (Invocation.Emit): Likewise. + +2004-09-27 Raja R Harinath + + * README: Update to changes. + +2004-09-24 Marek Safar + + * cs-parser.jay: Reverted 642 warning fix. + +2004-09-23 Marek Safar + + Fix bug #66615 + * decl.cs (FindMemberWithSameName): Indexer can have more than + 1 argument. + +2004-09-23 Marek Safar + + * expression.cs (LocalVariableReference.DoResolveLValue): + Do not report warning 219 for out values. + (EmptyExpression.Null): New member to avoid extra allocations. + +2004-09-23 Marek Safar + + * cs-parser.jay: Fix wrong warning 642 report. + + * cs-tokenizer.cs (CheckNextToken): New helper; + Inspect next character if is same as expected. + +2004-09-23 Martin Baulig + + * convert.cs (Convert.ImplicitReferenceConversion): Some code cleanup. + (Convert.ImplicitReferenceConversionExists): Likewise. + +2004-09-23 Marek Safar + + * class.cs (Operator.Define): Add error 448 and 559 report. + +2004-09-22 Marek Safar + + * class.cs (MemberBase.IsTypePermitted): New protected + method for checking error CS0610. + +2004-09-22 Marek Safar + + * class.cs (TypeContainer.HasExplicitLayout): New property + Returns whether container has StructLayout attribute set Explicit. + (FieldMember): New abstract class for consts and fields. + (FieldMember.ApplyAttributeBuilder): Add error 636 and 637 report. + (Field): Reuse FieldMember. + + * const.cs (Const): Reuse FieldMember. + + * rootcontext.cs: EmitConstants call moved to class. + +2004-09-22 Martin Baulig + + Thanks to Peter Sestoft for this bug report. + + * expression.cs (Conditional): If both the `trueExpr' and the + `falseExpr' is a NullLiteral, return a NullLiteral. + +2004-09-22 Martin Baulig + + * statement.cs (Foreach.EmitCollectionForeach): If we're in an + iterator, use `enumerator.EmitThis()' instead of `ec.EmitThis()' + for the "get_Current" call. + +2004-09-22 Martin Baulig + + Marek and me just fixed one of our oldest bugs: #28562 :-) + + * ecore.cs (EnumConstant.GetValueAsEnumType): New public method. + + * attribute.cs (Attribute.GetAttributeArgumentExpression): If + we're an EnumConstant, just return that. + (Attribute.Resolve): GetAttributeArgumentExpression() may give us + an EnumConstant. In this case, we need to use GetValueAsEnumType() + to get the value which'll actually be written into the attribute. + However, we have to use GetValue() to access the attribute's value + in the compiler. + +2004-09-22 Marek Safar + + * constant.cs (Constant.IsNegative): New abstract property + IsNegative. + + * expression.cs (ArrayAccess.DoResolve): Add warning 251. + (StackAlloc.DoResolve): Reused IsNegative. + +2004-09-21 Martin Baulig + + * codegen.cs (VariableStorage): Don't store the ILGenerator here; + if we're used in an iterator, we may be called from different + methods. + + * statement.cs (Foreach.EmitFinally): Only emit an `Endfinally' if + we actually have an exception block. + +2004-09-20 John Luke + + * class.cs, cs-parser.jay: Improve the error report for 1520: + report the actual line where the error happens, not where the + class was declared. + + * assign.cs, delegate.cs, ecore.cs, expression.cs, statement.cs: + Pass location information that was available elsewhere. + +2004-09-19 Sebastien Pouliot + + * codegen.cs: Fix bug #56621. It is now possible to use MCS on the MS + runtime to delay sign assemblies. + +2004-09-19 Miguel de Icaza + + * cs-parser.jay: Do not report the stack trace, this is barely + used nowadays. + +2004-08-22 John Luke + + * driver.cs : check that a resource id is not already used + before adding it, report CS1508 if it is, bug #63637 + +2004-09-19 Miguel de Icaza + + * ecore.cs: Removed dead code. + +2004-09-18 Marek Safar + + * class.cs: Do not report warning CS0067 on the interfaces. + +2004-09-16 Marek Safar + + * cs-parser.jay: Add error 504 report. + +2004-09-16 Marek Safar + + * rootcontext.cs: WarningLevel is 4 by default now. + + * statement.cs (Fixed.Resolve): Do not null + VariableInfo. + +2004-09-16 Marek Safar + + Fixed bug #55780 + * ecore.cs (PropertyExpr.FindAccessors): Do not perform + deep search when property is not virtual. + (PropertyExpr.ResolveAccessors): Make one call for both + accessors. + +2004-09-15 Marek Safar + + Fixed bug #65766 + * statement.cs: Error 152 report constains also location. + +2004-09-15 Marek Safar + + Fixed bug #65766 + * const.cs: Explicitly set constant as static. + +2004-09-15 Marek Safar + + Fixed bug #64226 + * cs-parser.jay: Add error 1017 report. + +2004-09-15 Marek Safar + + Fixed bug #59980, #64224 + * expression.cs (Invocation.DoResolve): Fixed error CS0571 test. + + * typemanager.cs (IsSpecialMethod): Simplified + +2004-09-14 Marek Safar + + * decl.cs (MemberCore.Emit): Resuscitated VerifyObsoleteAttribute + condition with better params. + +2004-09-14 Marek Safar + + Fixed bug #65238 + * attribute.cs (Resolve): Property has to have both + accessors. + +2004-09-14 Martin Baulig + + * decl.cs (MemberCore.Emit): Always call VerifyObsoleteAttribute(). + +2004-09-14 Marek Safar + + Fixed bug #61902 + * codegen.cs (TestObsoleteMethodUsage): Trace when method is + called and is obsolete then this member suppress message + when call is inside next [Obsolete] method or type. + + * expression.cs: Use TestObsoleteMethodUsage member. + +2004-09-14 Martin Baulig + + * cs-parser.jay: Sync a bit with the GMCS version. + +2004-09-14 Martin Baulig + + * cs-parser.jay (CSharpParser): Don't derive from GenericsParser. + (CSharpParser.yacc_verbose_flag): New public field. + + * genericparser.cs: Removed. + +2004-09-14 Raja R Harinath + + * cs-parser.jay (event_declaration): Re-enable cs0071 error. + +2004-09-13 Marek Safar + + * class.cs (MethodCore.CheckBase): Fix bug #65757. + +2004-09-10 Martin Baulig + + Backported my MemberName changes from GMCS into MCS. + + - we are now using a special `MemberName' class instead of using + strings; in GMCS, the `MemberName' also contains the type + arguments. + + - changed the grammar rules a bit: + * the old `member_name' is now a `namespace_or_type_name': + The rule is that we use `namespace_or_type_name' everywhere + where we expect either a "member name" (GetEnumerator) or a + "member name" with an explicit interface name + (IEnumerable.GetEnumerator). + In GMCS, the explicit interface name may include type arguments + (IEnumerable.GetEnumerator). + * we use `member_name' instead of just `IDENTIFIER' for + "member names": + The rule is that we use `member_name' wherever a member may + have type parameters in GMCS. + + * decl.cs (MemberName): New public class. + (MemberCore.MemberName): New public readonly field. + (MemberCore.ctor): Take a `MemberName' argument, not a string. + (DeclSpace): Likewise. + + * delegate.cs (Delegate.ctor): Take a MemberName, not a string. + * enum.cs (Enum.ctor): Likewise. + + * namespace.cs (AliasEntry.Alias): Changed type from Expression to + MemberName. + (AliasEntry.ctor): Take a MemberName, not an Expression. + (AliasEntry.UsingAlias): Likewise. + + * class.cs (TypeContainer.ctor): Take a MemberName, not a string. + (IMethodData.MemberName): Changed type from string to MemberName. + (MemberBase.ExplicitInterfaceName): Likewise. + (AbstractPropertyEventMethod.SetupName): Make this private. + (AbstractPropertyEventMethod.ctor): Added `string prefix' + argument; compute the member name here. + (AbstractPropertyEventMethod.UpdateName): Recompute the name based + on the `member.MemberName' and the `prefix'. + + * cs-parser.jay (attribute_name): Use `namespace_or_type_name', + not `type_name'. + (struct_declaration): Use `member_name' instead of `IDENTIFIER'; + thus, we get a `MemberName' instead of a `string'. These + declarations may have type parameters in GMCS. + (interface_method_declaration, delegate_declaration): Likewise. + (class_declaration, interface_declaration): Likewise. + (method_header): Use `namespace_or_type_name' instead of + `member_name'. We may be an explicit interface implementation. + (property_declaration, event_declaration): Likewise. + (member_name): This is now just an `IDENTIFIER', not a + `namespace_or_type_name'. + (type_name, interface_type): Removed. + (namespace_or_type_name): Return a MemberName, not an Expression. + (primary_expression): Use `member_name' instead of `IDENTIFIER'; + call GetTypeExpression() on the MemberName to get an expression. + (IndexerDeclaration.interface_type): Changed type from string to + MemberName. + (MakeName): Operate on MemberName's instead of string's. + +2004-09-13 Raja R Harinath + + Fix bug #55770. + * namespace.cs (AliasEntry.Resolve): Implement section 16.3.1. + (NamespaceEntry.Lookup): Add new argument to flag if we want the + lookup to avoid symbols introduced by 'using'. + * rootcontext.cs (NamespaceLookup): Update. + +2004-09-12 Marek Safar + + * class.cs (TypeContainer.DoDefineMembers): Do not call + DefineDefaultConstructor for static classes. + +2004-09-12 Marek Safar + + * attribute.cs (Attribute.Resolve): Add error 653 report. + + * class.cs (Class.ApplyAttributeBuilder): Add error 641 + report. + (Method.ApplyAttributeBuilder): Add error 685 report. + (Operator.Define): Add error 564 report. + + * cs-tokenizer.cs (handle_hex): Add error 1013 report. + + * expression.cs (Invocation.DoResolve): Add error + 245 and 250 report. + + * parameter.cs (Parameter.ApplyAttributeBuilder): Add + error 674 report. + +2004-09-11 Marek Safar + + * class.cs (ConstructorInitializer.Resolve): + Wrong error number (515->516). + +2004-09-11 Marek Safar + + * class.cs (Indexer.Define): Add error 631 report. + +2004-09-11 Marek Safar + + * ecore.cs (Error_NegativeArrayIndex): Fix 248 error. + +2004-09-11 Marek Safar + + * expression.cs (Probe.DoResolve): Add error CS0241 report. + +2004-09-10 Marek Safar + + * cs-parser.jay: Added error CS0241 report. + +2004-09-10 Raja R Harinath + + * cs-parser.jay (fixed_statement): Introduce a scope for the + declaration in the 'fixed' statement. + +2004-09-09 Marek Safar + + * cs-parser.jay: Added CS0230 error report. + +2004-09-09 Marek Safar + + * cs-parser.jay: Added errors CS0231 and CS0257 report. + +2004-09-09 Marek Safar + + * expression.cs (Argument.Resolve): Added error CS0192 and + CS0199 report. + +2004-09-09 Marek Safar + + C# 2.0 #pragma warning feature + + * cs-tokenizer.cs (PreProcessPragma): New method; + Handles #pragma directive. + + * report.cs (WarningRegions): New class; Support + class for #pragma warning directive. It tests whether + warning is enabled for a given line. + +2004-09-08 Miguel de Icaza + + * const.cs: Add more descriptive error report, tahnks to + Sebastien. + +2004-09-08 Marek Safar + + * ecore.cs (FieldExpr.DoResolveLValue): Fixed CS0198 report. + +2004-09-07 Miguel de Icaza + + * expression.cs: Apply patch from Ben: Remove dead code from + ArrayCreation, and remove the TurnintoConstant call in const.cs, + as that code just threw an exception anwyays. + + * const.cs: Remove the call to the turnintoconstant, for details + see bug: #63144 + + * literal.cs: The type of the null-literal is the null type; So + we use a placeholder type (literal.cs:System.Null, defined here) + for it. + + * expression.cs (Conditional.DoResolve): Remove some old code that + is no longer needed, conversions have been fixed. + + (ArrayCreationExpression.DoResolve): Return false if we fail to + resolve the inner expression. + +2004-09-07 Raja R Harinath + + Fix test-290.cs. + * cs-parser.jay (delegate_declaration): Record a delegate + declaration as a type declaration. + Reported by Jo Vermeulen . + +2004-09-06 Miguel de Icaza + + * parameter.cs: Do not crash if the type can not be resolved. + + * expression.cs: Report errors with unsafe pointers, fixes #64896 + +2004-09-06 Ben Maurer + + * expression.cs: Pointer arith always needs to do a conv.i + if the operand is a long. fix 65320 + +2004-09-04 Marek Safar + + Fixed cs0619-37.cs, cs0619-38.cs + + * enum.cs (GetObsoleteAttribute): Removed. + + * expression.cs (MemberAccess.DoResolve): Test for [Obsolete] + on Enum member is double staged. The first is tested member + and then enum. + +2004-09-04 Marek Safar + + Fixed #56986, #63631, #65231 + + * class.cs: (TypeContainer.AddToMemberContainer): New method, + adds member to name container. + (TypeContainer.AddToTypeContainer): New method, adds type to + name container. + (AddConstant, AddEnum, AddClassOrStruct, AddDelegate, AddMethod, + AddConstructor, AddInterface, AddField, AddProperty, AddEvent, + AddOperator): Simplified by reusing AddToMemberContainer. + (TypeContainer.UserDefinedStaticConstructor): Changed to property + instead of field. + (Method.CheckForDuplications): Fixed implementation to test all + possibilities. + (MemberBase): Detection whether member is explicit interface + implementation is now in constructor. + (MemberBase.UpdateMemberName): Handles IndexerName. + (Accessor): Changed to keep also location information. + (AbstractPropertyEventMethod): Is derived from MemberCore. + (AbstractPropertyEventMethod.IsDummy): Says whether accessor + will be emited or not. + (PropertyBase.AreAccessorsDuplicateImplementation): + Tests whether accessors are not in collision with some method. + (Operator): Is derived from MethodCore to simplify common + operations. + + * decl.cs (Flags.TestMethodDuplication): Test for duplication + must be performed. + (DeclSpace.AddToContainer): Adds the member to defined_names + table. It tests for duplications and enclosing name conflicts. + + * enum.cs (EnumMember): Clean up to reuse the base structures + +2004-09-03 Martin Baulig + + * class.cs (TypeContainer.DefineDefaultConstructor): Put this back + into TypeContainer, to make partial classes work again. + +2004-09-03 Martin Baulig + + * rootcontext.cs (RootContext.V2): Removed. + +2004-03-23 Martin Baulig + + * expression.cs (Invocation.OverloadResolve): Added `bool + may_fail' argument and use it instead of the Location.IsNull() hack. + +2004-09-03 Martin Baulig + + Merged latest changes into gmcs. Please keep this comment in + here, it makes it easier for me to see what changed in MCS since + the last time I merged. + +2004-09-03 Raja R Harinath + + Fix #61128. + * expression.cs (BetterConversion): Don't allow either conversion + to be null. Remove redundant implicit conversion test when 'q == + null' -- when this function is invoked, we already know that the + implicit conversion exists. + (BetterFunction): Assume that 'best' is non-null. Remove + redundant reimplementation of IsApplicable when 'best' is null. + (IsParamsMethodApplicable, IsApplicable): Add new parameter for + number of arguments. + (IsAncestralType): Extract from OverloadResolve. + (OverloadResolve): Make robust to the MethodGroupExpr being + unsorted. Implement all the logic of Section 14.5.5.1, and + support overloading of methods from multiple applicable types. + Clean up logic somewhat. Don't pass null methods to BetterFunction. + + * report.cs (SymbolRelatedToPreviousError): Cleanup output. + (RealError, Warning): Append type of report to related symbol. + +2004-09-03 Marek Safar + + * enum.cs: Fixed CLS-Compliance checks for enum members. + Error tests cs3008-8.cs, cs3014-8.cs + +2004-09-02 Marek Safar + + Fixed bug #62342, #63102 + * class.cs: ImplementIndexer uses member.IsExplicitImpl + like ImplementMethod. + +2004-09-02 Marek Safar + + * attribute.cs (Attribute.GetAttributeArgumentExpression): + Fixed bug #65170. + +2004-09-02 Martin Baulig + + * statement.cs (Using.EmitLocalVariableDeclFinally): Use + TypeManager.GetArgumentTypes() rather than calling GetParameters() + on the MethodBase. + +2004-09-01 Marek Safar + + C# 2.0 Static classes implemented + + * class.cs (TypeContainer): instance_constructors, + initialized_fields, initialized_static_fields, + default_constructor, base_inteface_types are protected to be + accessible from StaticClass. + (TypeContainer.DefineDefaultConstructor): New virtual method + for custom default constructor generating + (StaticClass): New class to handle "Static classes" feature. + + * cs-parser.jay: Handle static keyword on class like instance + of StaticClass. + + * driver.cs: Added "/langversion" command line switch with two + options (iso-1, default). + +2004-08-31 Marek Safar + + * ecore.cs (FieldExpr.Resolve): Fixed bug #64689. + +2004-08-31 Miguel de Icaza + + * delegate.cs: Style. + +2004-08-31 Ben Maurer + + * delegate.cs: Add seperate instance expr field for miguel. + +2004-08-29 Ben Maurer + + * PointerArithmetic (Resolve): make sure we are not doing + pointer arith on void*. Also, make sure we are resolved + by not setting eclass until resolve. + + All callers: Make sure that PointerArithmetic gets resolved. + +2004-08-29 Ben Maurer + + * ArrayCreation (LookupType): If the type does not resolve + to an array, give an error. + +2004-08-27 Marek Safar + + * statement.cs (Try.Resolve): Fixed bug #64222 + +2004-08-27 Martin Baulig + + * class.cs + (TC.OperatorArrayList.OperatorEntry.CheckPairedOperators): Don't + crash here. + +2004-08-26 Marek Safar + + * ecore.cs (Constantify): Get underlying type via + System.Enum.GetUnderlyingType to avoid StackOverflow on the + Windows in special cases. + +2004-08-26 Marek Safar + + * typemanager.cs (GetAddMethod): Used GetAddMethod (true) + for obtaining also private methods. + (GetRemoveMethod): Used GetRemoveMethod (true) + for obtaining also private methods. + +2004-08-24 Martin Baulig + + * class.cs (Method.Define): Set MethodAttributes.SpecialName and + MethodAttributes.HideBySig for operators. + +2004-08-23 Martin Baulig + + Back to the old error reporting system :-) + + * report.cs (Message): Removed. + (Report.MessageData, ErrorData, WarningData): Removed. + (Report.Error, Warning): Back to the old system. + +2004-08-23 Martin Baulig + + * decl.cs (IMemberContainer.Parent): Renamed to ParentContainer. + + * class.cs (TypeContainer.ParentContainer): New public virtual + method; replaces the explicit interface implementation. + (ClassPart.ParentContainer): Override. + +2004-08-23 Martin Baulig + + * statement.cs (Switch): Added support for constant switches; see + #59428 or test-285.cs. + +2004-08-22 Marek Safar + + Fixed bug #62740. + * statement.cs (GetEnumeratorFilter): Removed useless + logic because C# specs is strict. GetEnumerator must be + public. + +2004-08-22 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a switch and may break, reset the barrier. Fixes #59867. + +2004-08-22 Marek Safar + + CLS-Compliance speed up (~5% for corlib) + + * attribute.cs (AttributeTester.VerifyTopLevelNameClsCompliance): + New method. Tests container for CLS-Compliant names + + * class.cs (TypeContainer.VerifyClsName): New method. + Checks whether container name is CLS Compliant. + (Constructor): Implements IMethodData. + + * decl.cs (MemberCache.GetPublicMembers ): New method. Builds + low-case table for CLS Compliance test. + (MemberCache.VerifyClsParameterConflict): New method. + Checks method parameters for CS3006 error. + + * enum.cs (EnumMember): Is derived from MemberCore. + (Enum.VerifyClsName): Optimized for better performance. + +2004-08-06 Marek Safar + + * report.cs: Renamed Error_T to Error and changed all + references. + +2004-08-06 Marek Safar + + * class.cs (TypeContainer.IndexerArrayList): New inner class + container for indexers. + (TypeContainer.DefaultIndexerName): New constant for default + indexer name. Replaced all "Item" with this constant. + (TypeContainer.DefineIndexers): Moved to IndexerArrayList class. + + * typemanager.cs (TypeManager.default_member_ctor): Cache here + DefaultMemberAttribute constructor. + +2004-08-05 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeJumpOrigins): + Fix bug #59429. + +2004-08-05 Marek Safar + + * mcs.exe.sources: $(EXTRA_SOURCES) are now here to avoid + multi platforms problem. + + * compiler.csproj: Included shared files. + +2004-08-04 Marek Safar + + Fix bug 60333, 55971 in the more general way + * attribute.cs (Attribute.GetAttributeArgumentExpression): + Added arg_type argument for constant conversion. + (Attribute.Resolve): Reuse GetAttributeArgumentExpression. + +2004-08-04 Marek Safar + + Fix bug #59760 + * class.cs (TypeContainer ): New inner classes MethodArrayList, + OperatorArrayList, MethodCoreArrayList for typecontainer + containers. Changed class member types to these new types. + (MethodArrayList.DefineMembers): Added test for CS0659. + +2004-08-04 Miguel de Icaza + + * cfold.cs: Synchronize the folding with the code in expression.cs + Binary.DoNumericPromotions for uint operands. + + * attribute.cs: Revert patch from Raja, it introduced a regression + while building Blam-1.2.1 (hard to isolate a test case). + +2004-08-04 Marek Safar + + Fix for #55382 + * class.cs: + (TypeContainer.Define): Renamed to DefineContainerMembers because of + name collision. + (MethodCore.parent_method): New member. The method we're overriding + if this is an override method. + (MethodCore.CheckBase): Moved from Method class and made common. + (MethodCore.CheckMethodAgainstBase): Moved from MemberBase and made + private. + (MethodCore.CheckForDuplications): New abstract method. For custom + member duplication search in a container + (MethodCore.FindOutParentMethod): New abstract method. Gets parent + method and its return type. + (Event.conflict_symbol): New member. Symbol with same name in the + parent class. + + * decl.cs: + (MemberCache.FindMemberWithSameName): New method. The method + is looking for conflict with inherited symbols. + +2004-08-04 Martin Baulig + + * codegen.cs (VariableStorage.EmitLoadAddress): New public method. + + * statement.cs (Foreach.EmitFinally): Make this work for valuetypes. + +2004-08-03 Marek Safar + + * report.cs (Message): New enum for better error, warning reference in + the code. + (MessageData): New inner abstract class. It generally handles printing of + error and warning messages. + Removed unused Error, Warning, Message methods. + +2004-08-03 Marek Safar + + Fix for cs0592-8.cs test + * attribute.cs + (Attributable.ValidAttributeTargets): Made public. + (Attribute.ExplicitTarget): New member for explicit target value. + (Attribute.CheckTargets): Now we translate explicit attribute + target to Target here. + +2004-08-03 Ben Maurer + + * ecore.cs (MethodGroupExpr): new IsBase property. + + * expression.cs (BaseAccess): Set IsBase on MethodGroupExpr. + + * delegate.cs (DelegateCreation): store a MethodGroupExpr + rather than an instance expr. + + (DelegateCreation.Emit): Use the method group rather than + the instance expression. Also, if you have base.Foo as the + method for a delegate, make sure to emit ldftn, not ldftnvirt. + + (ResolveMethodGroupExpr): Use the MethodGroupExpr. + + (NewDelegate.DoResolve): Only check for the existance of Invoke + if the method is going to be needed. Use MethodGroupExpr. + + (NewDelegate.Emit): Remove, DelegateCreation implements this. + + * expression.cs: For pointer arith., make sure to use + the size of the type, not the size of the pointer to + the type. + +2004-08-03 Marek Safar + + Fix for #60722 + * class.cs (Class): Added error CS0502 test. + +2004-08-03 John Luke + Raja R Harinath + + Fix for #60997. + * attribute.cs (Attribute.complained_before): New flag. + (Attribute.ResolveType, Attribute.Resolve), + (Attribute.DefinePInvokeMethod): Set it. + (Attributes.Search): Pass 'complain' to Attribute.ResolveType. + +2004-08-03 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't abort if we can't + use a user-defined operator; we still need to do numeric + promotions in case one argument is a builtin type and the other + one has an implicit conversion to that type. Fixes #62322. + +2004-08-02 Martin Baulig + + * statement.cs (LocalInfo.Flags): Added `IsThis'. + (LocalInfo.IsThis): New public property. + (Block.EmitMeta): Don't create a LocalBuilder for `this'. + +2004-08-01 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Don't set the default + here since we may get called from GetPartialBases(). + (TypeContainer.DefineType): If GetClassBases() didn't return a + parent, use the default one. + +2004-07-30 Duncan Mak + + * Makefile (mcs2.exe, mcs3.exe): add $(EXTRA_SOURCES). + +2004-07-30 Martin Baulig + + * Makefile (EXTRA_SOURCES): List the symbol writer's sources here. + + * class.cs (SourceMethod): New public class, derive from the + symbol writer's ISourceMethod. + (Method): Use the new symbol writer API. + + * codegen.cs (CodeGen.InitializeSymbolWriter): Take the filename + as argument and use the new symbol writer. + + * location.cs + (SourceFile): Implement the symbol writer's ISourceFile. + (Location.SymbolDocument): Removed. + (Location.SourceFile): New public property. + + * symbolwriter.cs: Use the new symbol writer API. + +2004-07-30 Raja R Harinath + + * Makefile (install-local): Remove. Functionality moved to + executable.make. + +2004-07-28 Lluis Sanchez Gual + + * Makefile: Install mcs.exe.config file together with mcs.exe. + * mcs.exe.config: Added supportedRuntime entry to make sure it runs in the + correct runtime version. + +2004-07-25 Martin Baulig + + * class.cs + (TypeContainer.RegisterOrder): Removed, this was unused. + (TypeContainer, interface_order): Removed. + (TypeContainer.AddClass, AddStruct, AddInterface): Take a + TypeContainer as argument since we can also be called with a + `PartialContainer' for a partial class/struct/interface. + (TypeContainer.IsInterface): Use `Kind == Kind.Interface' instead + of checking whether we're an `Interface' - we could be a + `PartialContainer'. + (PartialContainer.Register): Override; call + AddClass()/AddStruct()/AddInterface() on our parent. + + * cs-parser.jay (interface_member_declaration): Add things to the + `current_container', not the `current_class'. + + * rootcontext.cs (RegisterOrder): The overloaded version which + takes an `Interface' was unused, removed. + + * typemanager.cs (TypeManager.LookupInterface): Return a + `TypeContainer', not an `Interface'. + (TypeManager.IsInterfaceType): The `builder_to_declspace' may + contain a `PartialContainer' for an interface, so check it's + `Kind' to figure out what it is. + +2004-07-25 Martin Baulig + + * class.cs (Class.DefaultTypeAttributes): New public constant. + (Struct.DefaultTypeAttributes): Likewise. + (Interface.DefaultTypeAttributes): Likewise. + (PartialContainer.TypeAttr): Override this and add the + DefaultTypeAttributes. + +2004-07-25 Martin Baulig + + * decl.cs (DeclSpace.Emit): Removed the `TypeContainer' argument, + we can just use the `Parent' field instead. + +2004-07-25 Martin Baulig + + * class.cs (TypeContainer.Emit): Renamed to EmitType(). + +2004-07-25 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Call DefineMembers() on + our parts before defining any methods. + (TypeContainer.VerifyImplements): Make this virtual. + (ClassPart.VerifyImplements): Override and call VerifyImplements() + on our PartialContainer. + +2004-07-25 Martin Baulig + + * iterators.cs (Iterator.Define): Renamed to DefineIterator(). + + * decl.cs (DeclSpace.Define): Removed the `TypeContainer' + argument, we can just use the `Parent' field instead. + + * class.cs + (MemberBase.CheckBase): Removed the `TypeContainer' argument. + (MemberBase.DoDefine): Likewise. + +2004-07-24 Martin Baulig + + * decl.cs (MemberCore.Parent): New public field. + (DeclSpace.Parent): Moved to MemberCore. + + * class.cs (MethodCore.ds): Removed; use `Parent' instead. + (MemberBase.ctor): Added TypeContainer argument, pass it to our + parent's .ctor. + (FieldBase, Field, Operator): Likewise. + (EventProperty.ctor): Take a TypeContainer instead of a DeclSpace. + (EventField, Event): Likewise. + +2004-07-23 Martin Baulig + + * class.cs (PartialContainer): New public class. + (ClassPart): New public class. + (TypeContainer): Added support for partial classes. + (TypeContainer.GetClassBases): Splitted some of the functionality + out into GetNormalBases() and GetPartialBases(). + + * cs-tokenizer.cs (Token.PARTIAL): New token. + (Tokenizer.consume_identifier): Added some hacks to recognize + `partial', but only if it's immediately followed by `class', + `struct' or `interface'. + + * cs-parser.jay: Added support for partial clases. + +2004-07-23 Martin Baulig + + * class.cs (MethodCore.ds): Made this a `TypeContainer' instead of + a `DeclSpace' and also made it readonly. + (MethodCore.ctor): Take a TypeContainer instead of a DeclSpace. + (Method.ctor, Constructor.ctor, Destruktor.ctor): Likewise. + (PropertyBase.ctor, Property.ctor, Indexer.ctor): Likewise. + + * cs-parser.jay: Pass the `current_class', not the + `current_container' (at the moment, this is still the same thing) + to a new Method, Property, Event, Indexer or Constructor. + +2004-07-23 Martin Baulig + + * cs-parser.jay (CSharpParser): Added a new `current_class' field + and removed the `current_interface' one. + (struct_declaration, class_declaration, interface_declaration): + Set `current_class' to the newly created class/struct/interface; + set their `Bases' and call Register() before parsing their body. + +2004-07-23 Martin Baulig + + * class.cs (Kind): New public enum. + (TypeContainer): Made this class abstract. + (TypeContainer.Kind): New public readonly field. + (TypeContainer.CheckDef): New public method; moved here from + cs-parser.jay. + (TypeContainer.Register): New public abstract method. + (TypeContainer.GetPendingImplementations): New public abstract + method. + (TypeContainer.GetClassBases): Removed the `is_class' and + `is_iface' parameters. + (TypeContainer.DefineNestedTypes): Formerly known as + DoDefineType(). + (ClassOrStruct): Made this class abstract. + + * tree.cs (RootTypes): New public type. + +2004-07-20 Martin Baulig + + * tree.cs (Tree.RecordNamespace): Removed. + (Tree.Namespaces): Removed. + + * rootcontext.cs (RootContext.IsNamespace): Removed. + + * cs-parser.jay (namespace_declaration): Just create a new + NamespaceEntry here. + +2004-07-20 Martin Baulig + + * statement.cs (ExceptionStatement): New abstract class. This is + now used as a base class for everyone who's using `finally'. + (Using.ResolveLocalVariableDecls): Actually ResolveLValue() all + our local variables before using them. + + * flowanalysis.cs (FlowBranching.StealFinallyClauses): New public + virtual method. This is used by Yield.Resolve() to "steal" an + outer block's `finally' clauses. + (FlowBranchingException): The .ctor now takes an ExceptionStatement + argument. + + * codegen.cs (EmitContext.StartFlowBranching): Added overloaded + version which takes an ExceptionStatement. This version must be + used to create exception branchings. + + * iterator.cs + (Yield.Resolve): "Steal" all `finally' clauses from containing blocks. + (Iterator.EmitMoveNext): Added exception support; protect the + block with a `fault' clause, properly handle 'finally' clauses. + (Iterator.EmitDispose): Run all the `finally' clauses here. + +2004-07-20 Martin Baulig + + * iterator.cs: This is the first of a set of changes in the + iterator code. Match the spec more closely: if we're an + IEnumerable, then GetEnumerator() must be called. The first time + GetEnumerator() is called, it returns the current instance; all + subsequent invocations (if any) must create a copy. + +2004-07-19 Miguel de Icaza + + * expression.cs: Resolve the constant expression before returning + it. + +2004-07-19 Martin Baulig + + * iterators.cs (Iterator.MapVariable): Don't define fields twice. + (Iterator.MoveNextMethod.DoEmit): Use `TypeManager.int32_type' as + the return type of the new EmitContext. + +2004-07-18 Martin Baulig + + * class.cs (Property.Define): Fix iterators. + + * iterators.cs (Iterator.Define): Moved the + `container.AddInterator (this)' call here from the .ctor; only do + it if we resolved successfully. + +2004-07-17 Miguel de Icaza + + * cs-tokenizer.cs (handle_preprocessing_directive): Do not return + `true' for preprocessing directives that we parse. The return + value indicates whether we should return to regular tokenizing or + not, not whether it was parsed successfully. + + In the past if we were in: #if false ... #line #endif, we would + resume parsing after `#line'. See bug 61604. + + * typemanager.cs: Removed an old hack from Gonzalo to get corlib + building: IsEnumType should return true only for enums, not for + enums or System.Enum itself. This fixes #61593. + + Likely what happened is that corlib was wrong: mcs depended on + this bug in some places. The bug got fixed, we had to add the + hack, which caused bug 61593. + + * expression.cs (ArrayAccess.GetStoreOpCode): Remove an old hack + that was a workaround for the older conditions. + +2004-07-16 Ben Maurer + + * assign.cs: IAssignMethod has a new interface, as documented + inline. All assignment code now uses this new api. + + * ecore.cs, expression.cs: All classes which implement + IAssignMethod now use the new interface. + + * expression.cs (Invocation): add a hack to EmitCall so that + IndexerAccess can be the target of a compound assignment without + evaluating its arguments twice. + + * statement.cs: Handle changes in Invocation api. + +2004-07-16 Martin Baulig + + * iterators.cs: Rewrote this. We're now using one single Proxy + class for both the IEnumerable and the IEnumerator interface and + `Iterator' derives from Class so we can use the high-level API. + + * class.cs (TypeContainer.AddIterator): New method. + (TypeContainer.DoDefineType): New protected virtual method, which + is called from DefineType(). + (TypeContainer.DoDefineMembers): Call DefineType() and + DefineMembers() on all our iterators. + (TypeContainer.Emit): Call Emit() on all our iterators. + (TypeContainer.CloseType): Call CloseType() on all our iterators. + + * codegen.cs (EmitContext.CurrentIterator): New public field. + +2004-07-15 Martin Baulig + + * typemanager.cs + (TypeManager.not_supported_exception_type): New type. + +2004-07-14 Martin Baulig + + * iterators.cs: Use real error numbers. + +2004-07-14 Martin Baulig + + * iterator.cs (IteratorHandle.IsIEnumerable): The spec explicitly + requires this to be a System.Collection.IEnumerable and not a + class implementing that interface. + (IteratorHandle.IsIEnumerator): Likewise, for IEnumerator. + +2004-07-13 Marek Safar + + * class.cs: Fixed previous fix, it broke some error tests. + +2004-07-12 Martin Baulig + + * enum.cs (Enum.Define): Call Emit() to emit the attributes. + Fixes #61293. + +2004-07-09 Miguel de Icaza + + * assign.cs (LocalTemporary): Add new argument: is_address,If + `is_address' is true, then the value that we store is the address + to the real value, and not the value itself. + + * ecore.cs (PropertyExpr): use the new local temporary + stuff to allow us to handle X.Y += z (where X is a struct) + +2004-07-08 Martin Baulig + + * statement.cs (Lock.Resolve): Set ec.NeedReturnLabel() if we do + not always return, just like we're doing in Using.Resolve(). + +2004-07-07 Miguel de Icaza + + * cs-parser.jay (fixed_statement): flag this as Pinned. + +2004-07-06 Miguel de Icaza + + * typemanager.cs (TypeManager): Removed MakePinned method, this + mechanism is replaced with the .NET 2.x compatible mechanism of + calling `ILGenerator.DeclareLocal (Type t, bool pinned)'. + + * statement.cs (LocalInfo): Remove MakePinned, add Pinned property + Rename `Fixed' to `Pinned' as a flag, to distinguish from the + `IsFixed' property which has a different meaning. + +2004-07-02 Raja R Harinath + + * ecore.cs (DoSimpleNameResolve): Expand CS0038 check to all names + visible from inside a nested class, not just the names of the + immediately enclosing class. + Fix for bug #60730. + +2004-06-24 Raja R Harinath + + * expression.cs (BetterConversion): Remove buggy special-case + handling of "implicit constant expression conversions". At this + point, we already know that the conversion is possible -- we're + only checking to see which is better. + +2004-06-24 Marek Safar + + * cs-parser.jay: Added error CS0210 test. + +2004-06-24 Marek Safar + + * cs-parser.jay: Added error CS0134 test. + +2004-06-24 Marek Safar + + Fix bug #52507 + * cs-parser.jay: Added error CS0145 test. + +2004-06-24 Marek Safar + + * class.cs (Operator.Define): Added test for errors CS0553, CS0554. + +2004-06-23 Ben Maurer + + * expression.cs (StackAlloc.Resolve): The argument may not + be a constant; deal with this case. + +2004-06-23 Marek Safar + + * attribute.cs (IndexerName_GetIndexerName): Renamed to + GetIndexerAttributeValue. + (ScanForIndexerName): Renamed to GetIndexerNameAttribute. + + * class.cs (Indexer.Define): Added error tests for CS0415, + CS0609. + +2004-06-23 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Keep field code in sync with + property code. + +2004-06-23 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeChild): If we're a loop and we + neither return nor throw, reset the barrier as well. Fixes #60457. + +2004-06-22 Atsushi Enomoto + + * class.cs : EventAttributes is now set to None by default. + This fixes bug #60459. + +2004-06-18 Marek Safar + + Fix bug #60219 + * class.cs (ConstructorInitializer.GetOverloadedConstructor): + Don't throw exception but return null (it's sufficient now). + +2004-06-18 Marek Safar + + * typemanager.cs (GetArgumentTypes): Faster implementation. + +2004-06-18 Martin Baulig + + * attribute.cs (Attribute.Resolve): Check whether we're an + EmptyCast which a Constant child. Fixes #60333. + +2004-06-17 Ben Maurer + + * statement.cs (EmitCollectionForeach): Account for the fact that + not all valuetypes are in areas which we can take the address of. + For these variables, we store to a temporary variable. Also, make + sure that we dont emit a `callvirt' on a valuetype method. + +2004-06-15 Marek Safar + + * expression.cs (StackAlloc.DoReSolve): Added test for + negative parameter (CS0247). + +2004-06-15 Marek Safar + + Fix bug #59792 + * class.cs: (Event.DelegateMethod.Emit): Added synchronization flag. + +2004-06-15 Marek Safar + + Fix bug #59781 + * expression.cs: (Binary.DoNumericPromotions): Added conversion for + ulong. + +2004-06-14 Marek Safar + + Fix bug #58254 & cs1555.cs, cs1556.cs + * driver.cs (MainDriver): Added tests for errors CS1555, CS1556. + +2004-06-14 Marek Safar + + * cs-parser.jay: Added error CS1669 test for indexers. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.IsParamsMethodApplicable): We need to + call this twice: for params and varargs methods. + +2004-06-11 Marek Safar + + * class.cs: + (FieldBase.DoDefine, PropertyBase.DoDefine): Added error test CS0610. + +2004-06-11 Marek Safar + + * attribute.cs (Attribute.GetValidTargets): Made public. + + * class.cs: + (AbstractPropertyEventMethod): New class for better code sharing. + (AbstractPropertyEventMethod.ApplyAttributeBuilder): Add error + CS1667 report. + (PropertyMethod, DelegateMethod): Derived from AbstractPropertyEventMethod + +2004-06-11 Raja R Harinath + + Fix bug #59477. + * ecore.cs (ResolveFlags): Add new 'Intermediate' flag to tell + that the call to Resolve is part of a MemberAccess. + (Expression.Resolve): Use it for SimpleName resolution. + (SimpleName.SimpleNameResolve, SimpleName.DoResolveAllowStatic): + Add 'intermediate' boolean argument. + (SimpleName.DoSimpleNameResolve): Likewise. Use it to disable an + error message when the SimpleName can be resolved ambiguously + between an expression and a type. + * expression.cs (MemberAccess.IdenticalNameAndTypeName): Make + public. + (MemberAccess.Resolve): Pass 'Intermediate' flag to the Resolve() + call on the left-side. + +2004-06-11 Marek Safar + + * class.cs: + (MethodCore.VerifyClsCompliance): Added test for error CS3000. + +2004-06-11 Marek Safar + + * attribute.cs (Attribute.Emit): Fixed error CS0579 reporting. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.EmitCall): Use OpCodes.Callvirt for + varargs methods if applicable. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.EmitCall): Don't use + `method.CallingConvention == CallingConventions.VarArgs' since the + method could also have `CallingConventions.HasThis'. + +2004-06-11 Marek Safar + + * class.cs (Event.GetSignatureForError): Implemented. + Fixed crash in error test cs3010.cs + +2004-06-10 Miguel de Icaza + + * cs-tokenizer.cs: Change the way we track __arglist to be + consistent with the other keywords. + +2004-06-09 Miguel de Icaza + + * codegen.cs: FAQ avoider: turn 1577 into a warning for now until + tomorrow. + +2004-06-09 Sebastien Pouliot + + * codegen.cs: Check that all referenced assemblies have a strongname + before strongnaming the compiled assembly. If not report error CS1577. + Fix bug #56563. Patch by Jackson Harper. + * typemanager.cs: Added a method to return all referenced assemblies. + Fix bug #56563. Patch by Jackson Harper. + +2004-06-08 Marek Safar + + * class.cs: + (Method.ApplyAttributeBuilder): Moved and added conditional + attribute error tests (CS0577, CS0578, CS0243, CS0582, CS0629). + + * delegate.cs: + (DelegateCreation.ResolveMethodGroupExpr): Added error CS1618 test. + +2004-06-08 Marek Safar + + Fixed #59640 + * class.cs: (EventField.attribute_targets): Changed default target. + +2004-06-08 Martin Baulig + + * expression.cs (Invocation.EmitCall): Enable varargs methods. + +2004-06-08 Martin Baulig + + * rootcontext.cs (ResolveCore): Added "System.RuntimeArgumentHandle". + +2004-06-07 Martin Baulig + + Added support for varargs methods. + + * cs-tokenizer.cs (Token.ARGLIST): New token for the `__arglist' + keyword. + + * cs-parser.jay: Added support for `__arglist'. + + * decl.cs (MemberCache.AddMethods): Don't ignore varargs methods. + + * expression.cs (Argument.AType): Added `ArgList'. + (Invocation): Added support for varargs methods. + (ArglistAccess): New public class. + (Arglist): New public class. + + * parameter.cs (Parameter.Modifier): Added `ARGLIST'. + + * statement.cs (Block.Flags): Added `HasVarargs'. We set this on + a method's top-level block if the method has varargs. + + * support.cs (ReflectionParameters, InternalParameters): Added + support for varargs methods. + +2004-06-07 Miguel de Icaza + + * class.cs: Provide location in indexer error report. + + * driver.cs: Use standard names. + + * namespace.cs: Catch the use of using after a namespace has been + declared also on using aliases. + +2004-06-03 Raja R Harinath + + Bug #50820. + * typemanager.cs (closure_private_ok, closure_invocation_type) + (closure_qualifier_type, closure_invocation_assembly) + (FilterWithClosure): Move to ... + (Closure): New internal nested class. + (Closure.CheckValidFamilyAccess): Split out from Closure.Filter. + (MemberLookup, RealMemberLookup): Add new almost_match parameter. + * ecore.cs (almostMatchedMembers): New variable to help report CS1540. + (MemberLookup, MemberLookupFailed): Use it. + * expression.cs (New.DoResolve): Treat the lookup for the + constructor as being qualified by the 'new'ed type. + (Indexers.GetIndexersForTypeOrInterface): Update. + +2004-06-03 Marek Safar + + * attribute.cs + (GetConditionalAttributeValue): New method. Returns + condition of ConditionalAttribute. + (SearchMulti): New method. Returns all attributes of type 't'. + Use it when attribute is AllowMultiple = true. + (IsConditionalMethodExcluded): New method. + + * class.cs + (Method.IsExcluded): Implemented. Returns true if method has conditional + attribute and the conditions is not defined (method is excluded). + (IMethodData): Extended interface for ConditionalAttribute support. + (PropertyMethod.IsExcluded): Implemented. + + * decl.cs + (MemberCore.Flags): Excluded_Undetected, Excluded new caching flags. + + * expression.cs + (Invocation.IsMethodExcluded): Checks the ConditionalAttribute + on the method. + +2004-06-02 Ben Maurer + + * expression.cs (ArrayCreationExpression): Make this just an + `expression'. It can't be a statement, so the code here was + dead. + +2004-06-02 Marek Safar + + Fixed #59072 + * typemanager.cs (GetFullNameSignature): New method for + MethodBase types. + +2004-06-02 Marek Safar + + Fixed #56452 + * class.cs (MemberBase.GetSignatureForError): New virtual method. + Use this method when MethodBuilder is null. + (MethodData.DefineMethodBuilder): Encapsulated code to the new method. + Added test for error CS0626 (MONO reports error for this situation). + (IMethodData.GetSignatureForError): Extended interface. + +2004-06-01 Marek Safar + + * attribute.cs + (AttributeTester.GetObsoleteAttribute): Returns instance of + ObsoleteAttribute when type is obsolete. + + * class.cs + (TypeContainer.VerifyObsoleteAttribute): Override. + (Method.GetSignatureForError): New method for usage when MethodBuilder is null. + (MethodCode.VerifyObsoleteAttribute): Override. + (MemberBase.VerifyObsoleteAttribute): Override. + + * decl.cs + (MemberCore.CheckUsageOfObsoleteAttribute): Tests presence of ObsoleteAttribute + and report proper error. + + *delegate.cs + Delegate.VerifyObsoleteAttribute): Override. + + * ecore.cs + (Expression.CheckObsoleteAttribute): Tests presence of ObsoleteAttribute + and report proper error. + (FieldExpr.DoResolve): Added tests for ObsoleteAttribute. + + * enum.cs + (Enum.GetObsoleteAttribute): Returns ObsoleteAttribute for both enum type + and enum member. + + * expression.cs + (Probe.DoResolve, Cast.DoResolve, LocalVariableReference.DoResolve, + New.DoResolve, SizeOf.DoResolve, TypeOf.DoResolce, MemberAccess.DoResolve): + Added test for ObsoleteAttribute. + + * statement.cs + (Catch): Derived from Statement. + +2004-06-01 Marek Safar + + Fixed bug #59071 & cs0160.cs + + * statement.cs (Try.Resolve): Check here whether order of catch + clauses matches their dependencies. + +2004-05-31 Miguel de Icaza + + * Reverted patch to namespace.cs (Use lookuptypedirect). This + caused a regression: #59343. Referencing nested classes from an + assembly stopped working. + +2004-05-31 Martin Baulig + + MCS is now frozen for beta 2. + +2004-05-30 Ben Maurer + + * convert.cs: add a trivial cache for overload operator resolution. + +2004-05-30 Ben Maurer + + * decl.cs: If possible, use lookuptypedirect here. We can only do + this if there is no `.' after the namespace. Avoids using + LookupType, which does lots of slow processing. + (FindNestedType) New method, does what it says :-). + * namespace.cs: use LookupTypeDirect. + * rootcontext.cs: use membercache, if possible. + * typemanager.cs (LookupTypeDirect): Cache negative hits too. + +2004-05-30 Ben Maurer + + * expression.cs: + According to the spec, + + In a member access of the form E.I, if E is a single identifier, + and if the meaning of E as a simple-name (§7.5.2) is a constant, + field, property, localvariable, or parameter with the same type as + the meaning of E as a type-name (§3.8), then both possible + meanings of E are permitted. + + We did not check that E as a simple-name had the same type as E as + a type name. + + This trivial check gives us 5-7% on bootstrap time. + +2004-05-30 Ben Maurer + + * expression.cs (Invocation.OverloadResolve): Avoid the + use of hashtables and boxing here by allocating on demand. + +2004-05-30 Martin Baulig + + * rootcontext.cs (RootContext.LookupType): Don't cache things if + we're doing a silent lookup. Don't try to lookup nested types in + TypeManager.object_type (thanks to Ben Maurer). + +2004-05-30 Martin Baulig + + Committing a patch from Ben Maurer. + + * rootcontext.cs (RootContext.LookupType): Cache negative results. + +2004-05-29 Martin Baulig + + * class.cs (IMethodData.ShouldIgnore): New method. + + * typemanager.cs (TypeManager.MethodFlags): Don't take a + `Location' argument, we don't need it anywhere. Use + `IMethodData.ShouldIgnore ()' instead of + `MethodData.GetMethodFlags ()'. + (TypeManager.AddMethod): Removed. + (TypeManager.AddMethod2): Renamed to AddMethod. + +2004-05-29 Martin Baulig + + Committing a patch from Benjamin Jemlich . + + * convert.cs (Convert.ImplicitReferenceConversion): If we're + converting from a class type S to an interface type and we already + have an object on the stack, don't box it again. Fixes #52578. + +2004-05-29 Martin Baulig + + * class.cs (ConstructorInitializer.GetOverloadedConstructor): + Added support for `params' parameters. Fixes #59267. + +2004-05-29 Martin Baulig + + * literal.cs (NullPointer): Provide a private .ctor which sets + `type' to TypeManager.object_type. Fixes #59048. + +2004-05-29 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): If we're an + EventExpr, set `ee.InstanceExpression = left'. Fixes #59188. + + * ecore.cs (EventExpr.instance_expr): Make the field private. + +2004-05-26 Marek Safar + + Fixed bug #50080 & cs0214-2.cs + * expression.cs (Cast.DoResolve): Check unsafe context here. + + * statement.cs (Resolve.DoResolve): Likewise. + +2004-05-26 Martin Baulig + + * namespace.cs (NamespaceEntry.Lookup): Added `bool silent'. + + * rootcontext.cs (RootContext.NamespaceLookup): Added `bool silent'. + (RootContext.LookupType): Pass down the `silent' flag. + +2004-05-25 Martin Baulig + + * expression.cs + (MethodGroupExpr.IdenticalTypeName): New public property. + (Invocation.DoResolve): Don't report a CS0176 if the "instance" + expression actually refers to a type. + +2004-05-25 Martin Baulig + + * expression.cs (Invocation.DoResolve): Applied Ben Maurer's patch + for #56176 and made it actually work. + +2004-05-25 Martin Baulig + + * ecore.cs (Expression.CacheTemporaries): Make this virtual. + (FieldExpr, PropertyExpr): Override and implement + CacheTemporaries. Fixes #52279. + +2004-05-25 Miguel de Icaza + + * location.cs: In the new compiler listing a file twice is a + warning, not an error. + +2004-05-24 Martin Baulig + + * enum.cs (Enum.DefineType): For the `BaseType' to be a + TypeLookupExpression; otherwise, report a CS1008. Fixes #58571. + +2004-05-24 Martin Baulig + + * decl.cs (DeclSpace.FindType): Try doing an alias lookup before + walking the `using' list. Fixes #53921. + +2004-05-24 Martin Baulig + + * const.cs (Const.LookupConstantValue): Added support for + EmptyCast's; fixes #55251. + +2004-05-24 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Renamed to + DoSimpleNameResolve() and provide a SimpleNameResolve() wrapper + which does the CS0135 check. The reason is that we first need to + check whether the variable actually exists. + +2004-05-24 Martin Baulig + + * class.cs (MemberBase.DoDefine): Use DeclSpace.FindType() rather + than RootContext.LookupType() to find the explicit interface + type. Fixes #58584. + +2004-05-24 Raja R Harinath + + * Makefile: Simplify. Use executable.make. + * mcs.exe.sources: New file. List of sources of mcs.exe. + +2004-05-24 Anders Carlsson + + * decl.cs: + * enum.cs: + Use the invariant culture when doing String.Compare for CLS case + sensitivity. + +2004-05-23 Martin Baulig + + * decl.cs (DeclSpace.FindType): Only check the `using' list if we + don't have any dots. Fixes #52622, added cs0246-8.cs. + + * namespace.cs (NamespaceEntry.Lookup): Likewise. + +2004-05-23 Marek Safar + + * class.cs (MemberBase.Define): Reuse MemberType member for + resolved type. Other methods can use it too. + +2004-05-23 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Only report a CS0135 if + the variable also exists in the current block (otherwise, we need + to report a CS0103). Fixes #58670. + +2004-05-23 Martin Baulig + + * flowanalysis.cs (Reachability.Reachable): Compute this + on-the-fly rather than storing it as a field. + +2004-05-23 Martin Baulig + + * flowanalysis.cs (Reachability.And): Manually compute the + resulting `barrier' from the reachability. + +2004-05-23 Marek Safar + + Fix bug #57835 + * attribute.cs (AttributeTester.GetMethodObsoleteAttribute): Returns + instance of ObsoleteAttribute when symbol is obsolete. + + * class.cs + (IMethodData): Extended interface for ObsoleteAttribute support. + +2004-05-22 Marek Safar + + * attribute.cs: Fix bug #55970 + +2004-05-22 Marek Safar + + Fix bug #52705 + * attribute.cs + (GetObsoleteAttribute): New method. Creates the instance of + ObsoleteAttribute. + (AttributeTester.GetMemberObsoleteAttribute): Returns instance of + ObsoleteAttribute when member is obsolete. + (AttributeTester.Report_ObsoleteMessage): Common method for + Obsolete error/warning reporting. + + * class.cs + (TypeContainer.base_classs_type): New member for storing parent type. + + * decl.cs + (MemberCore.GetObsoleteAttribute): Returns instance of ObsoleteAttribute + for this MemberCore. + +2004-05-21 Marek Safar + + * attribute.cs, const.cs: Fix bug #58590 + +2004-05-21 Martin Baulig + + * flowanalysis.cs (FlowBranching.MergeTopBlock): Don't check for + out parameters if the end of the method is unreachable. Fixes + #58098. + +2004-05-21 Marek Safar + + * codegen.cs, cs-parser.jay: Removed SetAttributes method. + Hari was right, why extra method. + +2004-05-21 Marek Safar + + * attribute.cs, cs-parser.jay: Fix errors/cs0579-7.cs. + +2004-05-20 Martin Baulig + + Merged this back from gmcs to keep the differences to a minumum. + + * attribute.cs (Attribute.CheckAttributeType): Take an EmitContext + instead of a Declspace. + (Attribute.ResolveType): Likewise. + (Attributes.Search): Likewise. + (Attributes.Contains): Likewise. + (Attributes.GetClsCompliantAttribute): Likewise. + + * class.cs (TypeContainer.VerifyMembers): Added EmitContext + argument. + (MethodData.ApplyAttributes): Take an EmitContext instead of a + DeclSpace. + +2004-05-19 Marek Safar + + Fix bug #58688 (MCS does not report error when the same attribute + is assigned twice) + + * attribute.cs (Attribute.Emit): Distinction between null and default. + +2004-05-19 Raja R Harinath + + * cs-parser.jay (attribute): Create a GlobalAttribute for the case + of a top-level attribute without an attribute target. + * attribute.cs (Attribute.Error_AttributeConstructorMismatch): + Make non-static. + (Attribute.Conditional_GetConditionName), + (Attribute.Obsolete_GetObsoleteMessage): Update. + (Attribute.IndexerName_GetIndexerName): New. Attribute-specific + part of ScanForIndexerName. + (Attribute.CanIgnoreInvalidAttribute): New function. + (Attribute.ScanForIndexerName): Move to ... + (Attributes.ScanForIndexerName): ... here. + (Attributes.Attrs): Rename from now-misnamed AttributeSections. + (Attributes.Search): New internal variant that can choose not to + complain if types aren't resolved. The original signature now + complains. + (Attributes.GetClsCompliantAttribute): Use internal variant, with + complaints suppressed. + (GlobalAttribute.CheckAttributeType): Overwrite ds.NamespaceEntry + only if it not useful. + (CanIgnoreInvalidAttribute): Ignore assembly attribute errors at + top-level for attributes that are shared between the assembly + and a top-level class. + * parameter.cs (ImplicitParameter): Rename from ParameterAtribute. + * class.cs: Update to reflect changes. + (DefineIndexers): Fuse loops. + * codegen.cs (GetAssemblyName): Update to reflect changes. Accept + a couple more variants of attribute names. + +2004-05-18 Marek Safar + + Fix bug #52585 (Implemented explicit attribute declaration) + + * attribute.cs: + (Attributable.ValidAttributeTargets): New abstract method. It gets + list of valid attribute targets for explicit target declaration. + (Attribute.Target): It holds target itself. + (AttributeSection): Removed. + (Attribute.CheckTargets): New method. It checks whether attribute + target is valid for the current element. + + * class.cs: + (EventProperty): New class. For events that are declared like + property (with add and remove accessors). + (EventField): New class. For events that are declared like field. + class.cs + + * cs-parser.jay: Implemented explicit attribute target declaration. + + * class.cs, decl.cs, delegate.cs, enum.cs, parameter.cs: + Override ValidAttributeTargets. + + * parameter.cs: + (ReturnParameter): Class for applying custom attributes on + the return type. + (ParameterAtribute): New class. Class for applying custom + attributes on the parameter type. + +2004-05-17 Miguel de Icaza + + * class.cs (MemberBase.DoDefine): Pass UNSAFE on interface + definitions. + + (Method): Allow UNSAFE here. + + * modifiers.cs: Support unsafe reporting. + +2004-05-17 Marek Safar + + * decl.cs: Fix bug #58478. + +2004-05-17 Gonzalo Paniagua Javier + + * statement.cs: When checking for unreachable code on an EmptyStatement, + set the location. Fixes bug #58488. + +2004-05-13 Miguel de Icaza + + * driver.cs: Add -pkg handling. + + From Gonzalo: UseShelLExecute=false + +2004-05-12 Marek Safar + + * attribute.cs: + (Attribute.GetAttributeTargets): New method. Gets AttributeTargets + for attribute. + (Attribute.IsClsCompliaceRequired): Moved to base for better + accesibility. + (Attribute.UsageAttribute): New property for AttributeUsageAttribute + when attribute is AttributeUsageAttribute. + (Attribute.GetValidTargets): Simplified. + (Attribute.GetAttributeUsage): New method returns AttributeUsage + attribute for this type. + (Attribute.ApplyAttributes): Method renamed to Emit and make + non-static. + (GlobalAttributeSection): New class for special handling of global + attributes (assembly, module). + (AttributeSection.Emit): New method. + + * class.cs: Implemented Attributable abstract methods. + (MethodCore.LabelParameters): Moved to Parameter class. + (Accessor): Is back simple class. + (PropertyMethod): Implemented Attributable abstract class. + (DelegateMethod): Implemented Attributable abstract class. + (Event): New constructor for disctintion between normal Event + and Event with accessors. + + * cs-parser.jay: Used new Event ctor and GlobalAttributeSection. + + * codegen.cs, const.cs, decl.cs, delegate.cs: + (CommonAssemblyModulClass): Implemented Attributable abstract class + and simplified. + + * enum.cs: Implement IAttributeSupport interface. + (EnumMember): New class for emum members. Implemented Attributable + abstract class + + * parameter.cs: + (ParameterBase): Is abstract. + (ReturnParameter): New class for easier [return:] attribute handling. + + * typemanager.cs: Removed builder_to_attr. + +2004-05-11 Raja R Harinath + + Fix bug #57151. + * attribute.cs (Attribute.GetPositionalValue): New function. + * class.cs (TypeContainer.VerifyMembers): New function. + (TypeContainer.Emit): Use it. + (ClassOrStruct): New base class for Class and Struct. + (ClassOrStruct.ApplyAttributeBuilder): New function. Note if + StructLayout(LayoutKind.Explicit) was ascribed to the struct or + class. + (ClassOrStruct.VerifyMembers): If the struct is explicitly laid out, + then each non-static field should have a FieldOffset attribute. + Otherwise, none of the fields should have a FieldOffset attribute. + * rootcontext.cs (RootContext.ResolveCore): Resolve StructLayout + and FieldOffset attributes. + * typemanager.cs (TypeManager.struct_layout_attribute_type) + (TypeManager.field_offset_attribute_type): New core types. + (TypeManager.InitCoreTypes): Initialize them. + +2004-05-11 Michal Moskal + + * class.cs (Event.RemoveDelegateMethod.DelegateMethodInfo): + Return correct type. + From bug #58270. + +2004-05-09 Miguel de Icaza + + * expression.cs (Binary.DoNumericPromotions): 0 long constant can + be implicitly converted to ulong. + + * expression.cs: The logic for allowing operator &, | and ^ worked + was wrong, it worked before because we did not report an error in + an else branch. Fixes 57895. + + * class.cs: Applied patch from iain@mccoy.id.au Iain McCoy to + allow volatile fields to be reference types. + +2004-05-07 Miguel de Icaza + + * driver.cs: Add support for /debug- + +2004-05-07 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType, Attribute.ResolveType): + Add a 'complain' parameter to silence errors. + (Attribute.Resolve): Update to changes. Put in sanity check to catch + silently overlooked type-resolutions. + (Attribute.ScanForIndexerName, Attribute.DefinePInvokeMethod): Update + to reflect changes. + (Attributes.Search): New function. + (Attributes.Contains, Attributes.GetClsCompliantAttribute): Use Search. + (Attributes.GetAttributeFullName): Remove hack. + * class.cs (MethodCore.LabelParameters, MethodData.ApplyAttributes): + Update to reflect changes. + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Use Attributes.Search instead of nested loops. + +2004-05-07 Marek Safar + + * decl.cs: + (MemberCore.Flags): Extended for caching presence of CLSCompliantAttribute. + (MemberCore.VerifyClsCompliance): Implemented CS3019 error report. + (DeclSpace.GetClsCompliantAttributeValue): Returns simple bool. + + * report.cs: (Report.Warning): Renamed to Warning_T because of + parameter collision. + +2004-05-05 Raja R Harinath + + * expression.cs (MemberAccess.ResolveMemberAccess): + Exit with non-zero status after Report.Error. + * rootcontext.cs (RootContext.BootstrapCorlib_ResolveDelegate): + Likewise. + * typemanager.cs (TypeManager.CoreLookupType): Likewise. + +2004-05-04 Lluis Sanchez Gual + + * support.cs: Don't hang when the file is empty. + +2004-05-04 Lluis Sanchez Gual + + * support.cs: In SeekableStreamReader, compute the preamble size of the + underlying stream. Position changes should take into account that initial + count of bytes. + +2004-05-03 Todd Berman + + * driver.cs: remove unused GetSysVersion function. + +2004-05-03 Todd Berman + + * driver.cs: Remove the hack from saturday, as well as the hack + from jackson (LoadAssemblyFromGac), also adds the CWD to the + link_paths to get that bit proper. + +2004-05-01 Todd Berman + + * driver.cs: Try a LoadFrom before a Load, this checks the current + path. This is currently a bug in mono that is be fixed, however, this + provides a workaround for now. This will be removed when the bug + is fixed. + +2004-05-01 Sebastien Pouliot + + * CryptoConvert.cs: Updated to latest version. Fix issue with + incomplete key pairs (#57941). + +2004-05-01 Todd Berman + + * driver.cs: Remove '.' from path_chars, now System.* loads properly + from the GAC + +2004-04-30 Jackson Harper + + * codegen.cs: Open keys readonly. + +2004-04-30 Gonzalo Paniagua Javier + + * typemanager.cs: don't report cyclic struct layout when a struct + contains 2 or more fields of the same type. Failed for Pango.AttrShape + which has 2 Pango.Rectangle fields. + +2004-04-29 Ben Maurer + + * expression.cs: Handle IntPtr comparisons with IL code + rather than a method call. + +2004-04-29 Martin Baulig + + * ecore.cs (PropertyExpr.FindAccessor): New private method. Walk + the list of PropertyInfo's in class hierarchy and find the + accessor. Fixes #56013. + +2004-04-29 Martin Baulig + + * typemanager.cs (TypeManager.CheckStructCycles): Fixed. + +2004-04-29 Martin Baulig + + Applying a patch from Benjamin Jemlich . + + * ecore.cs (FieldExpr.AddressOf): Make this work for valuetypes. + +2004-04-29 Martin Baulig + + * class.cs (ConstructorInitializer.Resolve): Check whether the + parent .ctor is accessible. Fixes #52146. + +2004-04-29 Martin Baulig + + Applying a patch from Benjamin Jemlich . + + * statement.cs (Using.EmitLocalVariableDecls): Use + TypeManager.idisposable_type, not typeof (IDisposable). + (Foreach.EmitCollectionForeach): Added support for valuetypes. + +2004-04-29 Martin Baulig + + * class.cs (Event.Define): Don't emit the field and don't set + RTSpecialName and SpecialName for events on interfaces. Fixes + #57703. + +2004-04-29 Raja R Harinath + + Refactor Attribute.ApplyAttributes. + * attribute.cs (Attributable): New base class for objects that can + have Attributes applied on them. + (Attribute): Make AttributeUsage fields public. + (Attribute.GetFieldValue, Attribute.GetMarshal): Make non-static. + (Attribute.IsInternalCall): New property. + (Attribute.UsageAttr): Convert to a public read-only property. + (Attribute.CheckAttributeType): Use a DeclSpace, not an EmitContext. + (Attribute.ResolveType, Attribute.Resolve) + (Attribute.ScanForIndexerName): Update to reflect changes. + (Attribute.CheckAttributeTarget): Re-format. + (Attribute.ApplyAttributes): Refactor, to various + Attributable.ApplyAttributeBuilder methods. + * decl.cs (MemberCore): Make Attributable. + * class.cs (Accessor): Make Attributable. + (MethodData.ApplyAttributes): Use proper attribute types, not + attribute names. + (TypeContainer.LabelParameters): Pass Parameter to ApplyAttributes. + (TypeContainer.ApplyAttributeBuilder) + (Method.ApplyAttributeBuilder, Constructor.ApplyAttributeBuilder) + (Field.ApplyAttributeBuilder, Accessor.ApplyAttributeBuilder) + (PropertyBase.ApplyAttributeBuilder, Event.ApplyAttributeBuilder) + (Operator.ApplyAttributeBuilder): New factored-out methods. + * const.cs (Const.ApplyAttributeBuilder): Likewise. + * delegate.cs (Delegate.ApplyAttributeBuilder): Likewise. + * enum.cs (Enum.ApplyAttributeBuilder): Likewise. + * parameter.cs (ParameterBase): New Attributable base class + that can also represent Return types. + (Parameter): Update to the changes. + +2004-04-29 Jackson Harper + + * driver.cs: Prefer the corlib system version when looking for + assemblies in the GAC. This is still a hack, but its a better hack + now. + +2004-04-29 Marek Safar + + * decl.cs, enum.cs: Improved error 3005 reporting. + + * report.cs (SymbolRelatedToPreviousError): New method for error reporting. + (related_symbols): New private member for list of symbols + related to reported error/warning. + + * tree.cs: Do not use now obsolete Report.LocationOfPreviousError. + +2004-04-29 Martin Baulig + + * ecore.cs (Expression.Constantify): If we're an enum and + TypeManager.TypeToCoreType() doesn't give us another type, use + t.UnderlyingSystemType. Fixes #56178. + +2004-04-29 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Look over all our + interfaces and for each interface, only add members directly + declared in that interface. Fixes #53255. + +2004-04-28 Martin Baulig + + * expression.cs (ConditionalLogicalOperator): Use a temporary + variable for `left' to avoid that we evaluate it more than once; + bug #52588. + +2004-04-28 Martin Baulig + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Don't allow + `void[]' (CS1547). + +2004-04-28 Martin Baulig + + * statement.cs (LocalInfo.Resolve): Check whether the type is not + void (CS1547). + + * class.cs (MemberBase.CheckParameters, FieldBase.DoDefine): Check + whether the type is not void (CS1547). + +2004-04-28 Martin Baulig + + * expression.cs (Unary.DoResolveLValue): Override this and report + CS0131 for anything but Operator.Indirection. + +2004-04-28 Martin Baulig + + Committing a patch from Ben Maurer; see bug #50820. + + * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540 + check for classes. + + * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for + classes. + +2004-04-28 Martin Baulig + + Committing a patch from Ben Maurer; see bug #50820. + + * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540 + check for classes. + + * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for + classes. + +2004-04-28 Martin Baulig + + * statement.cs (Block.LookupLabel): Also lookup in implicit child blocks. + (Block.AddLabel): Call DoLookupLabel() to only search in the + current block. + +2004-04-28 Martin Baulig + + * cfold.cs (ConstantFold.BinaryFold): Added special support for + comparing StringConstants and NullLiterals in Equality and Inequality. + +2004-04-28 Jackson Harper + + * driver.cs: Attempt to load referenced assemblies from the + GAC. This is the quick and dirty version of this method that + doesnt take into account versions and just takes the first + canidate found. Will be good enough for now as we will not have more + then one version installed into the GAC until I update this method. + +2004-04-28 Martin Baulig + + * typemanager.cs (TypeManager.CheckStructCycles): New public + static method to check for cycles in the struct layout. + + * rootcontext.cs (RootContext.PopulateTypes): Call + TypeManager.CheckStructCycles() for each TypeContainer. + [Note: We only need to visit each type once.] + +2004-04-28 Martin Baulig + + * constant.cs (StringConstant.Emit): Emit Ldnull if we're null. + + * const.cs (Const.LookupConstantValue): Return a `bool' signalling + success and added `out object value'. Use a `bool resolved' field + to check whether we've already been called rather than + `ConstantValue != null' since this breaks for NullLiterals. + +2004-04-28 Raja R Harinath + + * driver.cs (Driver.MainDriver) [IsModuleOnly]: Open code the + setting of this flag, since the 'set' method may be non-public. + +2004-04-28 Raja R Harinath + + * flowanalysis.cs (FlowBranchingException.LookupLabel): Add a null + check on current_vector.Block. + +2004-04-27 Martin Baulig + + * expression.cs (BaseAccess.CommonResolve): Don't allow `base' in + a field initializer. Fixes #56459. + +2004-04-27 Martin Baulig + + * ecore.cs (PropertyExpr.DoResolve/DoResolveLValue): Check whether + we're not attempting to use an indexer. Fixes #52154. + +2004-04-27 Martin Baulig + + * statement.cs (Return): Don't create a return label if we don't + need it; reverts my change from January 20th. Thanks to Ben + Maurer for this. + +2004-04-27 Martin Baulig + + According to the spec, `goto' can only leave a nested scope, but + never enter it. + + * statement.cs (Block.LookupLabel): Only lookup in the current + block, don't recurse into parent or child blocks. + (Block.AddLabel): Check in parent and child blocks, report + CS0140/CS0158 if we find a duplicate. + (Block): Removed this indexer for label lookups. + (Goto.Resolve): Call LookupLabel() on our current FlowBranching; + this already does the error reporting for us. + + * flowanalysis.cs + (FlowBranching.UsageVector.Block): New public variable; may be null. + (FlowBranching.CreateSibling): Added `Block' argument. + (FlowBranching.LookupLabel): New public virtual method. Lookup a + label for the target of a `goto' and check whether we're not + leaving a `finally'. + +2004-04-27 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a finite loop block, also do the ALWAYS->SOMETIMES for throws (not + just for returns). + +2004-04-27 Martin Baulig + + * statement.cs (Block.AddLabel): Also check for implicit blocks + and added a CS0158 check. + +2004-04-27 Martin Baulig + + * flowanalysis.cs (FlowBranchingLoop): New class. + (FlowBranching.UsageVector.MergeJumpOrigins): Take a list of + UsageVector's instead of an ArrayList. + (FlowBranching.Label): Likewise. + (FlowBranching.UsageVector.MergeBreakOrigins): New method. + (FlowBranching.AddBreakVector): New method. + +2004-04-27 Miguel de Icaza + + * attribute.cs: Small regression fix: only convert the type if we + the type is different, fixes System.Drawing build. + +2004-04-27 Martin Baulig + + * attribute.cs (Attribute.Resolve): If we have a constant value + for a named field or property, implicity convert it to the correct + type. + +2004-04-27 Raja R Harinath + + * statement.cs (Block.Block): Implicit blocks share + 'child_variable_names' fields with parent blocks. + (Block.AddChildVariableNames): Remove. + (Block.AddVariable): Mark variable as "used by a child block" in + every surrounding block. + * ecore.cs (SimpleName.SimpleNameResolve): If the name has already + been used in a child block, complain about violation of "Invariant + meaning in blocks" rule. + * cs-parser.jay (declare_local_variables): Don't use + AddChildVariableNames. + (foreach_statement): Don't create an implicit block: 'foreach' + introduces a scope. + +2004-04-23 Miguel de Icaza + + * convert.cs (ImplicitNumericConversion): 0 is also positive when + converting from 0L to ulong. Fixes 57522. + +2004-04-22 Marek Safar + + * decl.cs (FindMemberToOverride): Fix wrong warning for case when + derived class hides via 'new' keyword field from base class (test-242.cs). + TODO: Handle this in the more general way. + + * class.cs (CheckBase): Ditto. + +2004-04-22 Marek Safar + + * decl.cs (caching_flags): New member for storing cached values + as bit flags. + (MemberCore.Flags): New enum where bit flags for caching_flags + are defined. + (MemberCore.cls_compliance): Moved to caching_flags. + (DeclSpace.Created): Moved to caching_flags. + + * class.cs: Use caching_flags instead of DeclSpace.Created + +2004-04-21 Miguel de Icaza + + * ecore.cs (PropertyExpr.GetAccesor): Only perform the 1540 check + if we are only a derived class, not a nested class. + + * typemanager.cs: Same as above, but do this at the MemberLookup + level (used by field and methods, properties are handled in + PropertyExpr). Allow for the qualified access if we are a nested + method. + +2004-04-21 Marek Safar + + * class.cs: Refactoring. + (IMethodData): New inteface; Holds links to parent members + to avoid member duplication (reduced memory allocation). + (Method): Implemented IMethodData interface. + (PropertyBase): New inner classes for get/set methods. + (PropertyBase.PropertyMethod): Implemented IMethodData interface + (Event): New inner classes for add/remove methods. + (Event.DelegateMethod): Implemented IMethodData interface. + + * cs-parser.jay: Pass DeclSpace to Event class for creation of valid + EmitContext (related to class.cs refactoring). + +2004-04-21 Raja R Harinath + + * delegate.cs (Delegate.VerifyApplicability): If the number of + arguments are the same as the number of parameters, first try to + verify applicability ignoring any 'params' modifier on the last + parameter. + Fixes #56442. + +2004-04-16 Raja R Harinath + + * class.cs (TypeContainer.AddIndexer): Use + 'ExplicitInterfaceName' to determine if interface name was + explicitly specified. 'InterfaceType' is not initialized at this time. + (TypeContainer.DefineIndexers): Remove use of temporary list. The + Indexers array is already in the required order. Initialize + 'IndexerName' only if there are normal indexers. + (TypeContainer.DoDefineMembers): Don't initialize IndexerName. + (TypeContainer.Emit): Emit DefaultMember attribute only if + IndexerName is initialized. + Fixes #56300. + +2004-04-15 Benjamin Jemlich + + * enum.cs (Enum.DefineType): Don't allow char as type for enum. + Fixes #57007 + +2004-04-15 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Check for ambiguous + attributes. + Fix for #56456. + + * attribute.cs (Attribute.Resolve): Check for duplicate named + attributes. + Fix for #56463. + +2004-04-15 Miguel de Icaza + + * iterators.cs (MarkYield): track whether we are in an exception, + and generate code accordingly. Use a temporary value to store the + result for our state. + + I had ignored a bit the interaction of try/catch with iterators + since their behavior was not entirely obvious, but now it is + possible to verify that our behavior is the same as MS .NET 2.0 + + Fixes 54814 + +2004-04-14 Miguel de Icaza + + * iterators.cs: Avoid creating temporaries if there is no work to + do. + + * expression.cs (ArrayAccess.EmitLoadOpcode): If dealing with + Enumerations, use TypeManager.EnumToUnderlying and call + recursively. + + Based on the patch from Benjamin Jemlich (pcgod@gmx.net), fixes + bug #57013 + + (This.Emit): Use EmitContext.EmitThis to emit our + instance variable. + + (This.EmitAssign): Ditto. + + * ecore.cs (FieldExpr.Emit): Remove RemapToProxy special + codepaths, we will move all the functionality into + Mono.CSharp.This + + (FieldExpr.EmitAssign): Ditto. + + This fixes several hidden bugs that I uncovered while doing a code + review of this today. + + * codegen.cs (EmitThis): reworked so the semantics are more clear + and also support value types "this" instances. + + * iterators.cs: Changed so that for iterators in value types, we + do not pass the value type as a parameter. + + Initialization of the enumerator helpers is now done in the caller + instead of passing the parameters to the constructors and having + the constructor set the fields. + + The fields have now `assembly' visibility instead of private. + +2004-04-11 Miguel de Icaza + + * expression.cs (Argument.Resolve): Check if fields passed as ref + or out are contained in a MarshalByRefObject. + + * typemanager.cs, rootcontext.cs: Add System.Marshalbyrefobject as + another compiler type. + +2004-04-06 Ben Maurer + + * class.cs (Indexer.Define): use the new name checking method. + Also, return false on an error. + * cs-tokenizer.cs (IsValidIdentifier): Checks for a valid identifier. + (is_identifier_[start/part]_character): make static. + +2004-04-10 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Do no append strings + twice: since we can be invoked more than once (array evaluation) + on the same concatenation, take care of this here. Based on a fix + from Ben (bug #56454) + +2004-04-08 Sebastien Pouliot + + * codegen.cs: Fix another case where CS1548 must be reported (when + delay-sign isn't specified and no private is available #56564). Fix + loading the ECMA "key" to delay-sign an assembly. Report a CS1548 + error when MCS is used on the MS runtime and we need to delay-sign + (which seems unsupported by AssemblyBuilder - see #56621). + +2004-04-08 Marek Safar + + * typemanager.cs (TypeManager.TypeToCoreType): Handle IntPtr too. + (TypeManager.ComputeNamespaces): Faster implementation for + Microsoft runtime. + + * compiler.csproj: Updated AssemblyName to mcs. + +2004-04-07 Miguel de Icaza + + * rootcontext.cs: Add new types to the boot resolution. + + * ecore.cs (TypeExpr.CanInheritFrom): Inheriting from + MulticastDelegate is not allowed. + + * typemanager.cs: Add new types to lookup: System.TypedReference + and ArgIterator. + + * paramter.cs (Parameter.Resolve): if we are an out/ref parameter, + check for TypedReference or ArgIterator, they are not allowed. + + * ecore.cs (BoxedCast): Set the eclass to ExprClass.Value, this + makes us properly catch 1510 in some conditions (see bug 56016 for + details). + +2004-04-06 Bernie Solomon + + * CryptoConvert.cs: update from corlib version + with endian fixes. + +2004-04-05 Miguel de Icaza + + * class.cs (Indexer.Define): Check indexername declaration + +2004-04-05 Marek Safar + + * attribute.cs (IsClsCompliant): Fixed problem with handling + all three states (compliant, not-compliant, undetected). + +2004-03-30 Marek Safar + + * attribute.cs (Attribute): Location is now public. + (Resolve): Store resolved arguments (pos_values) in attribute class. + Attribute extractors (now GetClsCompliantAttributeValue) can reuse them. + (GetClsCompliantAttributeValue): New method that gets + CLSCompliantAttribute value. + (GetClsCompliantAttribute): Returns CLSCompliantAttribute for DeclSpace + if exists else null. + (AttributeTester): New class for CLS-Compliant verification routines. + + * class.cs (Emit): Add CLS-Compliant verification. + (Method.GetSignatureForError): Implemented. + (Constructor.GetSignatureForError): Implemented + (Constructor.HasCompliantArgs): Returns if constructor has + CLS-Compliant arguments. + (Constructor.Emit): Override. + (Construcor.IsIdentifierClsCompliant): New method; For constructors + is needed to test only parameters. + (FieldBase.GetSignatureForError): Implemented. + (TypeContainer): New member for storing base interfaces. + (TypeContainer.FindMembers): Search in base interfaces too. + + * codegen.cs (GetClsComplianceAttribute): New method that gets + assembly or module CLSCompliantAttribute value. + (ResolveClsCompliance): New method that resolve CLSCompliantAttribute + for assembly. + (ModuleClass.Emit): Add error 3012 test. + + * const.cs (Emit): Override and call base for CLS-Compliant tests. + + * decl.cs (ClsComplianceValue): New enum that holds CLS-Compliant + state for all decl types. + (MemberCore.Emit): Emit is now virtual and call VerifyClsCompliance + if CLS-Compliant tests are required. + (IsClsCompliaceRequired): New method. Analyze whether code + must be CLS-Compliant. + (IsExposedFromAssembly): New method. Returns true when MemberCore + is exposed from assembly. + (GetClsCompliantAttributeValue): New method. Resolve CLSCompliantAttribute + value or gets cached value. + (HasClsCompliantAttribute): New method. Returns true if MemberCore + is explicitly marked with CLSCompliantAttribute. + (IsIdentifierClsCompliant): New abstract method. This method is + used to testing error 3005. + (IsIdentifierAndParamClsCompliant): New method. Common helper method + for identifier and parameters CLS-Compliant testing. + (VerifyClsCompliance): New method. The main virtual method for + CLS-Compliant verifications. + (CheckAccessLevel): In one special case (System.Drawing) was TypeBuilder + null. I don't know why is null (too many public members !). + (GetClsCompliantAttributeValue). New method. Goes through class hierarchy + and get value of first CLSCompliantAttribute that found. + + * delegate.cs (Emit): Override and call base for CLS-Compliant tests. + (VerifyClsCompliance): Override and add extra tests. + + * driver.cs (CSCParseOption): New command line options (clscheck[+|-]). + clscheck- disable CLS-Compliant verification event if assembly is has + CLSCompliantAttribute(true). + + * enum.cs (Emit): Override and call base for CLS-Compliant tests. + ApllyAttribute is now called in emit section as in the other cases. + Possible future Emit integration. + (IsIdentifierClsCompliant): New override. + (VerifyClsCompliance): New override. + (GetEnumeratorName): Returns full enum name. + + * parameter.cs (GetSignatureForError): Implemented. + + * report.cs (WarningData): New struct for Warning message information. + (LocationOfPreviousError): New method. + (Warning): New method. Reports warning based on the warning table. + (Error_T): New method. Reports error based on the error table. + + * rootcontext.cs (EmitCode): Added new Emit(s) because CLS-Compliant + verifications are done here. + + * tree.cs (RecordDecl): Used new LocationOfPreviousError method. + + * typemanager.cs (cls_compliant_attribute_type): New member thath holds + CLSCompliantAttribute. + (all_imported_types): New member holds all imported types from other + assemblies. + (LoadAllImportedTypes): New method fills static table with exported types + from all referenced assemblies. + (Modules): New property returns all assembly modules. + +2004-03-30 Miguel de Icaza + + * cs-parser.jay: Add a rule to catch wrong event syntax instead of + throwing a parser error. + + * ecore.cs (PropertyExpr.GetAccessor): Apply patch from Patrik Reali + which removes the hardcoded get_/set_ prefixes for properties, as + IL allows for the properties to be named something else. + + Bug #56013 + + * expression.cs: Do not override operand before we know if it is + non-null. Fix 56207 + +2004-03-29 Ben Maurer + + * typemanager.cs: support for pinned variables. + +2004-03-29 Ben Maurer + + * decl.cs, typemanager.cs: Avoid using an arraylist + as a buffer if there is only one result set. + +2004-03-29 Ben Maurer + + * expression.cs: Make sure you cant call a static method + with an instance expression, bug #56174. + +2004-03-29 Miguel de Icaza + + * class.cs (IsDuplicateImplementation): Improve error reporting to + flag 663 (method only differs in parameter modifier). + + * cs-tokenizer.cs: Do not require whitespace when a ( or " will do + in preprocessor directives. + + * location.cs (LookupFile): Allow for the empty path. + + * attribute.cs (DefinePInvokeMethod): Fix 56148; I would like a + better approach for some of that patch, but its failing with the + CharSet enumeration. For now try/catch will do. + + * typemanager.cs: Do not crash if a struct does not have fields. + Fixes 56150. + +2004-03-28 Ben Maurer + + * expression.cs: cs0213, cant fix a fixed expression. + fixes 50231. + +2004-03-28 Ben Maurer + + * cs-parser.jay: detect invalid embeded statements gracefully. + bug #51113. + +2004-03-28 Ben Maurer + + * ecore.cs, typemanager.cs: Correct impl of cs1540 check. + As a regex: + s/ + the invocation type may not be a subclass of the tye of the item/ + The type of the item must be a subclass of the invocation item. + /g + + Fixes bug #50820. + +2004-03-25 Sebastien Pouliot + + * attribute.cs: Added methods to get a string and a bool from an + attribute. Required to information from AssemblyKeyFileAttribute, + AttributeKeyNameAttribute (string) and AssemblyDelaySign (bool). + * codegen.cs: Modified AssemblyName creation to include support for + strongnames. Catch additional exceptions to report them as CS1548. + * compiler.csproj: Updated include CryptoConvert.cs. + * compiler.csproj.user: Removed file - user specific configuration. + * CryptoConvert.cs: New. A COPY of the class CryptoConvert from + Mono.Security assembly. The original class is maintained and tested in + /mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoConvert.cs. + * drivers.cs: Added support for /keyfile, /keycontainer and /delaysign + like CSC 8.0 (C# v2) supports. + * Makefile: Added CryptoConvert.cs to mcs sources. + * rootcontext.cs: Added new options for strongnames. + +2004-03-24 Ben Maurer + + * driver.cs: For --expect-error, report error code `2' + if the program compiled with no errors, error code `1' if + it compiled with an error other than the one expected. + +2004-03-24 Sebastien Pouliot + + * compiler.csproj: Updated for Visual Studio .NET 2003. + * compiler.csproj.user: Updated for Visual Studio .NET 2003. + * compiler.sln: Updated for Visual Studio .NET 2003. + +2004-03-24 Ravi Pratap M + + * expression.cs: Fix bug #47234. We basically need to apply the + rule that we prefer the conversion of null to a reference type + when faced with a conversion to 'object' (csc behaviour). + +2004-03-23 Ben Maurer + + * statement.cs: Shorter form for foreach, eliminates + a local variable. r=Martin. + +2004-03-23 Ben Maurer + + * constant.cs, ecore.cs, literal.cs: New prop IsZeroInteger that + checks if we can use brtrue/brfalse to test for 0. + * expression.cs: use the above in the test for using brtrue/brfalse. + cleanup code a bit. + +2004-03-23 Ben Maurer + + * expression.cs: Rewrite string concat stuff. Benefits: + + - "a" + foo + "b" + "c" becomes "a" + foo + "bc" + - "a" + foo + "b" + bar + "c" + baz ... uses concat (string []). + rather than a concat chain. + + * typemanager.cs: Add lookups for more concat overloads. + +2004-03-23 Ben Maurer + + * expression.cs: Emit shorter il code for array init. + + newarr + dup + // set 1 + + // set 2 + + newarr + stloc.x + + ldloc.x + // set 1 + + ldloc.x + // set 2 + +2004-03-22 Ben Maurer + + * statement.cs: Before, two switch blocks would be merged if the + total size of the blocks (end_item - begin_item + 1) was less than + two times the combined sizes of the blocks. + + Now, it will only merge if after the merge at least half of the + slots are filled. + + fixes 55885. + +2004-03-20 Atsushi Enomoto + + * class.cs : csc build fix for GetMethods(). See bug #52503. + +2004-03-20 Ben Maurer + + * expression.cs: Make sure fp comparisons work with NaN. + This fixes bug #54303. Mig approved this patch a long + time ago, but we were not able to test b/c the runtime + had a related bug. + +2004-03-19 Miguel de Icaza + + * ecore.cs (TypExpr.GetHashCode): implement this overload. + +2004-03-19 Martin Baulig + + * class.cs (MemberCore.IsDuplicateImplementation): Report the + error here and not in our caller. + +2004-03-19 Martin Baulig + + * interface.cs: Completely killed this file. + (Interface): We're now a TypeContainer and live in class.cs. + + * class.cs (TypeContainer.GetClassBases): Added `bool is_iface' + argument; we're now also called for interfaces. + (TypeContainer.DefineMembers): Allow this method being called + multiple times. + (TypeContainer.GetMethods): New public method; formerly known as + Interface.GetMethod(). This is used by PendingImplementation. + (TypeContainer.EmitDefaultMemberAttr): Moved here from Interface; + it's now private and non-static. + (Interface): Moved this here; it's now implemented similar to + Class and Struct. + (Method, Property, Event, Indexer): Added `bool is_interface' + argument to their .ctor's. + (MemberBase.IsInterface): New public field. + + * cs-parser.jay: Create normal Method, Property, Event, Indexer + instances instead of InterfaceMethod, InterfaceProperty, etc. + (opt_interface_base): Removed; we now use `opt_class_base' instead. + (InterfaceAccessorInfo): Create `Get' and `Set' Accessor's. + +2004-03-19 Martin Baulig + + * class.cs (MethodCore.IsDuplicateImplementation): New private + method which does the CS0111 checking. + (Method.CheckBase, Constructor.CheckBase, PropertyBase.CheckBase): + Use IsDuplicateImplementation(). + +2004-03-17 Ben Maurer + + * decl.cs (FindMemberToOverride): New method to find the correct + method or property to override in the base class. + * class.cs + - Make Method/Property use the above method to find the + version in the base class. + - Remove the InheritableMemberSignatureCompare as it is now + dead code. + + This patch makes large code bases much faster to compile, as it is + O(n) rather than O(n^2) to do this validation. + + Also, it fixes bug 52458 which is that nested classes are not + taken into account when finding the base class member. + + Reviewed/Approved by Martin. + +2004-03-17 Marek Safar + + * interface.cs: In all interface classes removed redundant + member initialization. + +2004-03-16 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Fix the CS0528 check. + +2004-03-15 Miguel de Icaza + + * decl.cs (DefineTypeAndParents): New helper method to define a + type's containers before the type itself is defined; This is a + bug exposed by the recent changes to Windows.Forms when an + implemented interface was defined inside a class that had not been + built yet. + + * modifiers.cs (MethodAttr): All methods in C# are HideBySig. + + (Check): Loop correctly to report errors modifiers + (UNSAFE was not in the loop, since it was the same as TOP). + + * interface.cs: Every interface member now takes a ModFlags, + instead of a "is_new" bool, which we set on the base MemberCore. + + Every place where we called "UnsafeOk" in the interface, now we + call the proper member (InterfaceMethod.UnsafeOK) instead to get + the unsafe settings from the member declaration instead of the + container interface. + + * cs-parser.jay (opt_new): Allow unsafe here per the spec. + + * pending.cs (TypeAndMethods): Add `get_indexer_name' and + `set_indexer_name' to the pending bits (one per type). + + We fixed a bug today that was picking the wrong method to + override, since for properties the existing InterfaceMethod code + basically ignored the method name. Now we make sure that the + method name is one of the valid indexer names. + +2004-03-14 Gustavo Giráldez + + * support.cs (SeekableStreamReader): Keep track of stream byte + positions and don't mix them with character offsets to the buffer. + + Patch from Gustavo Giráldez + +2004-03-15 Marek Safar + + * interface.cs (InterfaceSetGetBase): Removed double member + initialization, base class does it as well. + +2004-03-13 Martin Baulig + + * class.cs: Reverted Miguel's latest commit; it makes mcs crash + when compiling corlib. + +2004-03-13 Miguel de Icaza + + * convert.cs (ExplicitConversion): We were reporting an error on + certain conversions (object_type source to a value type, when the + expression was `null') before we had a chance to pass it through + the user defined conversions. + + * driver.cs: Replace / and \ in resource specifications to dots. + Fixes 50752 + + * class.cs: Add check for duplicate operators. Fixes 52477 + +2004-03-11 Miguel de Icaza + + * statement.cs (Switch.SimpleSwitchEmit): Deal with default labels + that are in the middle of the statements, not only at the end. + Fixes #54987 + + * class.cs (TypeContainer.AddField): No longer set the + `HaveStaticConstructor' flag, now we call it + `UserDefineStaticConstructor' to diferentiate the slightly + semantic difference. + + The situation is that we were not adding BeforeFieldInit (from + Modifiers.TypeAttr) to classes that could have it. + BeforeFieldInit should be set to classes that have no static + constructor. + + See: + + http://www.yoda.arachsys.com/csharp/beforefieldinit.html + + And most importantly Zoltan's comment: + + http://bugzilla.ximian.com/show_bug.cgi?id=44229 + + "I think beforefieldinit means 'it's ok to initialize the type sometime + before its static fields are used', i.e. initialization does not need + to be triggered by the first access to the type. Setting this flag + helps the JIT to compile better code, since it can run the static + constructor at JIT time, and does not need to generate code to call it + (possibly lots of times) at runtime. Unfortunately, mcs does not set + this flag for lots of classes like String. + + csc sets this flag if the type does not have an explicit static + constructor. The reasoning seems to be that if there are only static + initalizers for a type, and no static constructor, then the programmer + does not care when this initialization happens, so beforefieldinit + can be used. + + This bug prevents the AOT compiler from being usable, since it + generates so many calls to mono_runtime_class_init that the AOT code + is much slower than the JITted code. The JITted code is faster, + because it does not generate these calls if the vtable is type is + already initialized, which is true in the majority of cases. But the + AOT compiler can't do this." + +2004-03-10 Miguel de Icaza + + * class.cs (MethodData.Emit): Refactor the code so symbolic + information is generated for destructors; For some reasons we + were taking a code path that did not generate symbolic information + before. + +2004-03-11 Ben Maurer + + * class.cs: Create a Constructor.CheckBase method that + takes care of all validation type code. The method + contains some code that was moved from Define. + + It also includes new code that checks for duplicate ctors. + This fixes bug #55148. + +2004-03-09 Joshua Tauberer + + * expression.cs (ArrayCreation): Fix: More than 6 nulls in + a { ... }-style array creation invokes EmitStaticInitializers + which is not good for reference-type arrays. String, decimal + and now null constants (NullCast) are not counted toward + static initializers. + +2004-03-05 Martin Baulig + + * location.cs (SourceFile.HasLineDirective): New public field; + specifies whether the file contains or is referenced by a "#line" + directive. + (Location.DefineSymbolDocuments): Ignore source files which + either contain or are referenced by a "#line" directive. + +2004-02-29 Ben Maurer + + * class.cs (Method.CheckBase): Avoid using FindMembers, we have + direct access to our parent, so check the method inline there. + +2004-02-27 Ben Maurer + + * expression.cs (Invocation.EmitCall): Miguel's last commit + caused a regression. If you had: + + T t = null; + t.Foo (); + + In Foo the implict this would be null. + +2004-02-27 Miguel de Icaza + + * expression.cs (Invocation.EmitCall): If the method is not + virtual, do not emit a CallVirt to it, use Call. + + * typemanager.cs (GetFullNameSignature): Improve the method to + cope with ".ctor" and replace it with the type name. + + * class.cs (ConstructorInitializer.Resolve): Now the method takes + as an argument the ConstructorBuilder where it is being defined, + to catch the recursive constructor invocations. + +2004-02-26 Miguel de Icaza + + * iterators.cs (IteratorHandler.IsIEnumerator, IsIEnumerable): New + routines to check if a type is an enumerable/enumerator allow + classes that implement the IEnumerable or IEnumerator interfaces. + + * class.cs (Property, Operator): Implement IIteratorContainer, and + implement SetYields. + + (Property.Define): Do the block swapping for get_methods in the + context of iterators. We need to check if Properties also + include indexers or not. + + (Operator): Assign the Block before invoking the + OperatorMethod.Define, so we can trigger the Iterator code + replacement. + + * cs-parser.jay (SimpleIteratorContainer): new helper class. Both + Property and Operator classes are not created when we parse the + declarator but until we have the block completed, so we use a + singleton SimpleIteratorContainer.Simple to flag whether the + SetYields has been invoked. + + We propagate this setting then to the Property or the Operator to + allow the `yield' to function. + +2004-02-25 Marek Safar + + * codegen.cs: Implemented attribute support for modules. + New AssemblyClass, ModuleClass and CommonAssemblyModulClass for + Assembly/Module functionality. + + * attribute.cs, class.cs, cs-parser.jay, delegate.cs, driver.cs, enum.cs + interface.cs, rootcontext.cs, statement.cs, typemanager.cs: + Updated dependencies on CodeGen.ModuleBuilder and CodeGen.AssemblyBuilder. + +2004-02-16 Marek Safar + + * interface.cs (FindMembers): The operation is performed on all base + interfaces and not only on the first. It is required for future CLS Compliance patch. + +2004-02-12 Ben Maurer + + * statement.cs, codegen.cs: + This patch deals with patterns such as: + + public class List : IEnumerable { + + public MyEnumerator GetEnumerator () { + return new MyEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator () { + ... + } + + public struct MyEnumerator : IEnumerator { + ... + } + } + + Before, there were a few things we did wrong: + 1) we would emit callvirt on a struct, which is illegal + 2) we emited ldarg when we needed to emit ldarga + 3) we would mistakenly call the interface methods on an enumerator + type that derived from IEnumerator and was in another assembly. For example: + + public class MyEnumerator : IEnumerator + + Would have the interface methods called, even if there were public impls of the + method. In a struct, this lead to invalid IL code. + +2004-02-11 Marek Safar + + * const.cs: Const is now derived from FieldBase. Method EmitConstant name + renamed to Emit. + + * delegate.cs (Define): Fixed crash when delegate type is undefined. + +2004-02-11 Miguel de Icaza + + * cs-parser.jay: Fix small regression: we were not testing V2 + compiler features correctly. + + * interface.cs: If the emit context is null, then create one + +2004-02-09 Marek Safar + + * decl.cs (GetSignatureForError): New virtual method to get full name + for error messages. + + * attribute.cs (IAttributeSupport): New interface for attribute setting. + Now it is possible to rewrite ApplyAttributes method to be less if/else. + + * interface.cs : All InterfaceXXX classes are now derived from MemberCore. + Duplicated members and code in these classes has been removed. + Better encapsulation in these classes. + +2004-02-07 Miguel de Icaza + + * assign.cs (Assign.DoResolve): When dealing with compound + assignments, there is a new rule in ECMA C# 2.4 (might have been + there before, but it is documented here) that states that in: + + a op= b; + + If b is of type int, and the `op' is a shift-operator, then the + above is evaluated as: + + a = (int) a op b + + * expression.cs (Binary.ResolveOperator): Instead of testing for + int/uint/long/ulong, try to implicitly convert to any of those + types and use that in pointer arithmetic. + + * delegate.cs (Error_NoMatchingMethodForDelegate): Compute the + method to print information for from the type, not from the + null-method we were given. + +2004-02-01 Duncan Mak + + * cs-tokenizer.cs (get_cmd_arg): Skip over whitespace before + parsing for cmd, fixes bug #53694. + +2004-02-04 Marek Safar + + * class.cs, decl.cs: Fixed problem where IndexerName attribute was ignored + in the member name duplication tests. Property and operator name duplication + was missing too (error tests cs0102-{2,3,4,5}.cs, cs0111-{3,4}.cs). + +2004-02-03 Marek Safar + + * interface.cs (PopulateMethod): Fixed crash when interface method + returns not existing type (error test cs0246-3.cs). + +2004-02-02 Ravi Pratap M + + * cs-parser.jay (interface_accessors): Re-write actions to also + store attributes attached to get and set methods. Fix spelling + while at it. + + (inteface_property_declaration): Modify accordingly. + + (InterfaceAccessorInfo): New helper class to store information to pass + around between rules that use interface_accessors. + + * interface.cs (Emit): Apply attributes on the get and set + accessors of properties and indexers too. + + * attribute.cs (ApplyAttributes): Modify accordingly to use the + right MethodBuilder when applying attributes to the get and set accessors. + +2004-01-31 Miguel de Icaza + + * cs-tokenizer.cs: Applied patch from Marek Safar to fix bug 53386 + +2004-01-26 Miguel de Icaza + + * cs-tokenizer.cs: Handle #line hidden from PDC bits. + +2004-01-25 Miguel de Icaza + + * cs-parser.jay: Remove YIELD token, instead use the new grammar + changes that treat `yield' specially when present before `break' + or `return' tokens. + + * cs-tokenizer.cs: yield is no longer a keyword. + +2004-01-23 Marek Safar + + * cs-parser.jay, class.cs (DefineDefaultConstructor): Fixed ModFlags + setting for default constructors. + For default constructors are almost every time set wrong Modifier. The + generated IL code has been alright. But inside mcs this values was + wrong and this was reason why several of my CLS Compliance tests + failed. + +2004-01-22 Martin Baulig + + * cs-parser.jay (namespace_or_type_name): Return an Expression, + not a QualifiedIdentifier. This is what `type_name_expression' + was previously doing. + (type_name_expression): Removed; the code is now in + `namespace_or_type_name'. + (qualified_identifier): Removed, use `namespace_or_type_name' + instead. + (QualifiedIdentifier): Removed this class. + +2004-01-22 Martin Baulig + + * namespace.cs (NamespaceEntry.UsingAlias): Take an Expression, + not a string as alias name. + +2004-01-21 Miguel de Icaza + + * ecore.cs (FieldInfo.AddressOf): Revert patch from previous + #52730 bug, and instead compute correctly the need to use a + temporary variable when requesting an address based on the + static/instace modified of the field and the constructor. + +2004-01-21 Martin Baulig + + * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup in the current + class and namespace before looking up aliases. Fixes #52517. + +2004-01-21 Martin Baulig + + * flowanalysis.cs (UsageVector.Merge): Allow variables being + assinged in a 'try'; fixes exception4.cs. + +2004-01-21 Marek Safar + * class.cs : Implemented parameter-less constructor for TypeContainer + + * decl.cs: Attributes are now stored here. New property OptAttributes + + * delegate.cs, enum.cs, interface.cs: Removed attribute member. + + * rootcontext.cs, tree.cs: Now use parameter-less constructor of TypeContainer + +2004-01-21 Marek Safar + + * typemanager.cs (CSharpSignature): Now reports also inner class name. + (CSharpSignature): New method for indexer and property signature. + +2004-01-21 Marek Safar + + * pending.cs (IsVirtualFilter): Faster implementation. + +2004-01-21 Marek Safar + + * typemanager.cs: Avoid inclusion of same assembly more than once. + +2004-01-21 Marek Safar + + * cs-parser.jay: Fixed problem where the last assembly attribute + has been applied also to following declaration (class, struct, etc.) + +2004-01-21 Marek Safar + + * class.cs: Added error CS0538, CS0539 reporting. + Fixed crash on Microsoft runtime when field type is void. + + * cs-parser.jay: Added error CS0537 reporting. + + * pending.cs: Added error CS0535 reporting. + Improved error report for errors CS0536, CS0534. + +2004-01-20 Miguel de Icaza + + Merge a few bits from the Anonymous Method MCS tree. + + * statement.cs (ToplevelBlock): New class for toplevel methods, + will hold anonymous methods, lifted variables. + + * cs-parser.jay: Create toplevel blocks for delegates and for + regular blocks of code. + +2004-01-20 Martin Baulig + + * codegen.cs (EmitContext): Removed `InTry', `InCatch', + `InFinally', `InLoop', `TryCatchLevel', `LoopBeginTryCatchLevel' + and `NeedExplicitReturn'; added `IsLastStatement'. + (EmitContext.EmitTopBlock): Emit the explicit "ret" if we either + have a `ReturnLabel' or we're not unreachable. + + * flowanalysis.cs (FlowBranching.MergeChild): Actually merge the + child's reachability; don't just override ours with it. Fixes + #58058 (lluis's example). + (FlowBranching): Added public InTryOrCatch(), InCatch(), + InFinally(), InLoop(), InSwitch() and + BreakCrossesTryCatchBoundary() methods. + + * statement.cs (Return): Do all error checking in Resolve(). + Unless we are the last statement in a top-level block, always + create a return label and jump to it. + (Break, Continue): Do all error checking in Resolve(); also make + sure we aren't leaving a `finally'. + (Block.DoEmit): Set `ec.IsLastStatement' when emitting the last + statement in a top-level block. + (Block.Flags): Added `IsDestructor'. + (Block.IsDestructor): New public property. + +2004-01-20 Martin Baulig + + * statement.cs (Break.DoEmit): Set ec.NeedExplicitReturn; fixes #52427. + +2004-01-20 Martin Baulig + + * statement.cs (Statement.ResolveUnreachable): New public method. + (If, While): Do the dead-code elimination in Resolve(), not in Emit(). + (Block.Resolve): Resolve unreachable statements. + +2004-01-19 Ben Maurer + + * expression.cs: We need to fix the case where we do + not have a temp variable here. + + * assign.cs: Only expression compound assignments need + temporary variables. + +2004-01-19 Ben Maurer + + * flowanalysis.cs: Reduce memory allocation in a few ways: + - A block with no variables should not allocate a bit + vector for itself. + - A method with no out parameters does not need any tracking + for assignment of the parameters, so we need not allocate + any data for it. + - The arrays: + public readonly Type[] VariableTypes; + public readonly string[] VariableNames; + Are redundant. The data is already stored in the variable + map, so we need not allocate another array for it. + - We need to add alot of checks for if (params | locals) == null + due to the first two changes. + +2004-01-18 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): For ValueTypes that do not + implement IMemoryLocation, we store a copy on a local variable and + take the address of it. Patch from Benjamin Jemlich + + * cs-parser.jay: Applied patch from Ben Maurer to the "type" rule + to use a special "type_name_expression" rule which reduces the + number of "QualifiedIdentifier" classes created, and instead + directly creates MemberAccess expressions. + +2004-01-17 Miguel de Icaza + + * convert.cs: Applied patch from Benjamin Jemlich (pcgod@gmx.net) + that fixes #52853. Null literal assignment to ValueType + + * class.cs (MethodData.Emit): Instead of checking the name of the + method to determine if its a destructor, create a new derived + class from Method called Destructor, and test for that. + + * cs-parser.jay: Create a Destructor object instead of a Method. + + Based on a fix from Benjamin Jemlich (pcgod@gmx.net) + + Fixes: 52933 + +2004-01-16 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Perform an implicit + conversion from MethodGroups to their delegate types on the + Addition operation. + + * delegate.cs: Introduce a new class DelegateCreation that is the + base class for `NewDelegate' and `ImplicitDelegateCreation', + factor some code in here. + + * convert.cs (Convert.ImplicitConversionStandard): Add an implicit + conversion from MethodGroups to compatible delegate types. + + * ecore.cs (Expression.Resolve): Do not flag error 654 + (Methodgroupd needs parenthesis) if running on the V2 compiler, as + we allow conversions from MethodGroups to delegate types now. + + * assign.cs (Assign.DoResolve): Do not flag errors on methodgroup + assignments in v2 either. + +2004-01-10 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): Fix generated IL for accessing + static read-only fields in ctors. + + Applied patch from Benjamin Jemlich + + * expression.cs (UnaryMutator): Avoid leaking local variables. + +2004-01-09 Miguel de Icaza + + * cs-tokenizer.cs (IsCastToken): Allow the various native types + here to return true, as they can be used like this: + + (XXX) int.MEMBER () + + Fixed 49836 and all the other dups + +2004-01-09 Zoltan Varga + + * driver.cs: Implement /win32res and /win32icon. + +2004-01-08 Miguel de Icaza + + * cs-parser.jay: Add a rule to improve error handling for the + common mistake of placing modifiers after the type. + +2004-01-07 Miguel de Icaza + + * cs-parser.jay (interface_event_declaration): Catch + initialization of events on interfaces, and report cs0068 + + * cs-parser.jay (interface_event_declaration): Catch + initialization of events. + + * ecore.cs: Better report missing constructors. + + * expression.cs (Binary.ResolveOperator): My previous bug fix had + the error reporting done in the wrong place. Fix. + + * expression.cs (Binary.ResolveOperator): Catch the + operator + (E x, E y) error earlier, and later allow for implicit + conversions in operator +/- (E e, U x) from U to the underlying + type of E. + + * class.cs (TypeContainer.DefineDefaultConstructor): Fix bug + 52596, if the container class is abstract, the default constructor + is protected otherwise its public (before, we were always public). + + * statement.cs (Fixed.Resolve): Catch a couple more errors in the + fixed statement. + + (Using.EmitLocalVariableDecls): Applied patch from Benjamin + Jemlich that fixes bug #52597, MCS was generating invalid code for + idisposable structs. Thanks to Ben for following up with this + bug as well. + +2004-01-06 Miguel de Icaza + + * driver.cs: Allow assemblies without code to be generated, fixes + 52230. + +2004-01-07 Nick Drochak + + * attribute.cs: Remove unneeded catch variables. Eliminates a warning. + +2004-01-05 Miguel de Icaza + + * cs-parser.jay: Add rules to improve error reporting if fields or + methods are declared at the namespace level (error 116) + + * Add rules to catch event add/remove + +2004-01-04 David Sheldon + + * expression.cs: Added matching ")" to error message for + CS0077 + +2004-01-03 Todd Berman + + * ecore.cs, attribute.cs: + Applying fix from #52429. + +2004-01-03 Ben Maurer + + * ecore.cs, expression.cs, statement.cs: + Total rewrite of how we handle branching. We + now handle complex boolean expressions with fewer + jumps. As well if (x == 0) no longer emits a ceq. + + if (x is Foo) is much faster now, because we generate + better code. + + Overall, we get a pretty big improvement on our benchmark + tests. The code we generate is smaller and more readable. + + I did a full two-stage bootstrap. The patch was reviewed + by Martin and Miguel. + +2004-01-03 Ben Maurer + + * cs-parser.jay: Make primary_expression not take a QI. + we dont need this because the member_access rule covers + us here. So we replace the rule with just IDENTIFIER. + + This has two good effects. First, we remove a s/r conflict. + Second, we allocate many fewer QualifiedIdentifier objects. + +2004-01-03 Ben Maurer + + * attribute.cs: Handle MarshalAs attributes as pseudo, and + set the correct information via SRE. This prevents + hanging on the MS runtime. Fixes #29374. + +2004-01-03 Ben Maurer + + * convert.cs: correctly handle conversions to value types + from Enum and ValueType as unboxing conversions. + + Fixes bug #52569. Patch by Benjamin Jemlich. + +2004-01-02 Ravi Pratap + + * expression.cs (BetterConversion): Prefer int -> uint + over int -> ulong (csc's behaviour). This fixed bug #52046. + +2004-01-02 Ben Maurer + + * decl.cs (MemberCache.FindMembers): now returns a + MemberInfo []. + + * typemanager.cs: In general, go with with ^^. + (CopyNewMethods): take an IList. + (RealMemberLookup): Only allocate an arraylist + if we copy from two sets of methods. + + This change basically does two things: + 1) Fewer array lists allocated due to CopyNewMethods. + 2) the explicit cast in MemberList costed ALOT. + +2004-01-02 Zoltan Varga + + * cs-tokenizer.cs (consume_identifier) driver.cs: Cache identifiers in + a hashtable to avoid needless string allocations when an identifier is + used more than once (the common case). + +2004-01-01 Ben Maurer + + * pending.cs: MS's TypeBuilder.GetInterfaces () + is broken, it will not return anything. So, we + have to use the information we have in mcs to + do the task. + + * typemanager.cs: Add a cache for GetInterfaces, + since this will now be used more often (due to ^^) + + (GetExplicitInterfaces) New method that gets the + declared, not effective, interfaces on a type + builder (eg, if you have interface IFoo, interface + IBar, Foo : IFoo, Bar : Foo, IBar, GetExplInt (Bar) == + { IBar }. + + This patch makes MCS able to bootstrap itself on + Windows again. + +2004-01-01 Ben Maurer + + * expression.cs: Remove the Nop's that Miguel put + in by mistake. + +2003-12-31 Ben Maurer + + * report.cs, codegen.cs: Give the real stack trace to + the error when an exception is thrown. + +2003-12-31 Ben Maurer + + * decl.cs: only allocate hashtables for ifaces if + it is an iface! + +2003-12-31 Ben Maurer + + * expression.cs: fix the error from cs0121-2.cs + (a parent interface has two child interfaces that + have a function with the same name and 0 params + and the function is called through the parent). + +2003-12-30 Ben Maurer + + * class.cs, rootcontext.cs, typmanager.cs: do not + leak pointers. + +2003-12-28 Ben Maurer + + * codegen.cs: remove stack for the ec flow branching. + It is already a linked list, so no need. + +2003-12-27 Ben Maurer + + * Makefile: Allow custom profiler here. + +2003-12-26 Ben Maurer + + * typemanager.cs (LookupType): + - Use a static char [], because split takes + a param array for args, so it was allocating + every time. + - Do not store true in a hashtable, it boxes. + +2003-12-26 Ben Maurer + + * flowanalysis.cs: bytify common enums. + +2003-12-25 Ben Maurer + + * modifiers.cs: Add a new set of flags for the + flags allowed on explicit interface impls. + * cs-parser.jay: catch the use of modifiers in + interfaces correctly. + * class.cs: catch private void IFoo.Blah (). + + All related to bug #50572. + +2003-12-25 Ben Maurer + + * decl.cs: Rewrite the consistant accessability checking. + Accessability is not linear, it must be implemented in + a tableish way. Fixes #49704. + +2003-12-25 Ben Maurer + + * expression.cs: Handle negation in a checked context. + We must use subtraction from zero. Fixes #38674. + +2003-12-23 Ben Maurer + + * class.cs: Ignore static void main in DLLs. + * rootcontext.cs: Handle the target type here, + since we are have to access it from class.cs + * driver.cs: account for the above. + +2003-12-23 Ben Maurer + + * report.cs: Give line numbers and files if available. + +2003-12-20 Zoltan Varga + + * driver.cs: Implement /addmodule. + + * typemanager.cs: Change 'modules' field so it now contains Modules not + ModuleBuilders. + +2003-12-20 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Don't do the CS0649 check here. + (FieldBase.IsAssigned): Removed this field. + (FieldBase.SetAssigned): New public method. + (TypeContainer.Emit): Make the CS0169/CS0649 checks actually work. + +2003-12-20 Martin Baulig + + * expression.cs (LocalVariableReference.DoResolve): Don't set + `vi.Used' if we're called from DoResolveLValue(). + + * statement.cs (Block.DoResolve): `ec.DoEndFlowBranching()' now + returns the usage vector it just merged into the current one - + pass this one to UsageWarning(). + (Block.UsageWarning): Take the `FlowBranching.UsageVector' instead + of the `EmitContext', don't call this recursively on our children. + +2003-12-19 Zoltan Varga + + * driver.cs: Implement /target:module. + +2003-12-18 Zoltan Varga + + * support.cs (CharArrayHashtable): New helper class. + + * cs-tokenizer.cs: Store keywords in a hashtable indexed by + char arrays, not strings, so we can avoid creating a string in + consume_identifier if the identifier is a keyword. + +2003-12-16 Martin Baulig + + * statement.cs (LocalInfo.Assigned): Removed this property. + (LocalInfo.Flags): Removed `Assigned'. + (LocalInfo.IsAssigned): New public method; takes the EmitContext + and uses flow analysis. + (Block.UsageWarning): Made this method private. + (Block.Resolve): Call UsageWarning() if appropriate. + + * expression.cs (LocalVariableReference.DoResolve): Always set + LocalInfo.Used here. + +2003-12-13 Martin Baulig + + * statement.cs (Statement.DoEmit, Statement.Emit): Don't return + any value here; we're now using flow analysis to figure out + whether a statement/block returns a value. + +2003-12-13 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeFinallyOrigins): Made this + working again. + (FlowBranching.MergeFinally): Don't call + `branching.CheckOutParameters()' here, this is called in + MergeTopBlock(). + (FlowBranchingException.AddSibling): Call MergeFinallyOrigins() + when adding the `finally' vector. + +2003-12-13 Martin Baulig + + * flowanalysis.cs + (UsageVector.MergeJumpOrigins, FlowBranching.Label): Make this + actually work and also fix #48962. + +2003-12-12 Ben Maurer + + * decl.cs: Do not check System.Object for nested types, + since we know it does not have any. Big bang for buck: + + BEFORE: + Run 1: 8.35 seconds + Run 2: 8.32 seconds + corlib: 17.99 seconds + AFTER: + Run 1: 8.17 seconds + Run 2: 8.17 seconds + corlib: 17.39 seconds + +2003-12-11 Ben Maurer + + * class.cs (FindMembers): Allocate arraylists on demand. Most of the + time we are returning 0 members, so we save alot here. + +2003-12-11 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeResult): Renamed this back to + `MergeChild()', also just take the `FlowBranching' as argument; + call Merge() on it and return the result. + (FlowBranching.Merge): We don't need to do anything if we just + have one sibling. + +2003-12-11 Martin Baulig + + * flowanalysis.cs: Use a list of `UsageVector's instead of storing + them in an `ArrayList' to reduce memory usage. Thanks to Ben + Maurer for this idea. + +2003-12-11 Martin Baulig + + * flowanalysis.cs (MergeResult): This class is now gone; we now + use the `UsageVector' for this. The reason for this is that if a + branching just has one sibling, we don't need to "merge" them at + all - that's the next step to do. + (FlowBranching.Merge): We now return a `UsageVector' instead of a + `MergeResult'. + +2003-12-11 Martin Baulig + + Reworked flow analyis and made it more precise and bug-free. The + most important change is that we're now using a special `Reachability' + class instead of having "magic" meanings of `FlowReturns'. I'll + do some more cleanups and optimizations and also add some more + documentation this week. + + * flowanalysis.cs (Reachability): Added `Throws' and `Barrier'; + largely reworked this class. + (FlowReturns): Removed `Unreachable' and `Exception'; we now use + the new `Reachability' class instead of having "magic" values here. + (FlowBranching): We're now using an instance of `Reachability' + instead of having separate `Returns', `Breaks' etc. fields. + + * codegen.cs (EmitContext.EmitTopBlock): Set `has_ret' solely + based on flow analysis; ignore the return value of block.Emit (). + +2003-12-10 Zoltan Varga + + * driver.cs typemanager.cs: Find the mono extensions to corlib even + if they are private. + +2003-12-09 Martin Baulig + + * flowanalyis.cs (FlowBranching.Return, Goto, Throw): Removed; + call them directly on the UsageVector. + +2003-12-09 Martin Baulig + + * flowanalysis.cs (FlowBranching.MergeChild, MergeTopBlock): + Changed return type from `FlowReturns' to `Reachability'. + +2003-12-09 Martin Baulig + + * flowanalysis.cs (FlowBranching.Reachability): New sealed class. + (FlowBranching.MergeResult): Replaced the `Returns', `Breaks' and + `Reachable' fields with a single `Reachability' one. + +2003-12-08 Ben Maurer + + * class.cs (FindMembers): Remove foreach's. + + Bootstrap times: + + BEFORE + Run 1: 8.74 seconds + Run 2: 8.71 seconds + + AFTER + Run 1: 8.64 seconds + Run 2: 8.58 seconds + + +2003-12-08 Ben Maurer + + * cs-parser.jay: + * gen-treedump.cs: + * statement.cs: + This patch does a few things: + 1. EmptyStatement is now a singleton, so it is never reallocated. + 2. All blah is EmptyStatement constructs have been changed to + blah == EmptyStatement.Value, which is much faster and valid + now that EmptyStatement is a singleton. + 3. When resolving a block, rather than allocating a new array for + the non-empty statements, empty statements are replaced with + EmptyStatement.Value + 4. Some recursive functions have been made non-recursive. + Mainly the performance impact is from (3), however (1) and (2) are needed for + this to work. (4) does not make a big difference in normal situations, however + it makes the profile look saner. + + Bootstrap times: + + BEFORE + 9.25user 0.23system 0:10.28elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k + 9.34user 0.13system 0:10.23elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k + Total memory allocated: 56397 KB + + AFTER + 9.13user 0.09system 0:09.64elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k + 8.96user 0.24system 0:10.13elapsed 90%CPU (0avgtext+0avgdata 0maxresident)k + Total memory allocated: 55666 KB + +2003-12-08 Ben Maurer + + * support.cs: Rewrite DoubleHash to use its own impl. Is faster + than the hashtable in a hashtable version + + * decl.cs: Right now, whenever we try to lookup a type inside a namespace, + we always end up concating a string. This results in a huge perf + loss, because many strings have to be tracked by the GC. In this + patch, we first use a hashtable that works with two keys, so that + the strings do not need to be concat'ed. + + Bootstrap times: + BEFORE + Run 1: 8.74 seconds + Run 2: 8.71 seconds + + AFTER + Run 1: 8.65 seconds + Run 2: 8.56 seconds + +2003-12-08 Ben Maurer + + * Makefile: Add a new target `do-time' that does a quick and simple + profile, leaving easy to parse output. + +2003-12-08 Zoltan Varga + + * codegen.cs (Init): Create the dynamic assembly with + AssemblyBuilderAccess.Save, to enable some optimizations in the runtime. + +2003-12-02 Ben Maurer + + * support.cs: Make the PtrHashtable use only one + instance of its comparer. + +2003-11-30 Zoltan Varga + + * typemanager.cs: Fix lookup of GetNamespaces. + +2003-11-29 Miguel de Icaza + + * expression.cs: Removed redundant line. + + * statement.cs (Block.Resolve, Block.Emit): Avoid foreach on + ArrayLists, use for loops with bounds. + + * flowanalysis.cs (FlowBranching.Merge): Avoid foreach on + arraylist. + + * expression.cs (Invocation.OverloadResolve): Avoid foreach on + arraylists, use for loop with bounds. + + The above three changes give us a 0.071 second performance + improvement out of 3.294 seconds down to 3.223. On my machine + the above changes reduced the memory usage by 1,387 KB during + compiler bootstrap. + + * cs-parser.jay (QualifiedIdentifier): New class used to represent + QualifiedIdentifiers. Before we created a new string through + concatenation, and mostly later on, the result would be + manipulated by DecomposeQI through string manipulation. + + This reduced the compiler memory usage for bootstrapping from + 59380 KB to 59007 KB on my machine, 373 KB, and also reduced the + compile times in 0.05 seconds. + +2003-11-28 Dick Porter + + * support.cs: Do string compares with the Invariant culture. + + * rootcontext.cs: + * gen-treedump.cs: + * expression.cs: + * driver.cs: + * decl.cs: + * codegen.cs: + * class.cs: Use the char forms of IndexOf and LastIndexOf, so that + the comparison is done with the Invariant culture. + +2003-11-27 Miguel de Icaza + + * statement.cs (Foreach.TryType): Use DeclaredOnly to find the + GetEnumerator method. + + (ProbeCollectionType): Iterate starting at the most specific type + upwards looking for a GetEnumerator + + * expression.cs: Shift count can be up to 31 for int/uint and 63 + for long/ulong. + +2003-11-26 Miguel de Icaza + + * statement.cs (Block.LookupLabel): Also look for the label on the + children blocks. Use a hash table to keep track of visited + nodes. + + * cfold.cs (IntConstant to UIntConstant mapping): Only return if + we actually did transform the other operand, otherwise fall back + to the common codepath that casts to long. + + * cs-tokenizer.cs: Use the same code pattern as the int case. + Maybe I should do the parsing myself, and avoid depending on the + Parse routines to get this done. + +2003-11-25 Miguel de Icaza + + * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti), + which fixes bug 51347. This time test it. + + * expression.cs: Make TypeOfVoid derive from TypeOf, so code in + attributes for example can not tell the difference between these. + The difference was only a syntax feature of the language. + + * attribute.cs: Apply attributes to delegates. + + * delegate.cs: Call the apply attributes method. + +2003-11-24 Miguel de Icaza + + * convert.cs (TryImplicitIntConversion): One line bug fix: we were + comparing 0 vs Byte.MinValue, not the value + + (ImplicitConversionRequired): When reporting a conversion error, + use error 31 to print out the constant error instead of the + simpler 29. + + * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti), + which fixes bug 51347. + +2003-11-22 Miguel de Icaza + + * driver.cs: Applied patch from gert.driesen@pandora.be (Gert Driesen) + which fixes the -warnaserror command line option. + +2003-11-21 Miguel de Icaza + + * cfold.cs (DoNumericPromotions): During constant folding of + additions on UIntConstant, special case intconstants with + IntConstants like we do on the expression binary operator. + +2003-11-12 Miguel de Icaza + + * convert.cs (ImplicitReferenceConversion): We were missing a case + (System.Enum are not value types or class types, so we need to + classify them separatedly). + + * driver.cs: We do not support error 2007. + +2003-11-12 Jackson Harper + + * driver.cs: Use corlib.dll or mscorlib.dll when looking up the + system directory. Also use the full file name so users can + libraries names mscorlib-o-tron.dll in a non system dir. + +2003-11-10 Martin Baulig + + * typemanager.cs (TypeManager.ResolveExpressionTypes): Removed. + (TypeManager.InitCoreTypes): Initialize them here, but instead of + calling `ResolveType()' on them, directly assign their `Type'. + +2003-11-08 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Use TypeExpr's for the + return value and the `out parent' parameter. + (TypeContainer.DefineType): Moved the CS0644 check into + GetClassBases(). Don't pass the interface types to the + `builder.DefineType()'/`builder.DefineNestedType()', but resolve + them later and then call `TypeBuilder.AddInterfaceImplementation()'. + + * ecore.cs (TypeExpr.IsAttribute): New property. + (TypeExpr.GetInterfaces): New method. + + * interface.cs (Interface.GetInterfaceTypeByName): Return a + TypeExpr instead of a Type. + (Interface.GetInterfaceBases): Return TypeExpr's instead of Type's. + (Interface.DefineType): Don't pass the interface types to the + `builder.Definetype()'/`builder.DefineNestedType()', but resolve + them later and then call `TypeBulider.AddInterfaceImplementation()'. + + * typemanager.cs (TypeManager.AddUserType): Take a `TypeExpr[]' + instead of a `Type[]'. + (TypeManager.RegisterBuilder): Likewise. + (TypeManager.AddUserInterface): Likewise. + (TypeManager.ExpandInterfaces): Take a `Type[]' instead of a + `Type[]' and also return a `TypeExpr[]'. + (TypeManager.GetInterfaces): Return a `TypeExpr[]'. + +2003-11-08 Martin Baulig + + * decl.cs (DeclSpace.ResolveTypeExpr): Return a TypeExpr, not an + Expression. + +2003-11-08 Martin Baulig + + * decl.cs (DeclSpace.GetTypeResolveEmitContext): Call + TypeManager.ResolveExpressionTypes(). + + * ecore.cs (Expression.ResolveAsTypeTerminal): Return a TypeExpr + instead of an Expression. + (TypeExpr): This is now an abstract base class for `TypeExpression'. + (TypeExpression): New public class; formerly known as `TypeExpr'. + + * expression.cs (ComposedCast): Derive from TypeExpr. + + * typemanager.cs (TypeManager.system_*_expr): These are now + TypExpr's instead of Expression's. + (TypeManager.ResolveExpressionTypes): New public static function; + called from DeclSpace.GetTypeResolveEmitContext() to resolve all + of them. + +2003-11-06 Miguel de Icaza + + * expression.cs (New.DoResolve): Do not dereference value that + might be a null return. + + * statement.cs (Block.EmitMeta): Use the Const.ChangeType to make + sure that the constant value has the right type. Fixes an + unreported bug, similar to 50425. + + * const.cs (Const.LookupConstantValue): Call + ImplicitStandardConversionExists before doing a conversion to + avoid havng the TypeManager.ChangeType do conversions. + + Reduced the number of casts used + + (Const.ChangeType): New routine to enable reuse of the constant + type changing code from statement. + + * typemanager.cs (ChangeType): Move common initialization to + static global variables. + + Fixes #50425. + + * convert.cs (ImplicitReferenceConversion): Somehow we allowed + every value type to go through, even if it was void. Fix that. + + * cs-tokenizer.cs: Use is_identifier_start_character on the start + character of the define, and the is_identifier_part_character for + the rest of the string. + +2003-11-05 Miguel de Icaza + + * expression.cs (UnaryMutator.EmitCode): When I updated + LocalVariableReference.DoResolve, I overdid it, and dropped an + optimization done on local variable references. + +2003-11-04 Miguel de Icaza + + * ecore.cs: Convert the return from Ldlen into an int. + +2003-10-20 Miguel de Icaza + + * decl.cs (DeclSpace.GetAccessLevel): Handle NotPublic case for + the accessibility, this is a special case for toplevel non-public + classes (internal for instance). + +2003-10-20 Nick Drochak + + * ecore.cs: Fix typo and build. Needed another right paren. + +2003-10-19 Miguel de Icaza + + * ecore.cs: Applied fix from Ben Maurer. We were handling in the + `internal' case regular and protected, but not allowing protected + to be evaluated later. Bug 49840 + +2003-10-15 Miguel de Icaza + + * statement.cs (Switch.TableSwitchEmit): Compare the upper bound + to kb.Nlast, and not the kb.nFirst to isolate the switch + statement. + + Extract the underlying type, so enumerations of long/ulong are + treated like long/ulong. + +2003-10-14 Miguel de Icaza + + * expression.cs (New): Overload the meaning of RequestedType to + track the possible creation of the NewDelegate type, since + DoResolve is invoked more than once for new constructors on field + initialization. + + See bugs: #48800 and #37014 + + * cs-parser.jay (declare_local_constants): Take an arraylist + instead of a single constant. + + (local_constant_declaration): It should take a + constant_declarators, not a constant_declarator. Fixes 49487 + + * convert.cs: Fix error report. + +2003-10-13 Jackson Harper + + * typemanager.cs (TypeToCoreType): Add float and double this fixes + bug #49611 + +2003-10-09 Martin Baulig + + * class.cs (MethodCore): Added additional `DeclSpace ds' argument + to the .ctor. + (MethodCore.DoDefineParameters): Removed the TypeContainer + argument; use the DeclSpace which was passed to the .ctor instead. + (MethodCore.CheckParameter): Take a DeclSpace instead of a + TypeContainer; we only need a DeclSpace here. + +2003-10-09 Martin Baulig + + * class.cs (MethodData): Added additional `DeclSpace ds' argument + to the .ctor. + (MethodData.Define, MethodData.Emit): Pass the `ds' to the + EmitContext's .ctor. + +2003-10-09 Martin Baulig + + * decl.cs (DeclSpace.AsAccessible): Moved here from TypeContainer. + (AccessLevel, CheckAccessLevel, GetAccessLevel): They're used by + AsAccessible(), moved them as well. + + * class.cs (TypeContainer.AsAccessible): Moved to DeclSpace. + +2003-10-08 Atsushi Enomoto + + * cs-parser.jay : Renamed yyName to yyNames related to jay. + +2003-10-07 Miguel de Icaza + + * expression.cs (Binary.Emit.GreatherThanOrEqual): Fix the code + generation for >=, as spotted by Paolo, bug 48679. + Patch from David Waite. + + * cs-tokenizer.cs: Add handling for #pragma. + + * cs-parser.jay: Allow for both yield and yield return in the + syntax. The anti-cobolization of C# fight will go on! + + * class.cs (TypeBuilder.DefineType): Catch error condition here + (Parent.DefineType erroring out and returning null). + + * expression.cs (ArrayCreation.EmitDynamicInitializers): When + coping with enumerations variables, we were mistakenly processing + them as a regular value type instead of built-in types. Fixes the + bug #48063 + + * typemanager.cs (IsBuiltinOrEnum): New method. + +2003-09-30 Miguel de Icaza + + * cs-parser.jay: Upgrade: yield now needs the return clause. + +2003-09-19 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Take a + `MemberCache parent' argument. Normally, an interface doesn't + have a parent type except System.Object, but we use this in gmcs + for generic type parameters. + +2003-09-18 Martin Baulig + + * typemanager.cs (TypeHandle.ctor): Set `IsInterface' solely based + on `type.IsInterface'; don't check whether the type has a parent + to determine whether it's an interface. + +2003-09-15 Martin Baulig + + * class.cs (TypeContainer.DefineType): Added an error flag to + avoid reporting duplicate CS0146's ("class definition is + circular."). + + * driver.cs (Driver.MainDriver): Abort if + RootContext.ResolveTree() reported any errors. + +2003-09-07 Martin Baulig + + * report.cs (Error, Warning): Added overloaded versions which take + a `params object[] args' and call String.Format(). + +2003-09-07 Martin Baulig + + * decl.cs (DeclSpace..ctor): Don't call + NamespaceEntry.DefineName() here; do it in RecordDecl() which is + called from Tree.RecordDecl(). Fixes the CS0101 reporting. + (DeclSpace.RecordDecl): New method. + + * tree.cs (Tree.RecordDecl): Call ds.RecordDecl(). + +2003-09-02 Ravi Pratap + + * attribute.cs (CheckAttributeTarget): Ensure that we allow return + value attributes to be applied to ParameterBuilders. + + * class.cs (MethodCore.LabelParameters): Make static and more + generic so that it can be used from other places - like interface + methods, for instance. + + * interface.cs (Interface.Emit): Call LabelParameters before + emitting attributes on the InterfaceMethod. + +2003-08-26 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Look for members before + resolving aliases; fixes #47927. + +2003-08-26 Martin Baulig + + * statement.cs (Using.DoResolve): This is internally emitting a + try/finally clause, so we need to set ec.NeedExplicitReturn if we + do not always return. Fixes #47681. + +2003-08-26 Martin Baulig + + * decl.cs (MemberCore): Moved WarningNotHiding(), + Error_CannotChangeAccessModifiers() and CheckMethodAgainstBase() + into MemberBase. + (AdditionResult): Make this nested in DeclSpace. + (DeclSpace.ctor): The .ctor now takes an additional NamespaceEntry + argument; call NamespaceEntry.Define() unless we're nested in a + class or struct. + + * namespace.cs (Namespace.DefineName): New public function. This + is called from DeclSpace's .ctor to add + (Namespace.Lookup): Include DeclSpaces in the lookup. + + * class.cs (Operator): Derive from MemberBase, not MemberCore. + + * const.cs (Const): Derive from MemberBase, not MemberCore. + +2003-08-25 Martin Baulig + + * convert.cs (Convert.ExplicitReferenceConversion): When + converting from an interface type to a class, unbox if the target + type is a struct type. Fixes #47822. + +2003-08-24 Gonzalo Paniagua Javier + + * typemanager.cs: fixed the values of MethodFlags. Closes #47855 and + #47854. + +2003-08-22 Martin Baulig + + * class.cs (TypeManager.DefineType): When defining a nested type, + call DefineType() on our parent; fixes #47801. + +2003-08-22 Martin Baulig + + * class.cs (MethodData.Define): While checking if a method is an + interface implementation, improve the test a bit more to fix #47654. + +2003-08-22 Martin Baulig + + * expression.cs (Probe.DoResolve): Check whether `expr' resolved + correctly; fixes #47722. + +2003-08-22 Martin Baulig + + * expression.cs (UnaryMutator.ResolveVariable): If the target is a + LocalVariableReference, ensure it's not read-only. Fixes #47536. + + * statement.cs (Fixed.DoResolve): Make all variables read-only. + +2003-08-22 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Static read-only fields + can only be assigned in static constructors. Fixes #47161. + +2003-08-22 Martin Baulig + + Rewrote and improved the flow analysis code. + + * flowbranching.cs (FlowBranching): Make this class abstract. + (FlowBranching.CreateBranching): New static function to create a + new flow branching. + (FlowBranchingBlock, FlowBranchingException): New classes. + (FlowBranching.UsageVector.Type): New public readonly field. + (FlowBranching.UsageVector.Breaks): Removed the setter. + (FlowBranching.UsageVector.Returns): Removed the setter. + (FlowBranching.UsageVector): Added Break(), Return(), + NeverReachable() and Throw() methods to modify the reachability. + (FlowBranching.UsageVector.MergeChildren): Removed, this is now + done by FlowBranching.Merge(). + (FlowBranching.UsageVector.MergeChild): New method; merges the + merge result into the current vector. + (FlowBranching.Merge): New abstract method to merge a branching. + +2003-08-12 Martin Baulig + + * expression.cs (Indirection.CacheTemporaries): Create the + LocalTemporary with the pointer type, not its element type. + +2003-08-10 Miguel de Icaza + + * cs-parser.jay: FIRST_KEYWORD, LAST_KEYWORD: used to know if a + token was a keyword or not. + + Add `error' options where an IDENTIFIER was expected; Provide + CheckToken and CheckIdentifierToken convenience error reporting + functions. + + Do not use `DeclSpace.Namespace', use `DeclSpace.NamespaceEntry'. + + * decl.cs: Rename `NamespaceEntry Namespace' public field into + NameSpaceEntry NameSpaceEntry. + + (LookupInterfaceOrClass): Avoid creating a full qualified name + from namespace and name: avoid doing lookups when we know the + namespace is non-existant. Use new Tree.LookupByNamespace which + looks up DeclSpaces based on their namespace, name pair. + + * driver.cs: Provide a new `parser verbose' to display the + exception thrown during parsing. This is turned off by default + now, so the output of a failure from mcs is more graceful. + + * namespace.cs: Track all the namespaces defined in a hashtable + for quick lookup. + + (IsNamespace): New method + +2003-08-09 Miguel de Icaza + + * namespace.cs: Remove redundant call; Avoid using MakeFQN when + we know that we need to concatenate (full typename can never be + null). + + * class.cs: ditto. + + * statement.cs: Use a bitfield; Do not initialize to null things + which are done by the constructor by default. + + * cs-parser.jay: bug fix, parameter was 4, not 3. + + * expression.cs: Just use the property; + + * statement.cs: No need for GetVariableInfo method. + +2003-08-08 Martin Baulig + + * flowanalysis.cs (FlowReturns): This is now nested in the + `FlowBranching' class. + (MyBitVector): Moved this here from statement.cs. + (FlowBranching.SiblingType): New enum type. + (FlowBranching.CreateSibling): Added `SiblingType' argument. + +2003-08-07 Martin Baulig + + * flowanalysis.cs (FlowBranchingType): This is now nested in the + `FlowBranching' class and called `BranchingType'. + +2003-08-07 Martin Baulig + + * flowanalysis.cs: Moved all the control flow analysis code into + its own file. + +2003-08-07 Martin Baulig + + * assign.cs (Assign.DoResolve): `target' must either be an + IAssignMethod or an EventAccess; report a CS0131 otherwise. Fixes + #37319. + +2003-08-07 Miguel de Icaza + + * expression.cs (BinaryMethod): This kind of expression is created by the + Binary class if it determines that the operator has to be handled + by a method. + + (BinaryDelegate): This kind of expression is created if we are + dealing with a + or - operator on delegates. + + (Binary): remove method, argumetns, and DelegateOperator: when + dealing with methods, + + * ecore.cs (EventExpr.EmitAddOrRemove): Update to new layout. + + * statement.cs (Block): use bitfields for the three extra booleans + we had in use. Remove unused topblock parameter. + + * codegen.cs: Remove unecessary argument to Block.EmitTopBlock + + * assign.cs: Drop extra unneeded tests. + +2003-08-06 Miguel de Icaza + + * iterators.cs (Mapvariable): provide a mechanism to use prefixes. + + * statement.cs (Foreach): Use VariableStorage instead of + LocalBuilders. + + * codegen.cs (VariableStorage): New class used by clients that + require a variable stored: locals or fields for variables that + need to live across yield. + + Maybe provide a convenience api for EmitThis+EmitLoad? + + (GetTemporaryLocal, FreeTemporaryLocal): Recycle + these bad boys. + +2003-08-05 Miguel de Icaza + + * codegen.cs (RemapLocal, RemapLocalLValue, RemapParameter, + RemapParameterLValue): New methods that are used to turn a + precomputed FieldInfo into an expression like this: + + instance.FieldInfo + + The idea is to use this instead of making LocalVariableReference + have more than one meaning. + + * cs-parser.jay: Add error production to BASE. + + * ecore.cs: Deal with TypeManager.GetField returning null, which + is now a valid return value. + + (FieldExprNoAddress): New expression for Fields whose address can + not be taken. + + * expression.cs (LocalVariableReference): During the resolve + phases, create new expressions if we are in a remapping context. + Remove code that dealt with remapping here. + + (ParameterReference): same. + + (ProxyInstance): New expression, like the `This' expression, but + it is born fully resolved. We know what we are doing, so remove + the errors that are targeted to user-provided uses of `this'. + + * statement.cs (Foreach): our variable is now stored as an + Expression; During resolution, follow the protocol, dont just + assume it will return this. + +2003-08-06 Martin Baulig + + * support.cs (SeekableStreamReader.cs): New public class. + + * cs-tokenizer.cs, cs-parser.jay, driver.cs: Use the new + SeekableStreamReader instead of the normal StreamReader. + +2003-08-04 Martin Baulig + + * cs-parser.jay (CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, + CLOSE_PARENS_OPEN_PARENS, CLOSE_PARENS_MINUS): New tokens to + deambiguate casts and delegate invocations. + (parenthesized_expression): Use the new tokens to ensure this is + not a cast of method invocation. + + * cs-tokenizer.cs (is_punct): Return one of the new special tokens + when reading a `)' and Deambiguate_CloseParens () was previously + called. + + * expression.cs (ParenthesizedExpression): New class. This is + just used for the CS0075 test. + (Binary.DoResolve): Check for CS0075. + +2003-07-29 Ravi Pratap + + * expression.cs (Invocation.MakeUnionSet): Patch from Lluis + Sanchez : use TypeManager.ArrayContainsMethod instead of a direct + reference comparison. + + (TypeManager.ArrayContainsMethod): When we have a MethodInfo, also + examine the ReturnType for equality - this is necessary in the + cases of implicit and explicit operators whose signature also + includes the return type. + +2003-07-26 Miguel de Icaza + + * namespace.cs: Cache the result of the namespace computation, + instead of computing it every time. + +2003-07-24 Miguel de Icaza + + * decl.cs: Use a global arraylist that we reuse over invocations + to avoid excesive memory consumption. Reduces memory usage on an + mcs compile by one meg (45 average). + + * typemanager.cs (LookupTypeReflection): In .NET pointers are + private, work around that. + +2003-07-23 Miguel de Icaza + + * literal.cs (IntLiteral): Define Zero and One static literals. + + * cs-parser.jay (integer_literal): use static literals to reduce + memory usage for the most used literals (0, 1 and -1). 211kb + reduced in memory usage. + + Replace all calls to `new ArrayList' with `new + ArrayList(4)' which is a good average number for most allocations, + and also requires only 16 bytes of memory for its buffer by + default. + + This reduced MCS memory usage in seven megabytes for the RSS after + bootstrapping. + +2003-07-28 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Fix the algorithm to + handle params methods the correct way by forming only one + applicable set with params and normal methods in them. Earlier we + were looking at params methods only if we found no normal methods + which was not the correct thing to do. + + (Invocation.BetterFunction): Take separate arguments indicating + when candidate and the best method are params methods in their + expanded form. + + This fixes bugs #43367 and #46199. + + * attribute.cs: Documentation updates. + + (CheckAttribute): Rename to CheckAttributeTarget. + (GetValidPlaces): Rename to GetValidTargets. + + * expression.cs (Invocation.IsParamsMethodApplicable): Fix trivial + bug - use Convert.ImplicitConversion, not ImplicitUserConversion! + + Fixes bug #44468. + +2003-07-28 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Use the base type's full + name when looking up the base class of a nested class. Fixes #46977. + +2003-07-26 Martin Baulig + + * expression.cs (Indexers.Indexer): New nested struct; contains + getter, setter and the indexer's type. + (Indexers.Properties): This is now an ArrayList of + Indexers.Indexer's. + (IndexerAccess.DoResolveLValue): Correctly set the type if the + indexer doesn't have any getters. + + * assign.cs (Assign.DoResolve): Also do the implicit conversions + for embedded property and indexer assignments. + +2003-07-26 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.xtoken): Report a CS1040 if a + preprocessor directive is not the first non-whitespace character + on a line. + +2003-07-26 Martin Baulig + + * namespace.cs (NamespaceEntry.Lookup): New method; rewrote the + namespace parsing, follow the spec more closely. + + * rootcontext.cs (RootContext.NamespaceLookup): Use the new + NamespaceEntry.Lookup(). + +2003-07-25 Martin Baulig + + * MethodCore.cs (OverridesSomething): New public field; it's set + from TypeContainer.DefineMembers if this method overrides + something (which doesn't need to be a method). Fix #39462. + +2003-07-25 Ravi Pratap + + * typemanager.cs (GetMembers): Ensure that the list of members is + reversed. This keeps things in sync. + + * attribute.cs (Attribute.CheckAttribute): Break as soon as we + find an AttributeUsage attribute. + + * expression.cs (Invocation.OverloadResolve): Perform the check + which disallows Invoke to be directly called on a Delegate. + + (Error_InvokeOnDelegate): Report error cs1533. + +2003-07-25 Martin Baulig + + * expression.cs (Indexers.GetIndexersForType): Only look in the + interface hierarchy if the requested type is already an + interface. Fixes #46788 while keeping #46502 fixed. + +2003-07-25 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Check whether all + readonly fields have been assigned and report warning CS0649 if + not. + + * statement.cs (LocalInfo.IsFixed): Always return true if this is + a valuetype. + +2003-07-24 Ravi Pratap + + * decl.cs (MemberCache.AddMethods): Reverse the order of the array + returned from GetMethods to make things consistent with the + assumptions MCS makes about ordering of methods. + + This should comprehensively fix bug #45127 and it does :-) + + * ecore.cs (MethodGroupExpr.DeclaringType): Correct bug - the + ordering is actually reverse. + + * Clean up some debug messages I left lying around. + + * interface.cs (Populate*): Get rid of code which emits attributes + since the stage in which we emit attributes is the 'Emit' stage, + not the define stage. + + (Emit): Move attribute emission for interface members here. + +2003-07-22 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Follow the spec more + closely: we eliminate methods in base types when we have an + applicable method in a top-level type. + + Please see section 14.5.5.1 for an exact description of what goes + on. + + This fixes bug #45127 and a host of other related to corlib compilation. + + * ecore.cs (MethodGroupExpr.DeclaringType): The element in the + array is the method corresponding to the top-level type (this is + because of the changes made to icall.c) so we change this + accordingly. + + (MethodGroupExpr.Name): This too. + + * typemanager.cs (GetElementType): New method which does the right + thing when compiling corlib. + + * everywhere: Make use of the above in the relevant places. + +2003-07-22 Martin Baulig + + * cs-parser.jay (invocation_expression): Moved + `OPEN_PARENS expression CLOSE_PARENS unary_expression' here from + `cast_expression', but create a InvocationOrCast which later + resolves to either an Invocation or a Cast. + + * ecore.cs (ExpressionStatement.ResolveStatement): New virtual + method; call this before EmitStatement() to make sure that this + expression can be used as a statement. + + * expression.cs (InvocationOrCast): New class; resolves to either + an Invocation or a Cast. + + * statement.cs (StatementExpression): Call ResolveStatement() on + the ExpressionStatement before emitting it. + +2003-07-21 Martin Baulig + + * expression.cs (Invocation.VerifyArgumentsCompat): Check whether + `ref' and `out' attributes match; fixes #46220. + (MemberAccess.ResolveMemberAccess): You can't reference a type + through an expression; fixes #33180. + (Indexers.GetIndexersForType): Don't return the indexers from + interfaces the class implements; fixes #46502. + +2003-07-21 Martin Baulig + + * class.cs (TypeContainer.CheckPairedOperators): Added CS0660 and + CS0661 checks; fixes bug #30442. + +2003-07-21 Martin Baulig + + * decl.cs (AdditionResult): Added `Error'. + + * enum.cs (AddEnumMember): Report a CS0076 if name is `value__'. + + * typemanager.cs (TypeManager.ChangeType): Catch exceptions; + makes cs0031.cs actually work. + +2003-07-20 Martin Baulig + + * namespace.cs: Fixed that bug which caused a crash when compiling + the debugger's GUI. + +2003-07-20 Miguel de Icaza + + * typemanager.cs (LookupTypeReflection): Never expose types which + are NotPublic, NestedPrivate, NestedAssembly, or + NestedFamANDAssem. We used to return these, and later do a check + that would report a meaningful error, but the problem is that we + would not get the real match, if there was a name override. + +2003-07-18 Miguel de Icaza + + * namespace.cs (Namespace, Name): Do not compute the namespace + name dynamically, compute it in the constructor. This reduced + memory usage by 1697 KB. + + * driver.cs: Use --pause to pause at the end. + +2003-07-17 Peter Williams + + * Makefile: Change the name of the test target so that it doesn't + conflict with the recursive test target. + +2003-07-17 Miguel de Icaza + + * expression.cs (LocalVariableReference.Emit, EmitAssign, + AddressOf): Do not use EmitThis, that was wrong, use the actual + this pointer. + +2003-07-15 Miguel de Icaza + + * class.cs (MethodData.Define): While checking if a method is an + interface implementation, improve the test: If we are not public + (use new test here: use the computed MethodAttributes directly, + instead of the parsed modifier flags) check if the `implementing' + method comes from an interface or not. + + * pending.cs (VerifyPendingMethods): Slightly better error + message. + + * makefile: add test target that does the mcs bootstrap. + +2003-07-16 Ravi Pratap + + * interface.cs (Define): Do nothing here since there are no + members to populate etc. Move the attribute emission out of here + since this was just totally the wrong place to put it. Attribute + application happens during the 'Emit' phase, not in the 'Define' + phase. + + (Emit): Add this method and move the attribute emission here + + * rootcontext.cs (EmitCode): Call the Emit method on interface + types too. + +2003-07-14 Ravi Pratap M + + * expression.cs (OverloadResolve): Report error only if Location + is not 'Null' which means that there was a probe going on. + +2003-07-14 Martin Baulig + + * expression.cs (ConditionalLogicalOperator): New public class to + implement user defined conditional logical operators. + This is section 14.11.2 in the spec and bug #40505. + +2003-07-14 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Fixed bug #46198. + +2003-07-14 Martin Baulig + + * codegen.cs (EmitContext.InFixedInitializer): New public field. + + * ecore.cs (IVariable.VerifyFixed): New interface method. + + * expression.cs (Unary.ResolveOperator): When resolving the `&' + operator, check whether the variable is actually fixed. Fixes bug + #36055. Set a variable definitely assigned when taking its + address as required by the spec. + + * statement.cs (LocalInfo.IsFixed): New field. + (LocalInfo.MakePinned): Set `IsFixed' to true. + +2003-07-14 Ravi Pratap M + + * attribute.cs (Attribute.Resolve): While doing a Member lookup + for .ctors, ensure that we only ask for members declared in the + attribute type (BindingFlags.DeclaredOnly). + + Fixes bug #43632. + + * expression.cs (Error_WrongNumArguments): Report error 1501 + correctly the way CSC does. + +2003-07-13 Martin Baulig + + * expression.cs (MemberAccess.ResolveAsTypeStep): Try to do a type + lookup on the fully qualified name, to make things like "X.X" work + where "X.X" is a fully qualified type name, but we also have a + namespace "X" in the using list. Fixes #41975. + +2003-07-13 Martin Baulig + + * assign.cs (Assign.GetEmbeddedAssign): New protected virtual + function. If we're a CompoundAssign, we need to create an embedded + CompoundAssign, not an embedded Assign. + (Assign.DoResolve): Make this work for embedded CompoundAssign's. + Fixes #45854. + +2003-07-13 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): Make this actually + work to fix bug #46088. + +2003-07-13 Ravi Pratap + + * class.cs (Operator.Emit): Do not emit attributes here - it is + taken care of by the Method class that we delegate too. This takes + care of bug #45876. + +2003-07-10 Martin Baulig + + * expression.cs (TypeOfVoid): New class. + (TypeOf): Report a CS0673 if it's System.Void. Fixes #42264. + +2003-07-10 Martin Baulig + + * class.cs (MethodCore.DoDefineParameters): Added CS0225 check; + bug #35957. + +2003-07-10 Martin Baulig + + * rootcontext.cs (RootContext.NamespaceLookup): Take a DeclSpace, + not a NamespaceEntry, so we can use DeclSpace.CheckAccessLevel(). + + * decl.cs (DeclSpace.FindType): Use DeclSpace.CheckAccessLevel(). + + * typemanager.cs (TypeManager.IsAccessibleFrom): Removed. + +2003-07-10 Martin Baulig + + * expression.cs (ArrayCreation): Don't use a byte blob for arrays + of decimal. Fixes #42850. + + NOTE: I also fixed the created byte blob, but this doesn't work on + the MS runtime and csc never produces any byte blobs for decimal + arrays. + +2003-07-10 Martin Baulig + + * statement.cs (StructInfo.GetStructInfo): Catch deep cycles in + structs; fixes #32068. + (Block.AddChildVariableNames): Fixed #44302. + +2003-07-07 Gonzalo Paniagua Javier + + * namespace.cs: fixed compilation with csc. It's bugzilla #44302. + +2003-07-07 Miguel de Icaza + + * attribute.cs: And this test is onger needed. + +2003-07-08 Martin Baulig + + * rootcontext.cs (RootContext.NamespaceLookup): Ignore + inaccessible types. Fixes #36313. + + * decl.cs (DeclSpace.FindType): Ignore inaccessible types. + + * namespace.cs (NamespaceEntry): Create implicit entries for all + namespaces; ie. if we have `namespace N1.N2.N3 { ... }', we create + implicit entries for N1.N2 and N1. + +2003-07-08 Martin Baulig + + Rewrote the handling of namespaces to fix a lot of the issues + wrt. `using' aliases etc. + + * namespace.cs (Namespace): Splitted this class into a + per-assembly `Namespace' and a per-file `NamespaceEntry'. + + * typemanager.cs (TypeManager.IsNamespace): Removed. + (TypeManager.ComputeNamespaces): Only compute namespaces from + loaded assemblies here, not the namespaces from the assembly we're + currently compiling. + +2003-07-08 Martin Baulig + + * rootcontext.cs, class.cs: Fixed the CS1530 reporting. + +2003-07-07 Miguel de Icaza + + * typemanager.cs: Reverted patch from Gonzalo, my previous patch + already fixed it. + + I thought about the memory savings here, but LookupTypeReflection + is used under already very constrained scenarios. Compiling + corlib or mcs only exposes one hit, so it would not really reduce + any memory consumption. + +2003-07-07 Gonzalo Paniagua Javier + + * typemanager.cs: fixes bug #45889 by only adding public types from + other assemblies to the list of known types. + +2003-07-07 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Add call to CheckAccessLevel + on the type we resolved. + +2003-07-05 Martin Baulig + + * pending.cs (PendingImplementation.ParentImplements): Don't + create the proxy if the parent is abstract. + + * class.cs (TypeContainer.DefineIndexers): Process explicit + interface implementations first. Fixes #37714. + +2003-07-04 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): Events are + defined recursively; but since we modify the input parameters + (left is set to `this' temporarily), we reset this value if the + left_is_explicit is false, which gives the original semantics to + the code. + + * literal.cs (NullPointer): new class used to represent a null + literal in a pointer context. + + * convert.cs (Convert.ImplicitReferenceConversion): Is the target + type is a pointer, use a NullPointer object instead of a + NullLiteral. Closes 43687 + + (ExplicitConversion): Convert pointer values using + the conv opcode to the proper type. + + * ecore.cs (New): change ValueTypeVariable property into a method, + that returns whether the valuetype is suitable for being used. + + * expression.cs (Binary.DoNumericPromotions): Only return if we + the int constant was a valid uint, and we can return both left and + right as uints. If not, we continue processing, to trigger the + type conversion. This fixes 39018. + + * statement.cs (Block.EmitMeta): During constant resolution, set + the CurrentBlock property on the emitcontext, so that we resolve + constants propertly. + +2003-07-02 Martin Baulig + + * codegen.cs (EmitContext.NeedExplicitReturn): New public variable. + (EmitContext.EmitTopBlock): Emit an explicit return if it's set. + + * statement.cs (Try.Resolve): Set ec.NeedExplicitReturn rather + than emitting it here. + + * statement.cs: Fixed some more flow analysis bugs. + +2003-07-02 Martin Baulig + + * class.cs (MethodData.Define): When implementing interface + methods, set Final unless we're Virtual. + + * decl.cs (MemberCore.CheckMethodAgainstBase): Make the CS0506 + check work for interface methods. + +2003-07-01 Martin Baulig + + * ecore.cs (EmitContext.This): Replaced this property with a + GetThis() method which takes a Location argument. This ensures + that we get the correct error location for a CS0188. + +2003-07-01 Miguel de Icaza + + * ecore.cs: (Convert.ConvertIntLiteral): Add test for + ImplicitStandardConversion. + + * class.cs (TypeContainer.GetClassBases): Small bug fix for 45649. + +2003-07-01 Zoltan Varga + + * expression.cs (ResolveOperator): Fix Concat (string, string, string) + optimization. + +2003-06-30 Miguel de Icaza + + * class.cs (Constructor.Define): Turn off initlocals for unsafe + constructors. + + (MethodData.Define): Turn off initlocals for unsafe methods. + +2003-06-29 Miguel de Icaza + + * decl.cs (DeclSpace.CheckAccessLevel): Make this routine + complete; Fixes #37521. + + * delegate.cs: Use Modifiers.TypeAttr to compute the + TypeAttributes, instead of rolling our own. This makes the flags + correct for the delegates. + +2003-06-28 Miguel de Icaza + + * class.cs (Constructor.Define): Set the private flag for static + constructors as well. + + * cs-parser.jay (statement_expression): Set the return value to + null, to avoid a crash when we catch an error. + +2003-06-24 Miguel de Icaza + + * cs-parser.jay: Applied patch from Jackson that adds support for + extern and unsafe modifiers to destructor declarations. + + * expression.cs: Report error 21 if the user is trying to index a + System.Array. + + * driver.cs: Add an error message, suggested by the bug report. + + * class.cs (TypeContainer.Emit): Only call EmitFieldInitializers + if we do not have a ": this ()" constructor initializer. Fixes 45149 + +2003-06-14 Miguel de Icaza + + * namespace.cs: Add some information to reduce FAQs. + +2003-06-13 Miguel de Icaza + + * cfold.cs (BinaryFold): BitwiseAnd, BitwiseOr: handle other + underlying enumeration types. Fixes #43915. + + * expression.cs: Treat ushort/short as legal values to be used in + bitwise operations. + +Wed Jun 4 13:19:04 CEST 2003 Paolo Molaro + + * delegate.cs: transfer custom attributes for paramenters from + the delegate declaration to Invoke and BeginInvoke. + +Tue Jun 3 11:11:08 CEST 2003 Paolo Molaro + + * attribute.cs: handle custom marshalers and emit marshal info + for fields, too. + +2003-05-28 Hector E. Gomez Morales + + * makefile.gnu: Added anonymous.cs to the compiler sources. + +2003-05-28 Miguel de Icaza + + * iterators.cs: Change the name of the proxy class to include two + underscores. + + * cs-parser.jay: Update grammar to include anonymous methods. + + * anonymous.cs: new file. + +2003-05-27 Miguel de Icaza + + * class.cs (Field.Define): Add missing test for pointers and + safety. + +2003-05-27 Ravi Pratap + + * expression.cs (ArrayAccess.GetStoreOpCode): For System.IntPtr, + we use the stobj opcode. + + (ArrayCreation.EmitDynamicInitializers): Revert Miguel's patch + since it wasn't the correct fix. + + It still is puzzling that we are required to use stobj for IntPtr + which seems to be a ValueType. + +2003-05-26 Miguel de Icaza + + * ecore.cs (SimpleName.SimpleNameResolve): Consider using aliases + during regular simple name resolution. Now, the trick is that + instead of returning for processing the simplename, we do a + TypeManager.LookupType (ie, a rooted lookup as opposed to a + contextual lookup type). If a match is found, return that, if + not, return for further composition. + + This fixes long-standing 30485. + + * expression.cs (ArrayCreation.EmitDynamicInitializers): When + using the address to initialize an object, do an Stobj instead of + using the regular Stelem. + + (IndexerAccess.Emit, IndexerAccess.EmitAssign): + Pass `is_base_indexer' to Invocation.EmitCall instead of false. + Because if we are a BaseIndexerAccess that value will be true. + Fixes 43643. + + * statement.cs (GotoCase.Resolve): Return after reporting an + error, do not attempt to continue. + + * expression.cs (PointerArithmetic.Emit): If our operand is a + long, convert our constants to match the operand before + multiplying. Convert to I type before adding. Fixes 43670. + +2003-05-14 Ravi Pratap + + * enum.cs (ImplicitConversionExists) : Rename to + ImplicitEnumConversionExists to remove ambiguity. + + * ecore.cs (NullCast): New type of cast expression class which + basically is very similar to EmptyCast with the difference being + it still is a constant since it is used only to cast a null to + something else + (eg. (string) null) + + * convert.cs (ImplicitReferenceConversion): When casting a null + literal, we return a NullCast. + + * literal.cs (NullLiteralTyped): Remove - I don't see why this + should be around anymore. + + The renaming (reported was slightly wrong). Corrections: + + ConvertImplicitStandard -> ImplicitConversionStandard + ConvertExplicitStandard -> ExplicitConversionStandard + + * expression.cs (StaticCallExpr.MakeSimpleCall): Resolve arguments + before passing them in ! + + * convert.cs (ImplicitConversionStandard): When comparing for + equal expr and target types, ensure that expr is not a + NullLiteral. + + In general, we must not be checking (expr_type == + target_type) in the top level conversion methods + (ImplicitConversion, ExplicitConversion etc). This checking is + done in the methods that they delegate to. + +2003-05-20 Miguel de Icaza + + * convert.cs: Move Error_CannotConvertType, + ImplicitReferenceConversion, ImplicitReferenceConversionExists, + ImplicitNumericConversion, ImplicitConversionExists, + ImplicitUserConversionExists, StandardConversionExists, + FindMostEncompassedType, FindMostSpecificSource, + FindMostSpecificTarget, ImplicitUserConversion, + ExplicitUserConversion, GetConversionOperators, + UserDefinedConversion, ConvertImplicit, ConvertImplicitStandard, + TryImplicitIntConversion, Error_CannotConvertImplicit, + ConvertImplicitRequired, ConvertNumericExplicit, + ExplicitReferenceConversionExists, ConvertReferenceExplicit, + ConvertExplicit, ConvertExplicitStandard from the ecore.cs into + its own file. + + Perform the following renames: + + StandardConversionExists -> ImplicitStandardConversionExists + ConvertImplicit -> ImplicitConversion + ConvertImplicitStandard -> ImplicitStandardConversion + TryImplicitIntConversion -> ImplicitIntConversion + ConvertImplicitRequired -> ImplicitConversionRequired + ConvertNumericExplicit -> ExplicitNumericConversion + ConvertReferenceExplicit -> ExplicitReferenceConversion + ConvertExplicit -> ExplicitConversion + ConvertExplicitStandard -> ExplicitStandardConversion + +2003-05-19 Martin Baulig + + * statement.cs (TypeInfo.StructInfo): Made this type protected. + (TypeInfo): Added support for structs having structs as fields. + + * ecore.cs (FieldExpr): Implement IVariable. + (FieldExpr.DoResolve): Call VariableInfo.GetSubStruct() to get the + VariableInfo for the field. + +2003-05-18 Martin Baulig + + * expression.cs (This.DoResolve): Report a CS0027 if we're + emitting a field initializer. + +2003-05-18 Martin Baulig + + * expression.cs (This.ResolveBase): New public function. + (This.DoResolve): Check for CS0188. + + * codegen.cs (EmitContext.This): Just call This.ResolveBase(), not + This.Resolve(). + + * ecore.cs (MethodGroupExpr.DoResolve): Set the + `instance_expression' to null if we don't have any non-static + methods. + +2003-05-18 Martin Baulig + + Reworked the way how local variables and parameters are handled by + the flow analysis code. + + * statement.cs (TypeInfo, VariableMap): New public classes. + (VariableInfo): New public class. This is now responsible for + checking whether a variable has been assigned. It is used for + parameters and local variables. + (Block.EmitMeta): Take the InternalParameters as argument; compute + the layout of the flow vectors here. + (Block.LocalMap, Block.ParameterMap): New public properties. + (FlowBranching): The .ctor doesn't get the InternalParameters + anymore since Block.EmitMeta() now computes the layout of the flow + vector. + (MyStructInfo): This class is now known as `StructInfo' and nested + in `TypeInfo'; we don't access this directly anymore. + + * ecore.cs (IVariable): Added `VariableInfo VariableInfo' + property and removed IsAssigned(), IsFieldAssigned(), + SetAssigned() and SetFieldAssigned(); we now call them on the + VariableInfo so we don't need to duplicate this code everywhere. + + * expression.cs (ParameterReference): Added `Block block' argument + to the .ctor. + (LocalVariableReference, ParameterReference, This): The new + VariableInfo class is now responsible for all the definite + assignment stuff. + + * codegen.cs (EmitContext.IsVariableAssigned, SetVariableAssigned, + IsParameterAssigned, SetParameterAssigned): Removed. + +2003-05-18 Martin Baulig + + * typemanager.cs (InitCoreTypes): Try calling + SetCorlibTypeBuilders() with 4 args; if that fails, fall back to + the 3-args-version. Corlib now also needs our `void_type'. + (GetMethod): Added overloaded version which takes an optional + `bool report_errors' to allow lookups of optional methods. + +2003-05-12 Martin Baulig + + * statement.cs (VariableInfo): Renamed to LocalInfo since it's + only used for locals and not for parameters. + +2003-05-12 Miguel de Icaza + + * support.cs (InternalParameters.ParameterType): Return the + ExternalType of the parameter. + + * parameter.cs (Parameter.ExternalType): drop the two arguments, + they were unused. + +2003-05-11 Miguel de Icaza + + * class.cs (MethodData.Define): Do not set the `newslot' on + interface members, if they are also flagged as "override". + + * expression.cs (UnaryMutator.EmitCode): Simple workaround to emit + better code for ++i and i++. This only works for static fields + and local variables. + + * typemanager.cs (LookupDeclSpace): Add new method, sometimes we + want to pull the DeclSpace out of the builder_to_declspace instead + of the TypeBuilder (like in TypeContainer.FindMembers). + + * class.cs (TypeContainer.FindMembers): Use LookupDeclSpace + instead of LookupTypeContainer. Fixes the crash on .NET for + looking up interface members. + + * const.cs: Create our own emit context during the Definition + stage, so that constants are evaluated in the proper context, when + a recursive definition happens. + +2003-05-11 Martin Baulig + + * statement.cs (Block.CreateSwitchBlock): New method. Creates a + new block for a switch section. + (Block.AddLabel, Block.LookupLabel): If we're a switch section, do + the adding/lookup in the switch block. Fixes #39828. + +2003-05-09 Miguel de Icaza + + * expression.cs (UnaryMutator.LoadOneAndEmitOp): Missing + functionality: I needed to convert the data after I had performed + the add/sub operation into the operands type size. + + * ecore.cs (ImplicitReferenceConversion): When boxing an interface + pass the type for the box operation, otherwise the resulting + object would have been of type object. + + (BoxedCast): Add constructor to specify the type to box as. + +2003-05-07 Miguel de Icaza + + * iterators.cs: I was reusing the `count' variable inadvertently, + take steps to not allow this to happen. + +2003-05-06 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Params attributes are encoded + by creating an array at the point where the params starts and + putting all those arguments there, then adjusting the size of the + array. + +2003-05-05 Miguel de Icaza + + * expression.cs (New.AddressOf): Implement interface + IMemoryLocation. This is used when the `new' operator is used in + the context of an invocation to a method on a value type. + + See http://bugzilla.ximian.com/show_bug.cgi?id=#42390 for an + example. + + * namespace.cs: Also check the using aliases here. + + * driver.cs: Move the test for using validity after the types have + been entered, so we do a single pass that also includes the using + aliases. + + * statement.cs (Try.Resolve): Avoid crashing if there is a failure + in the regular case. CreateSiblingForFinally is doing extra + error checking. + + * attribute.cs (GetAttributeArgumentExpression): Store the result + on an out value, and use the return value to indicate failure + instead of using null (which is a valid return for Constant.GetValue). + + * statement.cs: Perform the analysis flow for the increment + portion after the statement, because this will be the real flow of + execution. Fixes #42385 + + * codegen.cs (EmitContext.EmitArgument, + EmitContext.EmitStoreArgument): New helper functions when the + RemapToProxy flag is set. + + * expression.cs (ParameterReference.EmitLdarg): Expose this useful + function. + + Add support for remapping parameters. + + * iterators.cs: Propagate parameter values; Store parameter + values in the proxy classes. + +2003-05-04 Miguel de Icaza + + * ecore.cs (FieldExpr): Fix an obvious bug. static fields do not + need a proxy reference; I do not know what I was thinking + + * cs-parser.jay (constructor_initializer): catch another error, + and display nice message. + + (field_declaration): catch void field declaration + to flag a better error. + + * class.cs (MemberBase.CheckBase): Report an error instead of a + warning if a new protected member is declared in a struct. + (Field.Define): catch the error of readonly/volatile. + + * ecore.cs (FieldExpr.EmitAssign): reuse the field lookup. + + (FieldExpr.AddressOf): ditto. Catch error where the address of a + volatile variable is taken + +2003-05-02 Miguel de Icaza + + * statement.cs (Fixed.Resolve): Report an error if we are not in + an unsafe context. + +2003-05-01 Miguel de Icaza + + * typemanager.cs: reuse the code that handles type clashes for + delegates and enumerations. + + * class.cs (Report28): Always report. + + * expression.cs (EncodeAsAttribute): Allow nulls here. + +2003-04-28 Miguel de Icaza + + * attribute.cs (Attribute.GetAttributeArgumentExpression): Moved + the functionality for testing whether an expression is valid for + an attribute here. Also handle the case of arrays of elements + being stored. + + * expression.cs (ArrayCreation.EncodeAsAttribute): Add support for + encoding a linear array into an array of objects that are suitable + to be passed to an CustomAttributeBuilder. + + * delegate.cs: Check unsafe types being used outside of an Unsafe context. + + * ecore.cs: (FieldExpr): Handle field remapping here. + + * iteratators.cs: Pass the instance variable (if the method is an + instance method) to the constructors, so we can access the field + variables on the class. + + TODO: Test this with structs. I think the THIS variable on + structs might have to be a pointer, and not a refenrece + +2003-04-27 Miguel de Icaza + + * codegen.cs (EmitContext.Mapvariable): Adds a mechanism to map + local variables to fields in a proxy class. + + * iterators.cs (PopulateProxy): Rename our internal fields to + . + Create a field if we are an instance method, so we can + reference our parent container variables. + (MapVariable): Called back from the EmitContext code to enter a + new variable to field mapping into the proxy class (we just create + a FieldBuilder). + + * expression.cs + (LocalVariableReference.{Emit,EmitAssign,AddressOf}): Add support + for using the remapped locals to fields. + + I placed the code here, because that gives the same semantics to + local variables, and only changes the Emit code. + + * statement.cs (Fixed.Resolve): it is not allowed to have fixed + statements inside iterators. + (VariableInfo): Add a FieldBuilder for the cases when we are + remapping local variables to fields in a proxy class + + * ecore.cs (SimpleNameResolve): Avoid testing two times for + current_block != null. + + * statement.cs (Swithc.SimpleSwitchEmit): Removed code that did + not cope with strings, as it has been moved to the + TableSwitchEmit. Fixed bug in switch generation. + + * expression.cs (New.DoResolve): Provide more context for the user + when reporting an error. + + * ecore.cs (Expression.LoadFromPtr): Use ldind_i when loading + pointers. + + * expression.cs (MemberAccess.DoResolve): When we get a type back, + check the permissions for it. Note than in a type-resolution + context the check was already present in DeclSpace.ResolveType, + but was missing from the MemberAccess. + + (ArrayCreation.CheckIndices): warn if the user has + more nested levels of expressions, but there are no more + dimensions specified. Avoids crash on bug 41906. + +2003-04-26 Miguel de Icaza + + * statement.cs (Block): replace Implicit bool, for a generic + flags. + New flag: `Unchecked'. This is used during the EmitMeta phase + (which is out-of-line with the regular Resolve/Emit process for a + statement, as this is done ahead of time, but still gets a chance + to call constant resolve). + + (Block.Flags): new enum for adding a new flag. + + (Block.EmitMeta): track the state of unchecked. + + (Unchecked): Set the "UnChecked" flags on any blocks we enclose, + to enable constant resolution to work there as well. + +2003-04-22 Miguel de Icaza + + * typemanager.cs (ienumerable_type): Also look up + System.Collections.IEnumerable. + +2003-04-21 Miguel de Icaza + + TODO: Test more than one conditional per method. + + * class.cs (Indexer.Define): Report the location where the user is + referencing the unsupported feature. + + (MethodData): Overload the use of `conditionals' to + minimize the creation of needless ArrayLists. This saves roughly + 212kb on my machine. + + (Method): Implement the new IIteratorContainer interface. + (Method.SetYields): Implement the method by setting the ModFlags + to contain METHOD_YIELDS. + + * expression.cs (Unary.ResolveOperator): Use expr_type, not Expr, + which just got set to null. + + * iterators.cs: New file. + + (Yield, YieldBreak): New statements. + + * statement.cs (Return.Resolve): Flag an error if we are used in + an iterator method. + + * codegen.cs (InIterator): New flag set if the code is being + compiled in an iterator method. + + * modifiers.cs: New flag METHOD_YIELDS. This modifier is an + internal modifier, and we just use it to avoid adding extra + fields, as this is seldom used. + + * cs-parser.jay: Add yield_statement (yield and yield break). + + * driver.cs: New flag -v2 to turn on version 2 features. + + * cs-tokenizer.cs (Tokenizer): Add yield and __yield to the + hashtable when v2 is enabled. + +2003-04-20 Miguel de Icaza + + * typemanager.cs (TypeManager.NamespaceClash): Use to check if + there is already a namespace defined with this name. + + (TypeManager.InitCoreTypes): Remove the temporary workaround, as + people upgraded their corlibs. + + (TypeManager.CoreLookupType): Use LookupTypeDirect, as we + always use fully qualified types, no need to use the compiler + front end. + + (TypeManager.IsNamespace): Use binarysearch. + + * class.cs (AddClass, AddStruct, AddInterface, AddEvent, + AddDelegate): I did not quite use the new IsValid API properly: I + have to pass the short-name and the fullname. I was passing only + the basename instead of the fullname sometimes. + + (TypeContainer.DefineType): call NamespaceClash. + + * interface.cs (Interface.DefineType): use NamespaceClash before + defining the type. + + * delegate.cs (Delegate.DefineType): use NamespaceClash before + defining the type. + + * enum.cs: (Enum.DefineType): use NamespaceClash before + defining the type. + + * typemanager.cs (: 3-line patch that gives us some tasty 11% + speed increase. First, use the negative_hits cache when we get a + negative. Second, add the type with its full original name + instead of the new . and + encoded name (reflection uses + to + separate type from a nested type). Use LookupTypeReflection + directly which bypasses the type->name hashtable (that we already + know does not contain the type. + + * decl.cs (DeclSpace.ResolveTypeExpr): track the + location/container type. + + * driver.cs: When passing utf8, use directly the UTF8Encoding. + +2003-04-19 Miguel de Icaza + + * decl.cs (ResolveTypeExpr): Mirror check acess here too. + + * delegate.cs (NewDelegate.Resolve): Test whether an instance + method is being referenced in the method group from a static + context, and report error 120 if so. + + * expression.cs, ecore.cs (Error_UnexpectedKind): New name for + Error118. + + * typemanager.cs: Add intermediate namespaces (if a namespace A.B + is created, we create the A namespace). + + * cs-parser.jay: A namespace also introduces a DeclarationFound. + Fixes #41591 + +2003-04-18 Miguel de Icaza + + * typemanager.cs (GetReferenceType, GetPointerType): In .NET each + invocation to ModuleBuilder.GetType with the same values will + return a new type instance, so we need to cache its return + values. + + * expression.cs (Binary.ResolveOperator): Only allow the compare + operators on enums if they are of the same type. + + * ecore.cs (Expression.ImplicitReferenceConversion): handle target + types of ValueType on their own case. Before we were giving them + the same treatment as objects. + + * decl.cs (DeclSpace.IsValid): IsValid takes the short name and + fullname. Short name is used to compare against container name. + Fullname is used to check against defined namespace names. + + * class.cs (AddProperty, AddField, AddClass, AddStruct, AddEnum, + AddDelegate, AddEvent): Pass new parameter to DeclSpace.IsValid + + (Method.CheckBase): Call parent. + (MemberBase.CheckBase): Check for protected members on sealed + classes. + (PropertyBase.CheckBase): Call parent. + (Field.Define): Call parent. + + * report.cs: Negative error codes are now mapped to 8000 - code, + so that the display is render more nicely. + + * typemanager.cs: Do not use try/catch, instead report a regular + error. + + (GetPointerType, GetReferenceType): These methods provide + mechanisms to obtain the T* and T& from a T. We had the code + previously scattered around the code base, and it also used + TypeManager.LookupType that would go through plenty of caches. + This one goes directly to the type source. + + In some places we did the Type.GetType followed by + ModuleBuilder.GetType, but not in others, so this unifies the + processing as well. + + * namespace.cs (VerifyUsing): Perform a non-lazy approach to using + statements now that we have namespace information. + + * typemanager.cs (IsNamespace): New method, returns whether the + string presented is a namespace or not. + + (ComputeNamespaces): New public entry point, computes the list of + available namespaces, using the GetNamespaces API call in Mono, or + the slower version in MS.NET. + + Now before we start the semantic analysis phase, we have a + complete list of namespaces including everything that the user has + provided. + + Deleted old code to cache namespaces in .nsc files. + +2003-04-17 Miguel de Icaza + + * class.cs: (TypeContainer.DefineDefaultConstructor): Use the + class/struct location definition Location for the implicit + constructor location. + + (Operator.Define): Use the location of the operator for the + implicit Method definition. + + (Constructor.Emit): use the constructor location for the implicit + base initializer constructor. + + * ecore.cs: Remove ITypeExpression. This interface is now gone, + and the Expression class now contains two new methods: + + ResolveAsTypeStep and ResolveAsTypeTerminal. This is used to + isolate type lookup from the rest of the resolution process. + + Since we use Expressions to hold type definitions due to the way + we parse the input we have historically overloaded Resolve to + perform the Type lookups if a special flag is passed. Now this is + eliminated and two methods take their place. + + The differences in the two methods between xStep and xTerminal is + that xStep is involved in our current lookup system that uses + SimpleNames to compose a name, while xTerminal is used just to + catch the case where the simplename lookup failed. + +2003-04-16 Miguel de Icaza + + * expression.cs (ResolveMemberAccess): Remove redundant code. + TypeExpr expressions are always born fully resolved. + + * interface.cs (PopulateMethod): Do not lookup the types twice. + We were doing it once during SemanticAnalysis and once during + PopulateMethod. + + * cs-parser.jay: Due to our hack in the grammar, things like A.B[] + in local variable type definitions, were being returned as a + SimpleName (we decomposed everything into a string), that is + because primary_expression was being used instead of a type in the + grammar (reduce/reduce conflicts). + + The part that was wrong is that we converted the expression into a + string (an oversimplification in one hand, compounded with primary + expressions doing string concatenation). + + So things like: + + A.B.C [] x; + + Would return "A.B.C[]" as a SimpleName. This stopped things like + using clauses from working on this particular context. And a type + was being matched directly against "A.B.C[]". + + We now use the correct approach, and allow for ComposedCast to be + part of the unary expression. So the "A.B.C []" become a composed + cast of "A.B.C" (as a nested group of MemberAccess with a + SimpleName at the end) plus the rank composition "[]". + + Also fixes 35567 + +2003-04-10 Miguel de Icaza + + * decl.cs (CheckAccessLevel): Implement the NestedPrivate rules + for the access level checking. + + * class.cs: Cosmetic changes. Renamed `TypeContainer parent' to + `TypeContainer container', because I kept getting confused when I + was debugging this code. + + * expression.cs (Indexers): Instead of tracking getters/setters, + we now track them in parallel. We create one arraylist less, but + most importantly it is possible now for the LValue code to find a + matching get for a set. + + (IndexerAccess.DoResolveLValue): Update the code. + GetIndexersForType has been modified already to extract all the + indexers from a type. The code assumed it did not. + + Also make the code set the correct return type for the indexer. + This was fixed a long time ago for properties, but was missing for + indexers. It used to be void_type. + + (Binary.Emit): Test first for doubles instead of + floats, as they are more common. + + (Binary.EmitBranchable): Use the .un version of the branch opcodes + when dealing with floats and the <=, >= operators. This fixes bug + #39314 + + * statement.cs (Foreach.EmitArrayForeach): bug fix: The code used + to load the array value by emitting a load on the foreach variable + type. This was incorrect. + + We now emit the code to load an element using the the array + variable type, and then we emit the conversion operator. + + Fixed #40176 + +2003-04-10 Zoltan Varga + + * attribute.cs: Avoid allocation of ArrayLists in the common case. + +2003-04-09 Miguel de Icaza + + * class.cs (MethodSignature.InheritableMemberSignatureCompare): + test for protection before we test for signatures. + + (MethodSignature.ToString): implement. + + * expression.cs (Unary.TryReduceNegative): Add missing minus sign + to the case where we reduced into a LongConstant. + + * decl.cs (CheckAccessLevel): If the type is an array, we can not + depend on whether the information is acurrate, because the + Microsoft runtime will always claim that the array type is public, + regardless of the real state. + + If the type is a pointer, another problem happens: the type is + reported as non-public in Microsoft. + + In both cases we have to call CheckAccessLevel recursively with + the underlying type as the argument to be tested. + +2003-04-08 Miguel de Icaza + + * assign.cs (Assign.Emit): If we are dealing with a compound + assignment expression, we should use the code path that stores the + intermediate result in a temporary value. This fixes #40903. + + *expression.cs (Indirection.ToString): Provide ToString method for + debugging. + +2003-04-08 Zoltan Varga + + * class.cs: Null out fields holding references to Block objects so + they can be garbage collected. + + * expression.cs (OverloadResolve): Remove unused local. + +2003-04-07 Martin Baulig + + * codegen.cs (EmitContext.CurrentFile): New public field. + (EmitContext.Mark): Use the CurrentFile to check whether the + location is in the correct file. + (EmitContext.EmitTopBlock): Initialize CurrentFile here. + +2003-04-07 Martin Baulig + + * ecore.cs (Expression.ResolveBoolean): Don't call ec.Mark(). + + * codegen.cs (EmitContext.EmitTopBlock): Don't call Mark() on the + location. [FIXME: The location argument which gets passed to this + method is sometimes wrong!] + +2003-04-07 Nick Drochak + + * codegen.cs: Be more verbose when we can't find the symbol writer dll. + +2003-04-07 Miguel de Icaza + + * expression.cs (Indirection.EmitAssign): We were using the + temporary, but returning immediately instead of continuing the + EmitAssing flow. + +2003-04-06 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Don't report an error + if it's a nested child, but also deriving from the outer class. + See test 190.cs. + + * typemanager.cs (IsNestedChildOf): Make this work if it's a + nested child, but also deriving from the outer class. See + test-190.cs. + (FilterWithClosure): We may access private members of the outer + class if we're a nested child and deriving from the outer class. + (RealMemberLookup): Only set `closure_private_ok' if the + `original_bf' contained BindingFlags.NonPublic. + +2003-04-05 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #40670. + +2003-04-02 Miguel de Icaza + + * class.cs (Event.Define): Do not allow abstract events to have + initializers. + +2003-04-01 Miguel de Icaza + + * cs-parser.jay: Add error productions for ADD/REMOVE missing a + block in event declarations. + + * ecore.cs (FieldExpr.AddressOf): If our instance expression is a + value type, get its address. + + * expression.cs (Is.Emit): For action `LeaveOnStack' we were + leaving a class on the stack instead of a boolean value (int + 0/1). Change the code so we compare against null, and then the + result against zero. + + * class.cs (TypeContainer.GetClassBases): We were checking for the + parent class being sealed too late. + + * expression.cs (Binary.Emit): For <= and >= when dealing with + floating point values, use cgt.un and clt.un instead of cgt and + clt alone. + +2003-04-01 Zoltan Varga + + * statement.cs: Apply the same optimization as MS: skip the + GetEnumerator returning an IEnumerator, and use the one returning a + CharEnumerator instead. This allows us to avoid the try-finally block + and the boxing. + +2003-03-31 Gaurav Vaish + + * cs-parser.jay: Attributes cannot be applied to + namespaces. Fixes #40473 + +2003-03-31 Gonzalo Paniagua Javier + + * class.cs: + (Add*): check if the name is valid using the full name for constants, + fields, properties and events. + +2003-03-28 Miguel de Icaza + + * enum.cs (Enum.DefineType, Enum.IsValidEnumConstant): Also allow + char constants to be part of the enumeration. + + * expression.cs (Conditional.DoResolve): Add support for operator + true. Implements the missing functionality from 14.12 + + * class.cs (TypeContainer.CheckPairedOperators): Report error for missmatch on + operator true/false as required by the spec. + + * expression.cs (Unary.ResolveOperator): In LogicalNot, do an + implicit conversion to boolean. + + * statement.cs (Statement.ResolveBoolean): A boolean expression is + also one where the type implements `operator true'. + + * ecore.cs (Expression.GetOperatorTrue): New helper routine to + get an expression that will invoke operator true based on an + expression. + + (GetConversionOperators): Removed the hack that called op_True + here. + + (Expression.ResolveBoolean): Move this from Statement. + +2003-03-17 Miguel de Icaza + + * ecore.cs (FieldExpr): do not allow initialization of initonly + fields on derived classes + +2003-03-13 Martin Baulig + + * statement.cs (Block.Emit): Call ig.BeginScope() and + ig.EndScope() when compiling with debugging info; call + LocalBuilder.SetLocalSymInfo _after_ opening the scope. + +2003-03-08 Miguel de Icaza + + * expression.cs (Indexers): Do not construct immediately, allow + for new members to be appended as we go. Fixes 38143 + +2003-03-07 Gonzalo Paniagua Javier + + * expression.cs: save/restore context when resolving an unchecked + expression. + +2003-03-05 Miguel de Icaza + + * cfold.cs: Catch division by zero in modulus operator during + constant folding. + +2003-03-03 Miguel de Icaza + + * interface.cs (Interface.DefineMembers): Avoid defining members + twice. + +2003-02-27 Miguel de Icaza + + * driver.cs: handle the +/- options for -noconfig + + * statement.cs (Unckeched.Resolve): Also track the state of + unchecked in the Resolve phase. + +2003-02-27 Martin Baulig + + * ecore.cs (Expression.MemberLookup): Don't create a + MethodGroupExpr for something which is not a method. Fixes #38291. + +2003-02-25 Miguel de Icaza + + * class.cs (MemberBase.CheckParameters): Also check that the type + is unmanaged if it is a pointer. + + * expression.cs (SizeOf.Resolve): Add location information. + + * statement.cs (Block.EmitMeta): Flag error (208) if a pointer to + a managed type is declared. + + * expression.cs (Invocation.VerifyArgumentsCompat): Check for the + parameter modifiers as well. Fixes bug 38606 + + * class.cs: Very sad. Am backing out the speed up changes + introduced by the ArrayList -> Array in the TypeContainer, as they + were not actually that much faster, and introduced a bug (no error + reports on duplicated methods). + + * assign.cs (CompoundAssign.DoLResolve): Resolve the original + source first, this will guarantee that we have a valid expression + before calling in lower levels functions that will require a + resolved object. Then use this original_source in the + target.ResolveLValue instead of the original source that was + passed to us. + + Another change. Use target.Resolve instead of LValueResolve. + Although we are resolving for LValues, we will let the Assign code + take care of that (it will be called again from Resolve). This + basically allows code like this: + + class X { X operator + (X x, object o) {} X this [int idx] { get; set; } } + class Y { void A (X x) { x [0] += o; } + + The problem was that the indexer was trying to resolve for + set_Item (idx, object o) and never finding one. The real set_Item + was set_Item (idx, X). By delaying the process we get the right + semantics. + + Fixes bug 36505 + +2003-02-23 Martin Baulig + + * statement.cs (Block.Emit): Override this and set ec.CurrentBlock + while calling DoEmit (). + + * codegen.cs (EmitContext.Mark): Don't mark locations in other + source files; if you use the #line directive inside a method, the + compiler stops emitting line numbers for the debugger until it + reaches the end of the method or another #line directive which + restores the original file. + +2003-02-23 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #37708. + +2003-02-23 Martin Baulig + + * statement.cs (Block.AddChildVariableNames): We need to call this + recursively, not just for our immediate children. + +2003-02-23 Martin Baulig + + * class.cs (Event.Define): Always make the field private, like csc does. + + * typemanager.cs (TypeManager.RealMemberLookup): Make events + actually work, fixes bug #37521. + +2003-02-23 Miguel de Icaza + + * delegate.cs: When creating the various temporary "Parameters" + classes, make sure that we call the ComputeAndDefineParameterTypes + on those new parameters (just like we do with the formal ones), to + allow them to be resolved in the context of the DeclSpace. + + This fixes the bug that Dick observed in Bugzilla #38530. + +2003-02-22 Miguel de Icaza + + * expression.cs (ResolveMemberAccess): When resolving a constant, + do not attempt to pull a constant if the value was not able to + generate a valid constant. + + * const.cs (LookupConstantValue): Do not report more errors than required. + +2003-02-19 Gonzalo Paniagua Javier + + * expression.cs: fixes bug #38328. + +2003-02-18 Miguel de Icaza + + * class.cs: Changed all the various members that can be part of a + class from being an ArrayList to be an Array of the right type. + During the DefineType type_list, interface_list, delegate_list and + enum_list are turned into types, interfaces, delegates and enums + arrays. + + And during the member population, indexer_list, event_list, + constant_list, field_list, instance_constructor_list, method_list, + operator_list and property_list are turned into their real arrays. + + Although we could probably perform this operation earlier, for + good error reporting we need to keep the lists and remove the + lists for longer than required. + + This optimization was triggered by Paolo profiling the compiler + speed on the output of `gen-sample-program.pl' perl script. + + * decl.cs (DeclSpace.ResolveType): Set the ContainerType, so we do + not crash in methods like MemberLookupFailed that use this field. + + This problem arises when the compiler fails to resolve a type + during interface type definition for example. + +2003-02-18 Miguel de Icaza + + * expression.cs (Indexers.GetIndexersForType): Interfaces do not + inherit from System.Object, so we have to stop at null, not only + when reaching System.Object. + +2003-02-17 Miguel de Icaza + + * expression.cs: (Indexers.GetIndexersForType): Martin's fix used + DeclaredOnly because the parent indexer might have had a different + name, but did not loop until the top of the hierarchy was reached. + + The problem this one fixes is 35492: when a class implemented an + indexer from an interface, we were getting the interface method + (which was abstract) and we were flagging an error (can not invoke + abstract method). + + This also keeps bug 33089 functioning, and test-148 functioning. + + * typemanager.cs (IsSpecialMethod): The correct way of figuring + out if a method is special is to see if it is declared in a + property or event, or whether it is one of the predefined operator + names. This should fix correctly #36804. + +2003-02-15 Miguel de Icaza + + The goal here is to remove the dependency on EmptyCast.Peel (). + Killing it completely. + + The problem is that currently in a number of places where + constants are expected, we have to "probe" for an EmptyCast, and + Peel, which is not the correct thing to do, as this will be + repetitive and will likely lead to errors. + + The idea is to remove any EmptyCasts that are used in casts that + can be reduced to constants, so we only have to cope with + constants. + + This bug hunt was triggered by Bug 37363 and the desire to remove + the duplicate pattern where we were "peeling" emptycasts to check + whether they were constants. Now constants will always be + constants. + + * ecore.cs: Use an enumconstant here instead of wrapping with + EmptyCast. + + * expression.cs (Cast.TryReduce): Ah, the tricky EnumConstant was + throwing me off. By handling this we can get rid of a few hacks. + + * statement.cs (Switch): Removed Peel() code. + +2003-02-14 Miguel de Icaza + + * class.cs: Location information for error 508 + + * expression.cs (New.DoResolve): Add a guard against double + resolution of an expression. + + The New DoResolve might be called twice when initializing field + expressions (see EmitFieldInitializers, the call to + GetInitializerExpression will perform a resolve on the expression, + and later the assign will trigger another resolution + + This leads to bugs (#37014) + + * delegate.cs: The signature for EndInvoke should contain any ref + or out parameters as well. We were not doing this in the past. + + * class.cs (Field.Define): Do not overwrite the type definition + inside the `volatile' group. Turns out that volatile enumerations + were changing the type here to perform a validity test, which + broke conversions. + +2003-02-12 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): In the particular case of This + and structs, we do not want to load the instance variable + + (ImplicitReferenceConversion, ImplicitReferenceConversionExists): + enum_type has to be handled like an object reference (implicit + conversions exists from this to object), but the regular IsClass + and IsValueType tests will never return true for this one. + + Also we use TypeManager.IsValueType instead of type.IsValueType, + just for consistency with the rest of the code (this is only + needed if we ever use the construct exposed by test-180.cs inside + corlib, which we dont today). + +2003-02-12 Zoltan Varga + + * attribute.cs (ApplyAttributes): apply all MethodImplAttributes, not + just InternalCall. + +2003-02-09 Martin Baulig + + * namespace.cs (Namespace..ctor): Added SourceFile argument. + (Namespace.DefineNamespaces): New static public method; this is + called when we're compiling with debugging to add all namespaces + to the symbol file. + + * tree.cs (Tree.RecordNamespace): Added SourceFile argument and + pass it to the Namespace's .ctor. + + * symbolwriter.cs (SymbolWriter.OpenMethod): Added TypeContainer + and MethodBase arguments; pass the namespace ID to the symwriter; + pass the MethodBase instead of the token to the symwriter. + (SymbolWriter.DefineNamespace): New method to add a namespace to + the symbol file. + +2003-02-09 Martin Baulig + + * symbolwriter.cs: New file. This is a wrapper around + ISymbolWriter with a cleaner API. We'll dynamically Invoke() + methods here in near future. + +2003-02-09 Martin Baulig + + * codegen.cs (EmitContext.Mark): Just pass the arguments to + ILGenerator.MarkSequencePoint() which are actually used by the + symbol writer. + +2003-02-09 Martin Baulig + + * location.cs (SourceFile): New public sealed class. This + contains the name and an index which is used in the location's token. + (Location): Reserve an appropriate number of bits in the token for + the source file instead of walking over that list, this gives us a + really huge performance improvement when compiling with debugging. + + * driver.cs (Driver.parse, Driver.tokenize_file): Take a + `SourceFile' argument instead of a string. + (Driver.ProcessFile): Add all the files via Location.AddFile(), + but don't parse/tokenize here, we need to generate the list of all + source files before we do that. + (Driver.ProcessFiles): New static function. Parses/tokenizes all + the files. + + * cs-parser.jay (CSharpParser): Take a `SourceFile' argument + instead of a string. + + * cs-tokenizer.cs (Tokenizer): Take `SourceFile' argument instead + of a string. + +2003-02-09 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.PreProcessLine): Also reset the + filename on `#line default'. + +Sat Feb 8 17:03:16 CET 2003 Paolo Molaro + + * statement.cs: don't clear the pinned var when the fixed statement + returns from the method (fixes bug#37752). + +Sat Feb 8 12:58:06 CET 2003 Paolo Molaro + + * typemanager.cs: fix from mathpup@mylinuxisp.com (Marcus Urban) + to IsValueType. + +2003-02-07 Martin Baulig + + * driver.cs: Removed the `--debug-args' command line argument. + + * codegen.cs (CodeGen.SaveSymbols): Removed, this is now done + automatically by the AsssemblyBuilder. + (CodeGen.InitializeSymbolWriter): We don't need to call any + initialization function on the symbol writer anymore. This method + doesn't take any arguments. + +2003-02-03 Miguel de Icaza + + * driver.cs: (AddAssemblyAndDeps, LoadAssembly): Enter the types + from referenced assemblies as well. + +2003-02-02 Martin Baulig + + * class.cs (MethodData.Emit): Generate debugging info for external methods. + +2003-02-02 Martin Baulig + + * class.cs (Constructor.Emit): Open the symbol writer before + emitting the constructor initializer. + (ConstructorInitializer.Emit): Call ec.Mark() to allow + single-stepping through constructor initializers. + +2003-01-30 Miguel de Icaza + + * class.cs: Handle error 549: do not allow virtual methods in + sealed classes. + +2003-02-01 Jackson Harper + + * decl.cs: Check access levels when resolving types + +2003-01-31 Jackson Harper + + * statement.cs: Add parameters and locals set in catch blocks that might + return to set vector + +2003-01-29 Miguel de Icaza + + * class.cs (Operator): Set the SpecialName flags for operators. + + * expression.cs (Invocation.DoResolve): Only block calls to + accessors and operators on SpecialName methods. + + (Cast.TryReduce): Handle conversions from char constants. + + +Tue Jan 28 17:30:57 CET 2003 Paolo Molaro + + * statement.cs: small memory and time optimization in FlowBranching. + +2003-01-28 Pedro Mart + + * expression.cs (IndexerAccess.DoResolveLValue): Resolve the same + problem that the last fix but in the other sid (Set). + + * expression.cs (IndexerAccess.DoResolve): Fix a problem with a null + access when there is no indexer in the hierarchy. + +2003-01-27 Jackson Harper + + * class.cs: Combine some if statements. + +2003-01-27 Gonzalo Paniagua Javier + + * driver.cs: fixed bug #37187. + +2003-01-27 Pedro Martinez Juliá + + * expression.cs (IndexerAccess.DoResolve): Before trying to resolve + any indexer, it's needed to build a list with all the indexers in the + hierarchy (AllGetters), else we have problems. Fixes #35653. + +2003-01-23 Miguel de Icaza + + * class.cs (MethodData.Define): It is wrong for an interface + implementation to be static in both cases: explicit and implicit. + We were only handling this in one case. + + Improve the if situation there to not have negations. + + * class.cs (Field.Define): Turns out that we do not need to check + the unsafe bit on field definition, only on usage. Remove the test. + +2003-01-22 Gonzalo Paniagua Javier + + * driver.cs: use assembly.Location instead of Codebase (the latest + patch made mcs fail when using MS assemblies). + +2003-01-21 Tim Haynes + + * driver.cs: use DirectorySeparatorChar instead of a hardcoded "/" to + get the path to *corlib.dll. + +2003-01-21 Nick Drochak + + * cs-tokenizer.cs: + * pending.cs: + * typemanager.cs: Remove compiler warnings + +2003-01-20 Duncan Mak + + * AssemblyInfo.cs: Bump the version number to 0.19. + +2003-01-20 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: little fixes to line numbering when #line is used. + +2003-01-18 Zoltan Varga + + * class.cs (Constructor::Emit): Emit debugging info for constructors. + +2003-01-17 Miguel de Icaza + + * cs-parser.jay: Small fix: we were not comparing the constructor + name correctly. Thanks to Zoltan for the initial pointer. + +2003-01-16 Jackson Harper + + * cs-tokenizer.cs: Set file name when specified with #line + +2003-01-15 Miguel de Icaza + + * cs-parser.jay: Only perform the constructor checks here if we + are named like the class; This will help provider a better + error. The constructor path is taken when a type definition is + not found, but most likely the user forgot to add the type, so + report that rather than the constructor error. + +Tue Jan 14 10:36:49 CET 2003 Paolo Molaro + + * class.cs, rootcontext.cs: small changes to avoid unnecessary memory + allocations. + +2003-01-13 Jackson Harper + + * cs-parser.jay: Add cleanup call. + +2003-01-13 Duncan Mak + + * cs-tokenizer.cs (Cleanup): Rename to 'cleanup' to make it more + consistent with other methods. + +2003-01-13 Jackson Harper + + * cs-tokenizer.cs: Add Cleanup method, also fix #region error messages. + +Sun Jan 12 19:58:42 CET 2003 Paolo Molaro + + * attribute.cs: only set GuidAttr to true when we have a + GuidAttribute. + +2003-01-09 Gonzalo Paniagua Javier + + * ecore.cs: + * expression.cs: + * typemanager.cs: fixes to allow mcs compile corlib with the new + Type.IsSubclassOf fix. + +2003-01-08 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolve): Classify a + constant as a value, not as a variable. Also, set the type for + the variable. + + * cs-parser.jay (fixed_statement): take a type instead of a + pointer_type, so we can produce a better error message later. + + * statement.cs (Fixed.Resolve): Flag types that are not pointers + as an error. + + (For.DoEmit): Make inifinite loops have a + non-conditional branch back. + + (Fixed.DoEmit): First populate the pinned variables, then emit the + statement, then clear the variables. Before I was emitting the + code once for each fixed piece. + + +2003-01-08 Martin Baulig + + * statement.cs (FlowBranching.MergeChild): A break in a + SWITCH_SECTION does not leave a loop. Fixes #36155. + +2003-01-08 Martin Baulig + + * statement.cs (FlowBranching.CheckOutParameters): `struct_params' + lives in the same number space than `param_map'. Fixes #36154. + +2003-01-07 Miguel de Icaza + + * cs-parser.jay (constructor_declaration): Set the + Constructor.ModFlags before probing for it. This makes the + compiler report 514, 515 and 132 (the code was there, but got + broken). + + * statement.cs (Goto.Resolve): Set `Returns' to ALWAYS. + (GotoDefault.Resolve): Set `Returns' to ALWAYS. + (GotoCase.Resolve): Set `Returns' to ALWAYS. + +Tue Jan 7 18:32:24 CET 2003 Paolo Molaro + + * enum.cs: create the enum static fields using the enum type. + +Tue Jan 7 18:23:44 CET 2003 Paolo Molaro + + * class.cs: don't try to create the ParamBuilder for the return + type if it's not needed (and handle it breaking for the ms runtime + anyway). + +2003-01-06 Jackson Harper + + * cs-tokenizer.cs: Add REGION flag to #region directives, and add checks to make sure that regions are being poped correctly + +2002-12-29 Miguel de Icaza + + * cs-tokenizer.cs (get_cmd_arg): Fixups to allow \r to terminate + the command. This showed up while compiling the JANET source + code, which used \r as its only newline separator. + +2002-12-28 Miguel de Icaza + + * class.cs (Method.Define): If we are an operator (because it + reuses our code), then set the SpecialName and HideBySig. #36128 + +2002-12-22 Miguel de Icaza + + * ecore.cs (FieldExpr.DoResolve): Instead of throwing an + exception, report error 120 `object reference required'. + + * driver.cs: Add --pause option, used during to measure the size + of the process as it goes with --timestamp. + + * expression.cs (Invocation.DoResolve): Do not allow methods with + SpecialName to be invoked. + +2002-12-21 Miguel de Icaza + + * cs-tokenizer.cs: Small fix to the parser: compute the ascii + number before adding it. + +2002-12-21 Ravi Pratap + + * ecore.cs (StandardImplicitConversion): When in an unsafe + context, we allow conversion between void * to any other pointer + type. This fixes bug #35973. + +2002-12-20 Jackson Harper + + * codegen.cs: Use Path.GetFileNameWithoutExtension so an exception + is not thrown when extensionless outputs are used + +2002-12-20 Gonzalo Paniagua Javier + + * rootcontext.cs: fixed compilation of corlib. + +2002-12-19 Miguel de Icaza + + * attribute.cs (Attributes.Contains): Add new method. + + * class.cs (MethodCore.LabelParameters): if the parameter is an + `out' parameter, check that no attribute `[In]' has been passed. + + * enum.cs: Handle the `value__' name in an enumeration. + +2002-12-14 Jaroslaw Kowalski + + * decl.cs: Added special case to allow overrides on "protected + internal" methods + +2002-12-18 Ravi Pratap + + * attribute.cs (Attributes.AddAttributeSection): Rename to this + since it makes much more sense. + + (Attributes.ctor): Don't require a Location parameter. + + * rootcontext.cs (AddGlobalAttributeSection): Rename again. + + * attribute.cs (ApplyAttributes): Remove extra Location parameters + since we already have that information per attribute. + + * everywhere : make appropriate changes. + + * class.cs (LabelParameters): Write the code which actually + applies attributes to the return type. We can't do this on the MS + .NET runtime so we flag a warning in the case an exception is + thrown. + +2002-12-18 Miguel de Icaza + + * const.cs: Handle implicit null conversions here too. + +2002-12-17 Ravi Pratap + + * class.cs (MethodCore.LabelParameters): Remove the extra + Type [] parameter since it is completely unnecessary. Instead + pass in the method's attributes so that we can extract + the "return" attribute. + +2002-12-17 Miguel de Icaza + + * cs-parser.jay (parse): Use Report.Error to flag errors instead + of ignoring it and letting the compile continue. + + * typemanager.cs (ChangeType): use an extra argument to return an + error condition instead of throwing an exception. + +2002-12-15 Miguel de Icaza + + * expression.cs (Unary.TryReduce): mimic the code for the regular + code path. Perform an implicit cast in the cases where we can + implicitly convert to one of the integral types, and then reduce + based on that constant. This fixes bug #35483. + +2002-12-14 Gonzalo Paniagua Javier + + * typemanager.cs: fixed cut & paste error in GetRemoveMethod. + +2002-12-13 Gonzalo Paniagua Javier + + * namespace.cs: fixed bug #35489. + +2002-12-12 Miguel de Icaza + + * class.cs: Remove some dead code. + + * cs-parser.jay: Estimate the number of methods needed + (RootContext.MethodCount); + + * cs-tokenizer.cs: Use char arrays for parsing identifiers and + numbers instead of StringBuilders. + + * support.cs (PtrHashtable): Add constructor with initial size; + We can now reduce reallocations of the method table. + +2002-12-10 Ravi Pratap + + * attribute.cs (ApplyAttributes): Keep track of the emitted + attributes on a per-target basis. This fixes bug #35413. + +2002-12-10 Miguel de Icaza + + * driver.cs (MainDriver): On rotor encoding 28591 does not exist, + default to the Windows 1252 encoding. + + (UnixParseOption): Support version, thanks to Alp for the missing + pointer. + + * AssemblyInfo.cs: Add nice assembly information. + + * cs-tokenizer.cs: Add fix from Felix to the #if/#else handler + (bug 35169). + + * cs-parser.jay: Allow a trailing comma before the close bracked + in the attribute_section production. + + * ecore.cs (FieldExpr.AddressOf): Until I figure out why the + address of the instance was being taken, I will take this out, + because we take the address of the object immediately here. + +2002-12-09 Ravi Pratap + + * typemanager.cs (AreMultipleAllowed): Take care of the most + obvious case where attribute type is not in the current assembly - + stupid me ;-) + +2002-12-08 Miguel de Icaza + + * ecore.cs (SimpleName.DoResolve): First perform lookups on using + definitions, instead of doing that afterwards. + + Also we use a nice little hack, depending on the constructor, we + know if we are a "composed" name or a simple name. Hence, we + avoid the IndexOf test, and we avoid + + * codegen.cs: Add code to assist in a bug reporter to track down + the source of a compiler crash. + +2002-12-07 Ravi Pratap + + * attribute.cs (Attribute.ApplyAttributes) : Keep track of which attribute + types have been emitted for a given element and flag an error + if something which does not have AllowMultiple set is used more + than once. + + * typemanager.cs (RegisterAttributeAllowMultiple): Keep track of + attribute types and their corresponding AllowMultiple properties + + (AreMultipleAllowed): Check the property for a given type. + + * attribute.cs (Attribute.ApplyAttributes): Register the AllowMultiple + property in the case we have a TypeContainer. + + (Attributes.AddAttribute): Detect duplicates and just skip on + adding them. This trivial fix catches a pretty gross error in our + attribute emission - global attributes were being emitted twice! + + Bugzilla bug #33187 is now fixed. + +2002-12-06 Miguel de Icaza + + * cs-tokenizer.cs (pp_expr): Properly recurse here (use pp_expr + instead of pp_and). + + * expression.cs (Binary.ResolveOperator): I can only use the + Concat (string, string, string) and Concat (string, string, + string, string) if the child is actually a concatenation of + strings. + +2002-12-04 Miguel de Icaza + + * cs-tokenizer.cs: Small fix, because decimal_digits is used in a + context where we need a 2-character lookahead. + + * pending.cs (PendingImplementation): Rework so we can keep track + of interface types all the time, and flag those which were + implemented by parents as optional. + +2002-12-03 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Use + String.Concat(string,string,string) or + String.Concat(string,string,string,string) when possible. + + * typemanager: More helper methods. + + +Tue Dec 3 19:32:04 CET 2002 Paolo Molaro + + * pending.cs: remove the bogus return from GetMissingInterfaces() + (see the 2002-11-06 entry: the mono runtime is now fixed in cvs). + +2002-12-02 Gonzalo Paniagua Javier + + * namespace.cs: avoid duplicated 'using xxx' being added to + using_clauses. This prevents mcs from issuing and 'ambiguous type' error + when we get more than one 'using' statement for the same namespace. + Report a CS0105 warning for it. + +2002-11-30 Miguel de Icaza + + * cs-tokenizer.cs (consume_identifier): use read directly, instead + of calling getChar/putback, uses internal knowledge of it. + + (xtoken): Reorder tokenizer so most common patterns are checked + first. This reduces the compilation time in another 5% (from 8.11s + average to 7.73s for bootstrapping mcs on my Mobile p4/1.8ghz). + + The parsing time is 22% of the compilation in mcs, and from that + 64% is spent on the tokenization process. + + I tried using a binary search for keywords, but this is slower + than the hashtable. Another option would be to do a couple of + things: + + * Not use a StringBuilder, instead use an array of chars, + with a set value. Notice that this way we could catch + the 645 error without having to do it *afterwards*. + + * We could write a hand-parser to avoid the hashtable + compares altogether. + + The identifier consumption process takes 37% of the tokenization + time. Another 15% is spent on is_number. 56% of the time spent + on is_number is spent on Int64.Parse: + + * We could probably choose based on the string length to + use Int32.Parse or Int64.Parse and avoid all the 64-bit + computations. + + Another 3% is spend on wrapping `xtoken' in the `token' function. + + Handle 0xa0 as whitespace (#34752) + +2002-11-26 Miguel de Icaza + + * typemanager.cs (IsCLRType): New routine to tell whether a type + is one of the builtin types. + + Maybe it needs to use TypeCodes to be faster. Maybe we could use + typecode in more places instead of doing pointer comparissions. + We could leverage some knowledge about the way the typecodes are + laid out. + + New code to cache namespaces in assemblies, it is currently not + invoked, to be used soon. + + * decl.cs (DeclSpace.MakeFQN): Simple optimization. + + * expression.cs (Binary.ResolveOperator): specially handle + strings, and do not perform user-defined operator overloading for + built-in types. + +2002-11-24 Miguel de Icaza + + * cs-tokenizer.cs: Avoid calling Char.IsDigit which is an + internalcall as it is a pretty simple operation; Avoid whenever + possible to call Char.IsLetter. + + (consume_identifier): Cut by half the number of + hashtable calls by merging the is_keyword and GetKeyword behavior. + + Do not short-circuit, because if we do, we + report errors (ie, #if false && true would produce an invalid + directive error); + + +2002-11-24 Martin Baulig + + * expression.cs (Cast.TryReduce): If we're in checked syntax, + check constant ranges and report a CS0221. Fixes #33186. + +2002-11-24 Martin Baulig + + * cs-parser.jay: Make this work for uninitialized variable + declarations in the `for' initializer. Fixes #32416. + +2002-11-24 Martin Baulig + + * ecore.cs (Expression.ConvertExplicit): Make casting from/to + System.Enum actually work. Fixes bug #32269, added verify-6.cs. + +2002-11-24 Martin Baulig + + * expression.cs (Binary.DoNumericPromotions): Added `check_user_conv' + argument; if true, we also check for user-defined conversions. + This is only needed if both arguments are of a user-defined type. + Fixes #30443, added test-175.cs. + (Binary.ForceConversion): Pass the location argument to ConvertImplicit. + + * ecore.cs (Expression.ImplicitUserConversionExists): New method. + +2002-11-24 Martin Baulig + + * expression.cs (ArrayAccess.GetStoreOpcode): New public static + function to get the store opcode. + (Invocation.EmitParams): Call ArrayAccess.GetStoreOpcode() and + only emit the Ldelema if the store opcode is Stobj. You must run + both test-34 and test-167 to test this. Fixes #34529. + +2002-11-23 Martin Baulig + + * ecore.cs (Expression.MemberLookup): Added additional + `qualifier_type' argument which is used when we're being called + from MemberAccess.DoResolve() and null if we're called from a + SimpleName lookup. + (Expression.MemberLookupFailed): New method to report errors; this + does the CS1540 check and reports the correct error message. + + * typemanager.cs (MemberLookup): Added additional `qualifier_type' + argument for the CS1540 check and redone the way how we're dealing + with private members. See the comment in the source code for details. + (FilterWithClosure): Reverted this back to revision 1.197; renamed + `closure_start_type' to `closure_qualifier_type' and check whether + it's not null. It was not this filter being broken, it was just + being called with the wrong arguments. + + * expression.cs (MemberAccess.DoResolve): use MemberLookupFinal() + and pass it the correct `qualifier_type'; this also does the error + handling for us. + +2002-11-22 Miguel de Icaza + + * expression.cs (Invocation.EmitParams): If the we are dealing + with a non-built-in value type, load its address as well. + + (ArrayCreation): Use a a pretty constant instead + of the hardcoded value 2. Use 6 instead of 2 for the number of + static initializers. + + (ArrayCreation.EmitDynamicInitializers): Peel enumerations, + because they are not really value types, just glorified integers. + + * driver.cs: Do not append .exe, the CSC compiler does not do it. + + * ecore.cs: Remove redundant code for enumerations, make them use + the same code path as everything else, fixes the casting issue + with enumerations in Windows.Forms. + + * attribute.cs: Do only cast to string if it is a string, the + validation happens later. + + * typemanager.cs: Temproary hack to avoid a bootstrap issue until + people upgrade their corlibs. + + * ecore.cs: Oops, enumerations were not following the entire code path + +2002-11-21 Miguel de Icaza + + * typemanager.cs (FilterWithClosure): Commented out the test for + 1540 in typemanager.cs, as it has problems when accessing + protected methods from a parent class (see test-174.cs). + + * attribute.cs (Attribute.ValidateGuid): new method. + (Attribute.Resolve): Use above. + +2002-11-19 Miguel de Icaza + + * enum.cs: In FindMembers, perform a recursive lookup for values. (34308) + + * ecore.cs (SimpleName.SimpleNameResolve): Remove the special + handling for enumerations, as we only needed the TypeContainer + functionality to begin with (this is required for the fix below to + work for enums that reference constants in a container class for + example). + + * codegen.cs (EmitContext): Make TypeContainer a DeclSpace. + + * enum.cs (Enum.Define): Use `this' instead of parent, so we have + a valid TypeBuilder to perform lookups on.o + + * class.cs (InheritableMemberSignatureCompare): Use true in the + call to GetGetMethod and GetSetMethod, because we are comparing + the signature, and we need to get the methods *even* if they are + private. + + (PropertyBase.CheckBase): ditto. + + * statement.cs (Switch.ResolveAndReduce, Block.EmitMeta, + GotoCase.Resolve): Use Peel on EmpytCasts. + + * ecore.cs (EmptyCast): drop child, add Peel method. + +2002-11-17 Martin Baulig + + * ecore.cs (EmptyCast.Child): New public property. + + * statement.cs (SwitchLabel.ResolveAndReduce): Check whether the + label resolved to an EmptyCast. Fixes #34162. + (GotoCase.Resolve): Likewise. + (Block.EmitMeta): Likewise. + +2002-11-17 Martin Baulig + + * expression.cs (Invocation.BetterConversion): Prefer int over + uint; short over ushort; long over ulong for integer literals. + Use ImplicitConversionExists instead of StandardConversionExists + since we also need to check for user-defined implicit conversions. + Fixes #34165. Added test-173.cs. + +2002-11-16 Martin Baulig + + * expression.cs (Binary.EmitBranchable): Eliminate comparisions + with the `true' and `false' literals. Fixes #33151. + +2002-11-16 Martin Baulig + + * typemanager.cs (RealMemberLookup): Reverted Miguel's patch from + October 22nd; don't do the cs1540 check for static members. + + * ecore.cs (PropertyExpr.ResolveAccessors): Rewrote this; we're + now using our own filter here and doing the cs1540 check again. + +2002-11-16 Martin Baulig + + * support.cs (InternalParameters): Don't crash if we don't have + any fixed parameters. Fixes #33532. + +2002-11-16 Martin Baulig + + * decl.cs (MemberCache.AddMethods): Use BindingFlags.FlattenHierarchy + when looking up static methods to make this work on Windows. + Fixes #33773. + +2002-11-16 Martin Baulig + + * ecore.cs (PropertyExpr.VerifyAssignable): Check whether we have + a setter rather than using PropertyInfo.CanWrite. + +2002-11-15 Nick Drochak + + * class.cs: Allow acces to block member by subclasses. Fixes build + breaker. + +2002-11-14 Martin Baulig + + * class.cs (Constructor.Emit): Added the extern/block check. + Fixes bug #33678. + +2002-11-14 Martin Baulig + + * expression.cs (IndexerAccess.DoResolve): Do a DeclaredOnly + iteration while looking for indexers, this is needed because the + indexer may have a different name in our base classes. Fixed the + error reporting (no indexers at all, not get accessor, no + overloaded match). Fixes bug #33089. + (IndexerAccess.DoResolveLValue): Likewise. + +2002-11-14 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Make this work for multiple + indexers. Fixes the first part of bug #33089. + (MethodSignature.InheritableMemberSignatureCompare): Added support + for properties. + +2002-11-13 Ravi Pratap + + * attribute.cs (Attribute.Resolve): Catch the + NullReferenceException and report it since it isn't supposed to + happen. + +2002-11-12 Miguel de Icaza + + * expression.cs (Binary.EmitBranchable): Also handle the cases for + LogicalOr and LogicalAnd that can benefit from recursively + handling EmitBranchable. The code now should be nice for Paolo. + +2002-11-08 Miguel de Icaza + + * typemanager.cs (LookupType): Added a negative-hit hashtable for + the Type lookups, as we perform quite a number of lookups on + non-Types. This can be removed once we can deterministically tell + whether we have a type or a namespace in advance. + + But this might require special hacks from our corlib. + + * TODO: updated. + + * ecore.cs (TryImplicitIntConversion): Handle conversions to float + and double which avoids a conversion from an integer to a double. + + * expression.cs: tiny optimization, avoid calling IsConstant, + because it effectively performs the lookup twice. + +2002-11-06 Miguel de Icaza + + But a bogus return here to keep the semantics of the old code + until the Mono runtime is fixed. + + * pending.cs (GetMissingInterfaces): New method used to remove all + the interfaces that are already implemented by our parent + classes from the list of pending methods. + + * interface.cs: Add checks for calls after ResolveTypeExpr. + +2002-11-05 Miguel de Icaza + + * class.cs (Class.Emit): Report warning 67: event not used if the + warning level is beyond 3. + + * ecore.cs (Expression.ConvertExplicit): Missed a check for expr + being a NullLiteral. + + * cs-parser.jay: Fix, Gonzalo reverted the order of the rank + specifiers. + + * class.cs (TypeContainer.GetClassBases): Cover a missing code + path that might fail if a type can not be resolved. + + * expression.cs (Binary.Emit): Emit unsigned versions of the + operators. + + * driver.cs: use error 5. + +2002-11-02 Gonzalo Paniagua Javier + + * cs-parser.jay: simplified a rule and 5 SR conflicts dissapeared. + +2002-11-01 Miguel de Icaza + + * cs-parser.jay (switch_section): A beautiful patch from Martin + Baulig that fixed 33094. + +2002-10-31 Miguel de Icaza + + * ecore.cs (PropertyExpr.DoResolveLValue, PropertyExpr.DoResolve): + Check whether the base is abstract and report an error if so. + + * expression.cs (IndexerAccess.DoResolveLValue, + IndexerAccess.DoResolve): ditto. + + (Invocation.DoResolve): ditto. + + (Invocation.FullMethodDesc): Improve the report string. + + * statement.cs (Block): Eliminate IsVariableDefined as it is + basically just a wrapper for GetVariableInfo. + + * ecore.cs (SimpleName): Use new + + * support.cs (ReflectionParamter.ParameterType): We unwrap the + type, as we return the actual parameter ref/unref state on a + different call. + +2002-10-30 Miguel de Icaza + + * support.cs: Return proper flags REF/OUT fixing the previous + commit. + + * expression.cs: Reverted last patch, that was wrong. Is_ref is + not used to mean `ref' but `ref or out' in ParameterReference + + * delegate.cs (FullDelegateDesc): use ParameterDesc to get the + full type signature instead of calling TypeManger.CSharpName + ourselves. + + * support.cs (InternalParameters.ParameterDesc): Do not compare + directly to the modflags, because REF/OUT will actually be bitsets + if set. + + * delegate.cs (VerifyMethod): Check also the modifiers. + + * cs-tokenizer.cs: Fix bug where floating point values with an + exponent where a sign was missing was ignored. + + * driver.cs: Allow multiple assemblies to be specified in a single + /r: argument + +2002-10-28 Miguel de Icaza + + * cs-parser.jay: Ugly. We had to add a multiplicative_expression, + because identifiers after a parenthesis would end up in this kind + of production, and we needed to desamiguate it for having casts + like: + + (UserDefinedType *) xxx + +2002-10-24 Miguel de Icaza + + * typemanager.cs (RealMemberLookup): when we deal with a subclass, + we should set on the Bindingflags.NonPublic, but not turn on + private_ok. private_ok controls whether a Private member is + returned (this is chekced on the filter routine), while the + BindingFlags.NonPublic just controls whether private/protected + will be allowed. This fixes the problem part of the problem of + private properties being allowed to be used in derived classes. + + * expression.cs (BaseAccess): Provide an DoResolveLValue method, + so we can call the children DoResolveLValue method (this will + properly signal errors on lvalue assignments to base properties) + + * ecore.cs (PropertyExpr.ResolveAccessors): If both setter and + getter are null, and we have a property info, we know that this + happened because the lookup failed, so we report an error 122 for + protection level violation. + + We also silently return if setter and getter are null in the + resolve functions, this condition only happens if we have flagged + the error before. This is the other half of the problem. + + (PropertyExpr.ResolveAccessors): Turns out that PropertyInfo does + not have accessibility information, that is why we were returning + true in the filter function in typemanager.cs. + + To properly report 122 (property is inaccessible because of its + protection level) correctly, we report this error in ResolveAccess + by failing if both the setter and the getter are lacking (ie, the + lookup failed). + + DoResolve and DoLResolve have been modified to check for both + setter/getter being null and returning silently, the reason being + that I did not want to put the knowledge about this error in upper + layers, like: + + int old = Report.Errors; + x = new PropertyExpr (...); + if (old != Report.Errors) + return null; + else + return x; + + So the property expr is returned, but it is invalid, so the error + will be flagged during the resolve process. + + * class.cs: Remove InheritablePropertySignatureCompare from the + class, as we no longer depend on the property signature to compute + whether it is possible to implement a method or not. + + The reason is that calling PropertyInfo.GetGetMethod will return + null (in .NET, in Mono it works, and we should change this), in + cases where the Get Method does not exist in that particular + class. + + So this code: + + class X { public virtual int A { get { return 1; } } } + class Y : X { } + class Z : Y { public override int A { get { return 2; } } } + + Would fail in Z because the parent (Y) would not have the property + defined. So we avoid this completely now (because the alternative + fix was ugly and slow), and we now depend exclusively on the + method names. + + (PropertyBase.CheckBase): Use a method-base mechanism to find our + reference method, instead of using the property. + + * typemanager.cs (GetPropertyGetter, GetPropertySetter): These + routines are gone now. + + * typemanager.cs (GetPropertyGetter, GetPropertySetter): swap the + names, they were incorrectly named. + + * cs-tokenizer.cs: Return are more gentle token on failure. + + * pending.cs (PendingImplementation.InterfaceMethod): This routine + had an out-of-sync index variable, which caused it to remove from + the list of pending methods the wrong method sometimes. + +2002-10-22 Miguel de Icaza + + * ecore.cs (PropertyExpr): Do not use PropertyInfo.CanRead, + CanWrite, because those refer to this particular instance of the + property, and do not take into account the fact that we can + override single members of a property. + + Constructor requires an EmitContext. The resolution process does + not happen here, but we need to compute the accessors before, + because the resolution does not always happen for properties. + + * typemanager.cs (RealMemberLookup): Set private_ok if we are a + subclass, before we did not update this flag, but we did update + bindingflags. + + (GetAccessors): Drop this routine, as it did not work in the + presence of partially overwritten set/get methods. + + Notice that this broke the cs1540 detection, but that will require + more thinking. + +2002-10-22 Gonzalo Paniagua Javier + + * class.cs: + * codegen.cs: + * driver.cs: issue a warning instead of an error if we don't support + debugging for the platform. Also ignore a couple of errors that may + arise when trying to write the symbols. Undo my previous patch. + +2002-10-22 Gonzalo Paniagua Javier + + * driver.cs: ignore /debug switch except for Unix platforms. + +2002-10-23 Nick Drochak + + * makefile: Remove mcs2.exe and mcs3.exe on 'make clean' + +2002-10-21 Miguel de Icaza + + * driver.cs: Do not make mcs-debug conditional, so we do not break + builds that use it. + + * statement.cs (UsageVector.MergeChildren): I would like Martin to + review this patch. But basically after all the children variables + have been merged, the value of "Breaks" was not being set to + new_breaks for Switch blocks. I think that it should be set after + it has executed. Currently I set this to the value of new_breaks, + but only if new_breaks is FlowReturn.ALWAYS, which is a bit + conservative, but I do not understand this code very well. + + I did not break anything in the build, so that is good ;-) + + * cs-tokenizer.cs: Also allow \r in comments as a line separator. + +2002-10-20 Mark Crichton + + * cfold.cs: Fixed compile blocker. Really fixed it this time. + +2002-10-20 Nick Drochak + + * cfold.cs: Fixed compile blocker. + +2002-10-20 Miguel de Icaza + + * driver.cs: I was chekcing the key, not the file. + +2002-10-19 Ravi Pratap + + * ecore.cs (UserDefinedConversion): Get rid of the bogus error + message that we were generating - we just need to silently return + a null. + +2002-10-19 Miguel de Icaza + + * class.cs (Event.Define): Change my previous commit, as this + breaks the debugger. This is a temporary hack, as it seems like + the compiler is generating events incorrectly to begin with. + + * expression.cs (Binary.ResolveOperator): Added support for + "U operator - (E x, E y)" + + * cfold.cs (BinaryFold): Added support for "U operator - (E x, E + y)". + + * ecore.cs (FieldExpr.AddressOf): We had a special code path for + init-only variables, but this path did not take into account that + there might be also instance readonly variables. Correct this + problem. + + This fixes bug 32253 + + * delegate.cs (NewDelegate.DoResolve): Catch creation of unsafe + delegates as well. + + * driver.cs: Change the extension for modules to `netmodule' + + * cs-parser.jay: Improved slightly the location tracking for + the debugger symbols. + + * class.cs (Event.Define): Use Modifiers.FieldAttr on the + modifiers that were specified instead of the hardcoded value + (FamAndAssem). This was basically ignoring the static modifier, + and others. Fixes 32429. + + * statement.cs (Switch.SimpleSwitchEmit): Simplified the code, and + fixed a bug in the process (32476) + + * expression.cs (ArrayAccess.EmitAssign): Patch from + hwang_rob@yahoo.ca that fixes bug 31834.3 + +2002-10-18 Miguel de Icaza + + * driver.cs: Make the module extension .netmodule. + +2002-10-16 Miguel de Icaza + + * driver.cs: Report an error if the resource file is not found + instead of crashing. + + * ecore.cs (PropertyExpr.EmitAssign): Pass IsBase instead of + false, like Emit does. + +2002-10-16 Nick Drochak + + * typemanager.cs: Remove unused private member. Also reported mcs + bug to report this as a warning like csc. + +2002-10-15 Martin Baulig + + * statement.cs (Statement.Emit): Made this a virtual method; emits + the line number info and calls DoEmit(). + (Statement.DoEmit): New protected abstract method, formerly knows + as Statement.Emit(). + + * codegen.cs (EmitContext.Mark): Check whether we have a symbol writer. + +2002-10-11 Miguel de Icaza + + * class.cs: Following the comment from 2002-09-26 to AddMethod, I + have fixed a remaining problem: not every AddXXXX was adding a + fully qualified name. + + Now everyone registers a fully qualified name in the DeclSpace as + being defined instead of the partial name. + + Downsides: we are slower than we need to be due to the excess + copies and the names being registered this way. + + The reason for this is that we currently depend (on the corlib + bootstrap for instance) that types are fully qualified, because + we dump all the types in the namespace, and we should really have + types inserted into the proper namespace, so we can only store the + basenames in the defined_names array. + +2002-10-10 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): Reverted the patch + from bug #31834, see the bug report for a testcase which is + miscompiled. + +2002-10-10 Martin Baulig + + * codegen.cs (EmitContext.Breaks): Removed, we're now using the + flow analysis code for this. + + * statement.cs (Do, While, For): Tell the flow analysis code about + infinite loops. + (FlowBranching.UsageVector): Added support for infinite loops. + (Block.Resolve): Moved the dead code elimination here and use flow + analysis to do it. + +2002-10-09 Miguel de Icaza + + * class.cs (Field.Define): Catch cycles on struct type + definitions. + + * typemanager.cs (IsUnmanagedtype): Do not recursively check + fields if the fields are static. We only need to check instance + fields. + + * expression.cs (As.DoResolve): Test for reference type. + + * statement.cs (Using.ResolveExpression): Use + ConvertImplicitRequired, not ConvertImplicit which reports an + error on failture + (Using.ResolveLocalVariableDecls): ditto. + + * expression.cs (Binary.ResolveOperator): Report errors in a few + places where we had to. + + * typemanager.cs (IsUnmanagedtype): Finish implementation. + +2002-10-08 Miguel de Icaza + + * expression.cs: Use StoreFromPtr instead of extracting the type + and then trying to use Stelem. Patch is from hwang_rob@yahoo.ca + + * ecore.cs (ImplicitReferenceConversion): It is possible to assign + an enumeration value to a System.Enum, but System.Enum is not a + value type, but an class type, so we need to box. + + (Expression.ConvertExplicit): One codepath could return + errors but not flag them. Fix this. Fixes #31853 + + * parameter.cs (Resolve): Do not allow void as a parameter type. + +2002-10-06 Martin Baulig + + * statemenc.cs (FlowBranching.SetParameterAssigned): Don't crash + if it's a class type and not a struct. Fixes #31815. + +2002-10-06 Martin Baulig + + * statement.cs: Reworked the flow analysis code a bit to make it + usable for dead code elimination. + +2002-10-06 Gonzalo Paniagua Javier + + * cs-parser.jay: allow empty source files. Fixes bug #31781. + +2002-10-04 Miguel de Icaza + + * expression.cs (ComposedCast.DoResolveType): A quick workaround + to fix the test 165, will investigate deeper. + +2002-10-04 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Make + finally blocks actually work. + (Try.Resolve): We don't need to create a sibling for `finally' if + there is no finally block. + +2002-10-04 Martin Baulig + + * class.cs (Constructor.Define): The default accessibility for a + non-default constructor is private, not public. + +2002-10-04 Miguel de Icaza + + * class.cs (Constructor): Make AllowedModifiers public, add + EXTERN. + + * cs-parser.jay: Perform the modifiers test here, as the + constructor for the Constructor class usually receives a zero + because of the way we create it (first we create, later we + customize, and we were never checking the modifiers). + + * typemanager.cs (Typemanager.LookupTypeDirect): This new function + is a version of LookupTypeReflection that includes the type-name + cache. This can be used as a fast path for functions that know + the fully qualified name and are only calling into *.GetType() to + obtain a composed type. + + This is also used by TypeManager.LookupType during its type + composition. + + (LookupType): We now also track the real type name, as sometimes + we can get a quey for the real type name from things like + ComposedCast. This fixes bug 31422. + + * expression.cs (ComposedCast.Resolve): Since we are obtaining a + complete type fullname, it does not have to go through the type + resolution system to obtain the composed version of the type (for + obtaining arrays or pointers). + + (Conditional.Emit): Use the EmitBoolExpression to + generate nicer code, as requested by Paolo. + + (ArrayCreation.CheckIndices): Use the patch from + hwang_rob@yahoo.ca to validate the array initializers. + +2002-10-03 Miguel de Icaza + + * class.cs (ConstructorInitializer.Emit): simplify code by using + Invocation.EmitCall, and at the same time, fix the bugs in calling + parent constructors that took variable arguments. + + * ecore.cs (Expression.ConvertNumericExplicit, + Expression.ImplicitNumericConversion): Remove the code that + manually wrapped decimal (InternalTypeConstructor call is now gone + as well). + + * expression.cs (Cast.TryReduce): Also handle decimal types when + trying to perform a constant fold on the type. + + * typemanager.cs (IsUnmanagedtype): Partially implemented. + + * parameter.cs: Removed ResolveAndDefine, as it was not needed, as + that only turned off an error report, and did nothing else. + +2002-10-02 Miguel de Icaza + + * driver.cs: Handle and ignore /fullpaths + +2002-10-01 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Catch the case where + DoNumericPromotions returns true, + + (Binary.DoNumericPromotions): Simplify the code, and the tests. + +2002-09-27 Miguel de Icaza + + * ecore.cs (EventExpr.Emit): Instead of emitting an exception, + report error 70. + +2002-09-26 Miguel de Icaza + + * ecore.cs (ConvertNumericExplicit): It is not enough that the + conversion exists, but it is also required that the conversion be + performed. This manifested in "(Type64Enum) 2". + + * class.cs (TypeManager.AddMethod): The fix is not to change + AddEnum, because that one was using a fully qualified name (every + DeclSpace derivative does), but to change the AddMethod routine + that was using an un-namespaced name. This now correctly reports + the duplicated name. + + Revert patch until I can properly fix it. The issue + is that we have a shared Type space across all namespaces + currently, which is wrong. + + Options include making the Namespace a DeclSpace, and merge + current_namespace/current_container in the parser. + +2002-09-25 Miguel de Icaza + + * cs-parser.jay: Improve error reporting when we get a different + kind of expression in local_variable_type and + local_variable_pointer_type. + + Propagate this to avoid missleading errors being reported. + + * ecore.cs (ImplicitReferenceConversion): treat + TypeManager.value_type as a target just like object_type. As + code like this: + + ValueType v = 1; + + Is valid, and needs to result in the int 1 being boxed before it + is assigned to the value type v. + + * class.cs (TypeContainer.AddEnum): Use the basename, not the name + to validate the enumeration name. + + * expression.cs (ArrayAccess.EmitAssign): Mimic the same test from + EmitDynamicInitializers for the criteria to use Ldelema. Thanks + to hwang_rob@yahoo.ca for finding the bug and providing a patch. + + * ecore.cs (TryImplicitIntConversion): When doing an + implicit-enumeration-conversion, check if the type is 64-bits and + perform a conversion before passing to EnumConstant. + +2002-09-23 Miguel de Icaza + + * decl.cs (Error_AmbiguousTypeReference); New routine used to + report ambiguous type references. Unlike the MS version, we + report what the ambiguity is. Innovation at work ;-) + + (DeclSpace.FindType): Require a location argument to + display when we display an ambiguous error. + + * ecore.cs: (SimpleName.DoResolveType): Pass location to FindType. + + * interface.cs (GetInterfaceTypeByName): Pass location to FindType. + + * expression.cs (EmitDynamicInitializers): Apply patch from + hwang_rob@yahoo.ca that fixes the order in which we emit our + initializers. + +2002-09-21 Martin Baulig + + * delegate.cs (Delegate.VerifyApplicability): Make this work if the + delegate takes no arguments. + +2002-09-20 Miguel de Icaza + + * constant.cs: Use Conv_U8 instead of Conv_I8 when loading longs + from integers. + + * expression.cs: Extract the underlying type. + + * ecore.cs (StoreFromPtr): Use TypeManager.IsEnumType instad of IsEnum + + * decl.cs (FindType): Sorry about this, fixed the type lookup bug. + +2002-09-19 Miguel de Icaza + + * class.cs (TypeContainer.DefineType): We can not use the nice + PackingSize with the size set to 1 DefineType method, because it + will not allow us to define the interfaces that the struct + implements. + + This completes the fixing of bug 27287 + + * ecore.cs (Expresion.ImplicitReferenceConversion): `class-type S' + means also structs. This fixes part of the problem. + (Expresion.ImplicitReferenceConversionExists): ditto. + + * decl.cs (DeclSparce.ResolveType): Only report the type-not-found + error if there were no errors reported during the type lookup + process, to avoid duplicates or redundant errors. Without this + you would get an ambiguous errors plus a type not found. We have + beaten the user enough with the first error. + + (DeclSparce.FindType): Emit a warning if we have an ambiguous + reference. + + * ecore.cs (SimpleName.DoResolveType): If an error is emitted + during the resolution process, stop the lookup, this avoids + repeated error reports (same error twice). + + * rootcontext.cs: Emit a warning if we have an ambiguous reference. + + * typemanager.cs (LookupType): Redo the type lookup code to match + the needs of System.Reflection. + + The issue is that System.Reflection requires references to nested + types to begin with a "+" sign instead of a dot. So toplevel + types look like: "NameSpace.TopLevelClass", and nested ones look + like "Namespace.TopLevelClass+Nested", with arbitrary nesting + levels. + +2002-09-19 Martin Baulig + + * codegen.cs (EmitContext.EmitTopBlock): If control flow analysis + says that a method always returns or always throws an exception, + don't report the CS0161. + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Always + set `Returns = new_returns'. + +2002-09-19 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): When resolving + to an enum constant, check for a CS0176. + +2002-09-18 Miguel de Icaza + + * class.cs (TypeContainer.CheckPairedOperators): Now we check + for operators that must be in pairs and report errors. + + * ecore.cs (SimpleName.DoResolveType): During the initial type + resolution process, when we define types recursively, we must + check first for types in our current scope before we perform + lookups in the enclosing scopes. + + * expression.cs (MakeByteBlob): Handle Decimal blobs. + + (Invocation.VerifyArgumentsCompat): Call + TypeManager.TypeToCoreType on the parameter_type.GetElementType. + I thought we were supposed to always call this, but there are a + few places in the code where we dont do it. + +2002-09-17 Miguel de Icaza + + * driver.cs: Add support in -linkres and -resource to specify the + name of the identifier. + +2002-09-16 Miguel de Icaza + + * ecore.cs (StandardConversionExists): Sync with the conversion + code: allow anything-* to void* conversions. + + (FindMostSpecificSource): Use an Expression argument + instead of a Type, because we might be handed over a Literal which + gets a few more implicit conversions that plain types do not. So + this information was being lost. + + Also, we drop the temporary type-holder expression when not + required. + +2002-09-17 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Don't check the base class if + this is an explicit interface implementation. + +2002-09-17 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Make this work for indexers with + different `IndexerName' attributes. + + * expression.cs (BaseIndexerAccess): Rewrote this class to use IndexerAccess. + (IndexerAccess): Added special protected ctor for BaseIndexerAccess and + virtual CommonResolve(). + +2002-09-16 Miguel de Icaza + + * enum.cs (LookupEnumValue): Use the EnumConstant declared type, + and convert that to the UnderlyingType. + + * statement.cs (Foreach.Resolve): Indexers are just like variables + or PropertyAccesses. + + * cs-tokenizer.cs (consume_string): Track line numbers and columns + inside quoted strings, we were not doing this before. + +2002-09-16 Martin Baulig + + * ecore.cs (MethodGroupExpr.DoResolve): If we have an instance expression, + resolve it. This is needed for the definite assignment check of the + instance expression, fixes bug #29846. + (PropertyExpr.DoResolve, EventExpr.DoResolve): Likewise. + +2002-09-16 Nick Drochak + + * parameter.cs: Fix compile error. Cannot reference static member + from an instance object. Is this an mcs bug? + +2002-09-14 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Don't add an interface + multiple times. Fixes bug #30295, added test-166.cs. + +2002-09-14 Martin Baulig + + * statement.cs (Block.Emit): Don't emit unreachable code. + (Switch.SimpleSwitchEmit, Switch.TableSwitchEmit): Check for missing + `break' statements. + (Goto.Emit, Continue.Emit): Set ec.Breaks = true. + +2002-09-14 Martin Baulig + + * parameter.cs (Parameter.Attributes): Make this work if Modifier.ISBYREF + is set. + +2002-09-14 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): This must return false + if `type == parent' since in this case `type.IsSubclassOf (parent)' will + be false on the ms runtime. + +2002-09-13 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Include the member name in + the CS0038 error message. + +2002-09-12 Miguel de Icaza + + * expression.cs (CheckedExpr, UnCheckedExpr): If we have a + constant inside, return it. + +2002-09-12 Martin Baulig + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): Check whether an + implicit conversion can be done between enum types. + + * enum.cs (Enum.LookupEnumValue): If the value is an EnumConstant, + check whether an implicit conversion to the current enum's UnderlyingType + exists and report an error if not. + + * codegen.cs (CodeGen.Init): Delete the symbol file when compiling + without debugging support. + + * delegate.cs (Delegate.CloseDelegate): Removed, use CloseType instead. + Fixes bug #30235. Thanks to Ricardo Fernández Pascual. + +2002-09-12 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): New method. + + * ecore.cs (IMemberExpr.DeclaringType): New property. + (SimpleName.SimpleNameResolve): Check whether we're accessing a + nonstatic member of an outer type (CS0038). + +2002-09-11 Miguel de Icaza + + * driver.cs: Activate the using-error detector at warning level + 4 (at least for MS-compatible APIs). + + * namespace.cs (VerifyUsing): Small buglett fix. + + * pending.cs (PendingImplementation): pass the container pointer. + + * interface.cs (GetMethods): Allow for recursive definition. Long + term, I would like to move every type to support recursive + definitions, not the current ordering mechanism that we have right + now. + + The situation is this: Attributes are handled before interfaces, + so we can apply attributes to interfaces. But some attributes + implement interfaces, we will now handle the simple cases + (recursive definitions will just get an error). + + * parameter.cs: Only invalidate types at the end if we fail to + lookup all types. + +2002-09-09 Martin Baulig + + * ecore.cs (PropertyExpr.Emit): Also check for + TypeManager.system_int_array_get_length so this'll also work when + compiling corlib. Fixes #30003. + +2002-09-09 Martin Baulig + + * expression.cs (ArrayCreation.MakeByteBlob): Added support for enums + and throw an exception if we can't get the type's size. Fixed #30040, + added test-165.cs. + +2002-09-09 Martin Baulig + + * ecore.cs (PropertyExpr.DoResolve): Added check for static properies. + + * expression.cs (SizeOf.DoResolve): Sizeof is only allowed in unsafe + context. Fixes bug #30027. + + * delegate.cs (NewDelegate.Emit): Use OpCodes.Ldvirtftn for + virtual functions. Fixes bug #30043, added test-164.cs. + +2002-09-08 Ravi Pratap + + * attribute.cs : Fix a small NullRef crash thanks to my stupidity. + +2002-09-08 Nick Drochak + + * driver.cs: Use an object to get the windows codepage since it's not a + static property. + +2002-09-08 Miguel de Icaza + + * statement.cs (For.Emit): for infinite loops (test == null) + return whether there is a break inside, not always "true". + + * namespace.cs (UsingEntry): New struct to hold the name of the + using definition, the location where it is defined, and whether it + has been used in a successful type lookup. + + * rootcontext.cs (NamespaceLookup): Use UsingEntries instead of + strings. + + * decl.cs: ditto. + +2002-09-06 Ravi Pratap + + * attribute.cs : Fix incorrect code which relied on catching + a NullReferenceException to detect a null being passed in + where an object was expected. + +2002-09-06 Miguel de Icaza + + * statement.cs (Try): flag the catch variable as assigned + + * expression.cs (Cast): Simplified by using ResolveType instead of + manually resolving. + + * statement.cs (Catch): Fix bug by using ResolveType. + +2002-09-06 Ravi Pratap + + * expression.cs (BetterConversion): Special case for when we have + a NullLiteral as the argument and we have to choose between string + and object types - we choose string the way csc does. + + * attribute.cs (Attribute.Resolve): Catch the + NullReferenceException and report error #182 since the Mono + runtime no more has the bug and having this exception raised means + we tried to select a constructor which takes an object and is + passed a null. + +2002-09-05 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Flag a nicer error + message (1502, 1503) when we can't locate a method after overload + resolution. This is much more informative and closes the bug + Miguel reported. + + * interface.cs (PopulateMethod): Return if there are no argument + types. Fixes a NullReferenceException bug. + + * attribute.cs (Attribute.Resolve): Ensure we allow TypeOf + expressions too. Previously we were checking only in one place for + positional arguments leaving out named arguments. + + * ecore.cs (ImplicitNumericConversion): Conversion from underlying + type to the enum type is not allowed. Remove code corresponding to + that. + + (ConvertNumericExplicit): Allow explicit conversions from + the underlying type to enum type. This precisely follows the spec + and closes a bug filed by Gonzalo. + +2002-09-04 Gonzalo Paniagua Javier + + * compiler.csproj: + * compiler.csproj.user: patch from Adam Chester (achester@bigpond.com). + +2002-09-03 Miguel de Icaza + + * statement.cs (SwitchLabel.ResolveAndReduce): In the string case, + it was important that we stored the right value after the + reduction in `converted'. + +2002-09-04 Martin Baulig + + * location.cs (Location.SymbolDocument): Use full pathnames for the + source files. + +2002-08-30 Miguel de Icaza + + * expression.cs (ComposedCast): Use DeclSparce.ResolveType instead + of the expression resolve mechanism, because that will catch the + SimpleName error failures. + + (Conditional): If we can not resolve the + expression, return, do not crash. + +2002-08-29 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: + (location): display token name instead of its number. + +2002-08-28 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't silently return + but return an error if an operator cannot be applied between two + enum types. + +2002-08-28 Martin Baulig + + * class.cs (Constructor.Define): Set the permission attributes + correctly instead of making all constructors public. + +2002-08-28 Martin Baulig + + * ecore.cs (Expression.DoResolve): Do a TypeManager.MemberLook + for private members before reporting a CS0103; if we find anything, + it's a CS0122. + +2002-08-28 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): It's not enough + to check whether `closure_start_type == closure_invocation_type', + we also need to check whether `m.DeclaringType == closure_invocation_type' + before bypassing the permission checks. We might be accessing + protected/private members from the base class. + (TypeManager.RealMemberLookup): Only set private_ok if private + members were requested via BindingFlags.NonPublic. + + * ecore.cs (MethodGroupExpr.IsExplicitImpl): New property. + + * expression.cs (MemberAccess.ResolveMemberAccess): Set + MethodGroupExpr.IsExplicitImpl if appropriate. + (Invocation.DoResolve): Don't report the CS0120 for explicit + interface implementations. + +2002-08-27 Martin Baulig + + * expression.cs (Invocation.DoResolve): If this is a static + method and we don't have an InstanceExpression, we must report + a CS0120. + +2002-08-25 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't allow `!=' and + `==' between a valuetype and an object. + +2002-08-25 Miguel de Icaza + + * ecore.cs (TypeExpr): Provide a ToString method. + +2002-08-24 Martin Baulig + + * codegen.cs (CodeGen.InitMonoSymbolWriter): The symbol file is + now called proggie.dbg and it's a binary file. + +2002-08-23 Martin Baulig + + * decl.cs (MemberCache.AddMethods): Ignore varargs methods. + +2002-08-23 Martin Baulig + + * struct.cs (MyStructInfo.ctor): Make this work with empty + structs; it's not allowed to use foreach() on null. + +2002-08-23 Martin Baulig + + * codegen.cs (CodeGen.InitMonoSymbolWriter): Tell the symbol + writer the full pathname of the generated assembly. + +2002-08-23 Martin Baulig + + * statements.cs (FlowBranching.UsageVector.MergeChildren): + A `finally' block never returns or breaks; improved handling of + unreachable code. + +2002-08-23 Martin Baulig + + * statement.cs (Throw.Resolve): Allow `throw null'. + +2002-08-23 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): If this is an + EventExpr, don't do a DeclaredOnly MemberLookup, but check whether + `ee.EventInfo.DeclaringType == ec.ContainerType'. The + MemberLookup would return a wrong event if this is an explicit + interface implementation and the class has an event with the same + name. + +2002-08-23 Martin Baulig + + * statement.cs (Block.AddChildVariableNames): New public method. + (Block.AddChildVariableName): Likewise. + (Block.IsVariableNameUsedInChildBlock): Likewise. + (Block.AddVariable): Check whether a variable name has already + been used in a child block. + + * cs-parser.jay (declare_local_variables): Mark all variable names + from the current block as being used in a child block in the + implicit block. + +2002-08-23 Martin Baulig + + * codegen.cs (CodeGen.InitializeSymbolWriter): Abort if we can't + find the symbol writer. + + * driver.cs: csc also allows the arguments to /define being + separated by commas, not only by semicolons. + +2002-08-23 Martin Baulig + + * interface.cs (Interface.GetMembers): Added static check for events. + +2002-08-15 Martin Baulig + + * class.cs (MethodData.EmitDestructor): In the Expression.MemberLookup + call, use ec.ContainerType.BaseType as queried_type and invocation_type. + + * ecore.cs (Expression.MemberLookup): Added documentation and explained + why the MethodData.EmitDestructor() change was necessary. + +2002-08-20 Martin Baulig + + * class.cs (TypeContainer.FindMembers): Added static check for events. + + * decl.cs (MemberCache.AddMembers): Handle events like normal members. + + * typemanager.cs (TypeHandle.GetMembers): When queried for events only, + use Type.GetEvents(), not Type.FindMembers(). + +2002-08-20 Martin Baulig + + * decl.cs (MemberCache): Added a special method cache which will + be used for method-only searched. This ensures that a method + search will return a MethodInfo with the correct ReflectedType for + inherited methods. + +2002-08-20 Martin Baulig + + * decl.cs (DeclSpace.FindMembers): Made this public. + +2002-08-20 Gonzalo Paniagua Javier + + * delegate.cs: fixed build on windows. + [FIXME: Filed as bug #29150: MCS must report these errors.] + +2002-08-19 Ravi Pratap + + * ecore.cs (StandardConversionExists): Return a false + if we are trying to convert the void type to anything else + since that is not allowed. + + * delegate.cs (DelegateInvocation.DoResolve): Ensure that + we flag error 70 in the event an event is trying to be accessed + directly from outside the declaring type. + +2002-08-20 Martin Baulig + + * typemanager.cs, decl.cs: Moved MemberList, IMemberContainer and + MemberCache from typemanager.cs to decl.cs. + +2002-08-19 Martin Baulig + + * class.cs (TypeContainer): Implement IMemberContainer. + (TypeContainer.DefineMembers): Create the MemberCache. + (TypeContainer.FindMembers): Do better BindingFlags checking; only + return public members if BindingFlags.Public was given, check + whether members are static. + +2002-08-16 Martin Baulig + + * decl.cs (DeclSpace.Define): Splitted this in Define and + DefineMembers. DefineMembers is called first and initializes the + MemberCache. + + * rootcontext.cs (RootContext.DefineMembers): New function. Calls + DefineMembers() on all our DeclSpaces. + + * class.cs (TypeContainer.Define): Moved all code to DefineMembers(), + but call DefineMembers() on all nested interfaces. We call their + Define() in our new Define() function. + + * interface.cs (Interface): Implement IMemberContainer. + (Interface.Define): Moved all code except the attribute stuf to + DefineMembers(). + (Interface.DefineMembers): Initialize the member cache. + + * typemanager.cs (IMemberFinder): Removed this interface, we don't + need this anymore since we can use MemberCache.FindMembers directly. + +2002-08-19 Martin Baulig + + * typemanager.cs (MemberCache): When creating the cache for an + interface type, add all inherited members. + (TypeManager.MemberLookup_FindMembers): Changed `ref bool searching' + to `out bool used_cache' and documented it. + (TypeManager.MemberLookup): If we already used the cache in the first + iteration, we don't need to do the interfaces check. + +2002-08-19 Martin Baulig + + * decl.cs (DeclSpace.FindMembers): New abstract method. Moved this + here from IMemberFinder and don't implement this interface anymore. + (DeclSpace.MemberCache): Moved here from IMemberFinder. + + * typemanager.cs (IMemberFinder): This interface is now only used by + classes which actually support the member cache. + (TypeManager.builder_to_member_finder): Renamed to builder_to_declspace + since we only put DeclSpaces into this Hashtable. + (MemberLookup_FindMembers): Use `builder_to_declspace' if the type is + a dynamic type and TypeHandle.GetTypeHandle() otherwise. + +2002-08-16 Martin Baulig + + * typemanager.cs (ICachingMemberFinder): Removed. + (IMemberFinder.MemberCache): New property. + (TypeManager.FindMembers): Merged this with RealFindMembers(). + This function will never be called from TypeManager.MemberLookup() + so we can't use the cache here, just the IMemberFinder. + (TypeManager.MemberLookup_FindMembers): Check whether the + IMemberFinder has a MemberCache and call the cache's FindMembers + function. + (MemberCache): Rewrote larger parts of this yet another time and + cleaned it up a bit. + +2002-08-15 Miguel de Icaza + + * driver.cs (LoadArgs): Support quoting. + + (Usage): Show the CSC-like command line arguments. + + Improved a few error messages. + +2002-08-15 Martin Baulig + + * typemanager.cs (IMemberContainer.Type): New property. + (IMemberContainer.IsInterface): New property. + + The following changes are conditional to BROKEN_RUNTIME, which is + defined at the top of the file. + + * typemanager.cs (MemberCache.MemberCache): Don't add the base + class'es members, but add all members from TypeHandle.ObjectType + if we're an interface. + (MemberCache.AddMembers): Set the Declared flag if member.DeclaringType + is the current type. + (MemberCache.CacheEntry.Container): Removed this field. + (TypeHandle.GetMembers): Include inherited members. + +2002-08-14 Gonzalo Paniagua Javier + + * typemanager.cs: fixed compilation and added a comment on a field that + is never used. + +2002-08-15 Martin Baulig + + * class.cs (ConstructorInitializer.Resolve): In the + Expression.MemberLookup call, use the queried_type as + invocation_type. + + * typemanager.cs (IMemberContainer.GetMembers): Removed the `bool + declared' attribute, it's always true. + (IMemberContainer.Parent, IMemberContainer.Name): New properties. + (TypeManager.MemberLookup_FindMembers): [FIXME FIXME FIXME] Added + temporary wrapper for FindMembers which tells MemberLookup whether + members from the base classes are included in the return value. + This will go away soon. + (TypeManager.MemberLookup): Use this temporary hack here; once the + new MemberCache is completed, we don't need to do the DeclaredOnly + looping here anymore since the MemberCache will take care of this. + (TypeManager.IsSubclassOrNestedChildOf): Allow `type == parent'. + (MemberCache): When creating the MemberCache for a class, get + members from the current class and all its base classes. + (MemberCache.CacheEntry.Container): New field. This is a + temporary hack until the Mono runtime is fixed to distinguish + between ReflectedType and DeclaringType. It allows us to use MCS + with both the MS runtime and the unfixed Mono runtime without + problems and without accecting performance. + (MemberCache.SearchMembers): The DeclaredOnly looping from + TypeManager.MemberLookup is now done here. + +2002-08-14 Martin Baulig + + * statement.cs (MyStructInfo.MyStructInfo): Don't call + Type.GetFields on dynamic types but get the fields from the + corresponding TypeContainer. + (MyStructInfo.GetStructInfo): Added check for enum types. + + * typemanager.cs (MemberList.IsSynchronized): Implemented. + (MemberList.SyncRoot): Implemented. + (TypeManager.FilterWithClosure): No need to check permissions if + closure_start_type == closure_invocation_type, don't crash if + closure_invocation_type is null. + +2002-08-13 Martin Baulig + + Rewrote TypeContainer.FindMembers to use a member cache. This + gives us a speed increase of about 35% for the self-hosting MCS + build and of about 15-20% for the class libs (both on GNU/Linux). + + * report.cs (Timer): New class to get enhanced profiling. This + whole class is "TIMER" conditional since it remarkably slows down + compilation speed. + + * class.cs (MemberList): New class. This is an IList wrapper + which we're now using instead of passing MemberInfo[]'s around to + avoid copying this array unnecessarily. + (IMemberFinder.FindMember): Return a MemberList, not a MemberInfo []. + (ICachingMemberFinder, IMemberContainer): New interface. + (TypeManager.FilterWithClosure): If `criteria' is null, the name + has already been checked, otherwise use it for the name comparision. + (TypeManager.FindMembers): Renamed to RealMemberFinder and + provided wrapper which tries to use ICachingMemberFinder.FindMembers + if possible. Returns a MemberList, not a MemberInfo []. + (TypeHandle): New class, implements IMemberContainer. We create + one instance of this class per type, it contains a MemberCache + which is used to do the member lookups. + (MemberCache): New class. Each instance of this class contains + all members of a type and a name-based hash table. + (MemberCache.FindMembers): This is our new member lookup + function. First, it looks up all members of the requested name in + the hash table. Then, it walks this list and sorts out all + applicable members and returns them. + +2002-08-13 Martin Baulig + + In addition to a nice code cleanup, this gives us a performance + increase of about 1.4% on GNU/Linux - not much, but it's already + half a second for the self-hosting MCS compilation. + + * typemanager.cs (IMemberFinder): New interface. It is used by + TypeManager.FindMembers to call FindMembers on a TypeContainer, + Enum, Delegate or Interface. + (TypeManager.finder_to_member_finder): New PtrHashtable. + (TypeManager.finder_to_container): Removed. + (TypeManager.finder_to_delegate): Removed. + (TypeManager.finder_to_interface): Removed. + (TypeManager.finder_to_enum): Removed. + + * interface.cs (Interface): Implement IMemberFinder. + + * delegate.cs (Delegate): Implement IMemberFinder. + + * enum.cs (Enum): Implement IMemberFinder. + + * class.cs (TypeContainer): Implement IMemberFinder. + +2002-08-12 Martin Baulig + + * ecore.cs (TypeExpr.DoResolveType): Mark this as virtual. + +2002-08-12 Martin Baulig + + * ecore.cs (ITypeExpression): New interface for expressions which + resolve to a type. + (TypeExpression): Renamed to TypeLookupExpression. + (Expression.DoResolve): If we're doing a types-only lookup, the + expression must implement the ITypeExpression interface and we + call DoResolveType() on it. + (SimpleName): Implement the new ITypeExpression interface. + (SimpleName.SimpleNameResolve): Removed the ec.OnlyLookupTypes + hack, the situation that we're only looking up types can't happen + anymore when this method is called. Moved the type lookup code to + DoResolveType() and call it. + (SimpleName.DoResolveType): This ITypeExpression interface method + is now doing the types-only lookup. + (TypeExpr, TypeLookupExpression): Implement ITypeExpression. + (ResolveFlags): Added MaskExprClass. + + * expression.cs (MemberAccess): Implement the ITypeExpression + interface. + (MemberAccess.DoResolve): Added support for a types-only lookup + when we're called via ITypeExpression.DoResolveType(). + (ComposedCast): Implement the ITypeExpression interface. + + * codegen.cs (EmitContext.OnlyLookupTypes): Removed. Call + Expression.Resolve() with ResolveFlags.Type instead. + +2002-08-12 Martin Baulig + + * interface.cs (Interface.Define): Apply attributes. + + * attribute.cs (Attribute.ApplyAttributes): Added support for + interface attributes. + +2002-08-11 Martin Baulig + + * statement.cs (Block.Emit): Only check the "this" variable if we + do not always throw an exception. + + * ecore.cs (PropertyExpr.DoResolveLValue): Implemented, check + whether the property has a set accessor. + +2002-08-11 Martin Baulig + + Added control flow analysis support for structs. + + * ecore.cs (ResolveFlags): Added `DisableFlowAnalysis' to resolve + with control flow analysis turned off. + (IVariable): New interface. + (SimpleName.SimpleNameResolve): If MemberAccess.ResolveMemberAccess + returns an IMemberExpr, call DoResolve/DoResolveLValue on it. + (FieldExpr.DoResolve): Resolve the instance expression with flow + analysis turned off and do the definite assignment check after the + resolving when we know what the expression will resolve to. + + * expression.cs (LocalVariableReference, ParameterReference): + Implement the new IVariable interface, only call the flow analysis + code if ec.DoFlowAnalysis is true. + (This): Added constructor which takes a Block argument. Implement + the new IVariable interface. + (MemberAccess.DoResolve, MemberAccess.DoResolveLValue): Call + DoResolve/DoResolveLValue on the result of ResolveMemberLookup(). + This does the definite assignment checks for struct members. + + * class.cs (Constructor.Emit): If this is a non-static `struct' + constructor which doesn't have any initializer, call + Block.AddThisVariable() to tell the flow analysis code that all + struct elements must be initialized before control returns from + the constructor. + + * statement.cs (MyStructInfo): New public class. + (UsageVector.this [VariableInfo vi]): Added `int field_idx' + argument to this indexer. If non-zero, check an individual struct + member, not the whole struct. + (FlowBranching.CheckOutParameters): Check struct members. + (FlowBranching.IsVariableAssigned, SetVariableAssigned): Added + overloaded versions of these methods which take an additional + `int field_idx' argument to check struct members. + (FlowBranching.IsParameterAssigned, SetParameterAssigned): Added + overloaded versions of these methods which take an additional + `string field_name' argument to check struct member.s + (VariableInfo): Implement the IVariable interface. + (VariableInfo.StructInfo): New public property. Returns the + MyStructInfo instance of the variable if it's a struct or null. + (Block.AddThisVariable): New public method. This is called from + Constructor.Emit() for non-static `struct' constructor which do + not have any initializer. It creates a special variable for the + "this" instance variable which will be checked by the flow + analysis code to ensure that all of the struct's fields are + initialized before control returns from the constructor. + (UsageVector): Added support for struct members. If a + variable/parameter is a struct with N members, we reserve a slot + in the usage vector for each member. A struct is considered fully + initialized if either the struct itself (slot 0) or all its + members are initialized. + +2002-08-08 Martin Baulig + + * driver.cs (Driver.MainDriver): Only report an error CS5001 + if there were no compilation errors. + + * codegen.cs (EmitContext.EmitContext): Use the DeclSpace's + `UnsafeContext' property to determine whether the parent is in + unsafe context rather than checking the parent's ModFlags: + classes nested in an unsafe class are unsafe as well. + +2002-08-08 Martin Baulig + + * statement.cs (UsageVector.MergeChildren): Distinguish between + `Breaks' and `Returns' everywhere, don't set `Breaks' anymore if + we return. Added test17() and test18() to test-154.cs. + +2002-08-08 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): If we have + Family access, make sure the invoking type isn't a subclass of the + queried type (that'd be a CS1540). + + * ecore.cs (Expression.MemberLookup): Added overloaded version of + this method which takes an additional `Type invocation_type'. + + * expression.cs (BaseAccess.DoResolve): Use the base type as + invocation and query type. + (MemberAccess.DoResolve): If the lookup failed and we're about to + report a CS0122, try a lookup with the ec.ContainerType - if this + succeeds, we must report a CS1540. + +2002-08-08 Martin Baulig + + * ecore.cs (IMemberExpr): Added `bool IsInstance' property. + (MethodGroupExpr): Implement the IMemberExpr interface. + + * expression (MemberAccess.ResolveMemberAccess): No need to have + any special code for MethodGroupExprs anymore, they're now + IMemberExprs. + +2002-08-08 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): Check Assembly, + Family, FamANDAssem and FamORAssem permissions. + (TypeManager.IsSubclassOrNestedChildOf): New public method. + +2002-08-08 Martin Baulig + + * statement.cs (FlowBranchingType): Added LOOP_BLOCK. + (UsageVector.MergeChildren): `break' breaks unless we're in a switch + or loop block. + +Thu Aug 8 10:28:07 CEST 2002 Paolo Molaro + + * driver.cs: implemented /resource option to embed managed resources. + +2002-08-07 Martin Baulig + + * class.cs (FieldBase.Initializer): Renamed to `init' and made private. + (FieldBase.HasFieldInitializer): New public property. + (FieldBase.GetInitializerExpression): New public method. Resolves and + returns the field initializer and makes sure it is only resolved once. + (TypeContainer.EmitFieldInitializers): Call + FieldBase.GetInitializerExpression to get the initializer, this ensures + that it isn't resolved multiple times. + + * codegen.cs (EmitContext): Added `bool IsFieldInitialier'. This tells + the resolving process (SimpleName/MemberLookup) that we're currently + emitting a field initializer (which must not access any instance members, + this is an error CS0236). + + * ecore.cs (SimpleName.Error_ObjectRefRequired): Added EmitContext + argument, if the `IsFieldInitializer' flag is set, we must report and + error CS0236 and not an error CS0120. + +2002-08-07 Martin Baulig + + * ecore.cs (IMemberExpr): New public interface. + (FieldExpr, PropertyExpr, EventExpr): Implement IMemberExpr. + (SimpleName.SimpleNameResolve): Call MemberAccess.ResolveMemberAccess + if the expression is an IMemberExpr. + + * expression.cs (MemberAccess.ResolveMemberAccess): Allow `left' + to be null, implicitly default to `this' if we're non-static in + this case. Simplified the code a lot by using the new IMemberExpr + interface. Also fixed bug #28176 here. + +2002-08-06 Martin Baulig + + * cs-parser.jay (SimpleLookup): Removed. We need to create + ParameterReferences during semantic analysis so that we can do a + type-only search when resolving Cast, TypeOf and SizeOf. + (block): Pass the `current_local_parameters' to the Block's + constructor. + + * class.cs (ConstructorInitializer): Added `Parameters parameters' + argument to the constructor. + (ConstructorInitializer.Resolve): Create a temporary implicit + block with the parameters. + + * ecore.cs (SimpleName.SimpleNameResolve): Resolve parameter + references here if we aren't doing a type-only search. + + * statement.cs (Block): Added constructor which takes a + `Parameters parameters' argument. + (Block.Parameters): New public property. + + * support.cs (InternalParameters.Parameters): Renamed `parameters' + to `Parameters' and made it public readonly. + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.Warning): Made this public as well. + + * report.cs (Report.Debug): Print the contents of collections. + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.ResolveFlags): New [Flags] enum. This is + used to tell Resolve() which kinds of expressions it may return. + (Expression.Resolve): Added overloaded version of this method which + takes a `ResolveFlags flags' argument. This can be used to tell + Resolve() which kinds of expressions it may return. Reports a + CS0118 on error. + (Expression.ResolveWithSimpleName): Removed, use Resolve() with + ResolveFlags.SimpleName. + (Expression.Error118): Added overloaded version of this method which + takes a `ResolveFlags flags' argument. It uses the flags to determine + which kinds of expressions are allowed. + + * expression.cs (Argument.ResolveMethodGroup): New public method. + Resolves an argument, but allows a MethodGroup to be returned. + This is used when invoking a delegate. + + * TODO: Updated a bit. + +2002-08-06 Gonzalo Paniagua Javier + + Fixed compilation with csc. + + * ecore.cs: Expression.Error made public. Is this correct? Should + Warning be made public too? + + * expression.cs: use ea.Location instead of ea.loc. + [FIXME: Filed as bug #28607: MCS must report these errors.] + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.loc): Moved the location here instead of + duplicating it in all derived classes. + (Expression.Location): New public property. + (Expression.Error, Expression.Warning): Made them non-static and + removed the location argument. + (Expression.Warning): Added overloaded version which takes an + `int level' argument. + (Expression.Error118): Make this non-static and removed the + expression and location arguments. + (TypeExpr): Added location argument to the constructor. + + * expression.cs (StaticCallExpr): Added location argument to + the constructor. + (Indirection, PointerArithmetic): Likewise. + (CheckedExpr, UnCheckedExpr): Likewise. + (ArrayAccess, IndexerAccess, UserCast, ArrayPtr): Likewise. + (StringPtr): Likewise. + + +2002-08-05 Martin Baulig + + * expression.cs (BaseAccess.DoResolve): Actually report errors. + + * assign.cs (Assign.DoResolve): Check whether the source + expression is a value or variable. + + * statement.cs (Try.Resolve): Set ec.InTry/InCatch/InFinally + while resolving the corresponding blocks. + + * interface.cs (Interface.GetInterfaceTypeByName): Actually report + an error, don't silently return null. + + * statement.cs (Block.AddVariable): Do the error reporting here + and distinguish between CS0128 and CS0136. + (Block.DoResolve): Report all unused labels (warning CS0164). + (LabeledStatement): Pass the location to the constructor. + (LabeledStatement.HasBeenReferenced): New property. + (LabeledStatement.Resolve): Set it to true here. + + * statement.cs (Return.Emit): Return success even after reporting + a type mismatch error (CS0126 or CS0127), this is what csc does and + it avoids confusing the users with any consecutive errors. + +2002-08-05 Martin Baulig + + * enum.cs (Enum.LookupEnumValue): Catch circular definitions. + + * const.cs (Const.LookupConstantValue): Catch circular definitions. + + * expression.cs (MemberAccess.DoResolve): Silently return if an + error has already been reported. + + * ecore.cs (Expression.MemberLookupFinal): Silently return if an + error has already been reported. + +2002-08-05 Martin Baulig + + * statement.cs (UsageVector): Only initialize the `parameters' + vector if we actually have any "out" parameters. + +2002-08-05 Martin Baulig + + * expression.cs (Binary.ResolveOperator): When combining delegates, + they must have the same type. + +2002-08-05 Martin Baulig + + * typemanager.cs (TypeManager.GetArgumentTypes): Don't call + PropertyInfo.GetIndexParameters() on dynamic types, this doesn't + work with the ms runtime and we also don't need it: if we're a + PropertyBuilder and not in the `indexer_arguments' hash, then we + are a property and not an indexer. + + * class.cs (TypeContainer.AsAccessible): Use Type.IsArray, + Type.IsPointer and Type.IsByRef instead of Type.HasElementType + since the latter one doesn't work with the ms runtime. + +2002-08-03 Martin Baulig + + Fixed bugs #27998 and #22735. + + * class.cs (Method.IsOperator): New public field. + (Method.CheckBase): Report CS0111 if there's already a method + with the same parameters in the current class. Report CS0508 when + attempting to change the return type of an inherited method. + (MethodData.Emit): Report CS0179 if a method doesn't have a body + and it's not marked abstract or extern. + (PropertyBase): New abstract base class for Property and Indexer. + (PropertyBase.CheckBase): Moved here from Property and made it work + for indexers. + (PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is + the same so we can reuse it there. + (Property, Indexer): Derive from PropertyBase. + (MethodSignature.inheritable_property_signature_filter): New delegate + to find properties and indexers. + + * decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name' + argument and improved error reporting. + + * parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to + EmptyReadOnlyParameters and made it a property. + + * typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded + version of this method which takes a `PropertyInfo indexer'. + (TypeManager.RegisterIndexer): New method. + + * class.cs: Added myself as author of this file :-) + +2002-08-03 Gonzalo Paniagua Javier + + * class.cs: fixed compilation on windoze. + +2002-08-03 Martin Baulig + + * interface.cs (Interface.GetInterfaceBases): Check whether all + base interfaces are at least as accessible than the current one. + + * class.cs (TypeContainer.GetClassBases): Check whether base types + are at least as accessible than the current type. + (TypeContainer.AsAccessible): Implemented and made non-static. + (MemberBase.CheckParameters): Report errors if the accessibility + checks fail. + + * delegate.cs (Delegate.Delegate): The default visibility is + internal for top-level types and private for nested types. + (Delegate.Define): Report errors if the accessibility checks fail. + + * enum.cs (Enum.Enum): The default visibility is internal for + top-level types and private for nested types. + (Enum.DefineType): Compute the correct visibility. + + * modifiers.cs (Modifiers.TypeAttr): Added a version of this + function which takes a `bool is_toplevel' instead of a TypeContainer. + + * typemanager.cs (TypeManager.IsBuiltinType): `void' is also a + builtin type. + +2002-08-02 Martin Baulig + + * expression.cs (LocalVariableReferenc): Added constructor which + takes additional `VariableInfo vi' and `bool is_readonly' arguments. + (LocalVariableReference.IsReadOnly): New property. + (LocalVariableReference.DoResolveLValue): Report a CS1604 if the + variable is readonly, use our own readonly flag to do this; you can + use the new constructor to get a writable reference to a read-only + variable. + + * cs-parser.jay (foreach_statement, using_statement): Get a writable + reference to the local variable. + +2002-08-01 Miguel de Icaza + + * rootcontext.cs (ResolveCore): Also include System.Exception + + * statement.cs (Block.Emit): Do not emit the dead-code warnings if + we reach an EmptyStatement. + + (Catch.DoResolve, Throw.DoResolve): Throwing the System.Exception + is also fine. + + * expression.cs (Binary.ResolveOperator): Check error result in + two places. + + use brtrue/brfalse directly and avoid compares to null. + +2002-08-02 Martin Baulig + + * class.cs (TypeContainer.Define): Define all nested interfaces here. + Fixes bug #28407, added test-155.cs. + +2002-08-01 Martin Baulig + + * class.cs (Event.EmitDefaultMethod): Make this work with static + events. Fixes #28311, added verify-3.cs. + +2002-08-01 Martin Baulig + + * statement.cs (ForeachHelperMethods): Added `enumerator_type' and + `is_disposable' fields. + (Foreach.GetEnumeratorFilter): Set `hm.enumerator_type' and + `hm.is_disposable' if we're using the collection pattern. + (Foreach.EmitCollectionForeach): Use the correct type for the + enumerator's local variable, only emit the try/finally block if + necessary (fixes #27713). + +2002-08-01 Martin Baulig + + * ecore.cs (Expression.report118): Renamed to Error118 and made + it public static. + + * statement.cs (Throw.Resolve): Check whether the expression is of + the correct type (CS0118) and whether the type derives from + System.Exception (CS0155). + (Catch.Resolve): New method. Do the type lookup here and check + whether it derives from System.Exception (CS0155). + (Catch.CatchType, Catch.IsGeneral): New public properties. + + * typemanager.cs (TypeManager.exception_type): Added. + +2002-07-31 Miguel de Icaza + + * driver.cs: Updated About function. + +2002-07-31 Martin Baulig + + Implemented Control Flow Analysis. + + * codegen.cs (EmitContext.DoFlowAnalysis): New public variable. + (EmitContext.CurrentBranching): Added. + (EmitContext.StartFlowBranching): Added. + (EmitContext.EndFlowBranching): Added. + (EmitContext.KillFlowBranching): Added. + (EmitContext.IsVariableAssigned): Added. + (EmitContext.SetVariableAssigned): Added. + (EmitContext.IsParameterAssigned): Added. + (EmitContext.SetParameterAssigned): Added. + (EmitContext.EmitTopBlock): Added `InternalParameters ip' argument. + Added control flow analysis stuff here. + + * expression.cs (Unary.DoResolve): If the operator is Oper.AddressOf, + resolve the expression as lvalue. + (LocalVariableReference.DoResolve): Check whether the variable has + already been assigned. + (ParameterReference.DoResolveLValue): Override lvalue resolve to mark + the parameter as assigned here. + (ParameterReference.DoResolve): Check whether the parameter has already + been assigned. + (Argument.Resolve): If it's a `ref' or `out' argument, resolve the + expression as lvalue. + + * statement.cs (FlowBranching): New class for the flow analysis code. + (Goto): Resolve the label in Resolve, not in Emit; added flow analysis. + (LabeledStatement.IsDefined): New public property. + (LabeledStatement.AddUsageVector): New public method to tell flow + analyis that the label may be reached via a forward jump. + (GotoCase): Lookup and resolve the label in Resolve, not in Emit; added + flow analysis. + (VariableInfo.Number): New public field. This is used by flow analysis + to number all locals of a block. + (Block.CountVariables): New public property. This is the number of + local variables in this block (including the locals from all parent + blocks). + (Block.EmitMeta): Number all the variables. + + * statement.cs: Added flow analysis support to all classes. + +2002-07-31 Martin Baulig + + * driver.cs: Added "--mcs-debug" argument if MCS_DEBUG is defined. + To get debugging messages, compile mcs with /define:MCS_DEBUG and + then use this argument. + + * report.cs (Report.Debug): Renamed to conditional to "MCS_DEBUG". + + * makefile.gnu (MCS_FLAGS): Include $(MCS_DEFINES), the user may + use this to specify /define options. + +2002-07-29 Martin Baulig + + * statement.cs (Fixed): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + + * statement.cs (For): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + + * statement.cs (Using): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + +2002-07-29 Martin Baulig + + * attribute.cs (Attribute.Resolve): Explicitly catch a + System.NullReferenceException when creating the + CustromAttributeBuilder and report a different warning message. + +2002-07-29 Martin Baulig + + * support.cs (ParameterData.ParameterName): Added method to + get the name of a parameter. + + * typemanager.cs (TypeManager.IsValueType): New public method. + +2002-07-29 Martin Baulig + + * parameter.cs (Parameter.Modifier): Added `ISBYREF = 8'. This + is a flag which specifies that it's either ref or out. + (Parameter.GetParameterInfo (DeclSpace, int, out bool)): Changed + the out parameter to `out Parameter.Modifier mod', also set the + Parameter.Modifier.ISBYREF flag on it if it's either ref or out. + + * support.cs (InternalParameters.ParameterModifier): Distinguish + between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the + Parameter.Modifier.ISBYREF flag if it's either ref or out. + + * expression.cs (Argument.GetParameterModifier): Distinguish + between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the + Parameter.Modifier.ISBYREF flag if it's either ref or out. + +2002-07-29 Martin Baulig + + * expression.cs (ParameterReference.ParameterReference): Added + `Location loc' argument to the constructor. + + * cs-parser.jay: Pass location to ParameterReference. + +2002-07-28 Miguel de Icaza + + * statement.cs (Try): Initialize the location. + + * cs-parser.jay: pass location to Try. + + * expression.cs (Unary.Reduce): Change the prototype to return + whether a constant fold could be performed or not. The result is + returned in an out parameters. In the case of Indirection and + AddressOf, we want to perform the full tests. + +2002-07-26 Miguel de Icaza + + * statement.cs (Statement.Emit): Flag dead code. + +2002-07-27 Andrew Birkett + + * expression.cs (Unary.Reduce): Handle AddressOf and Indirection. + +2002-07-27 Martin Baulig + + * class.cs (MethodData.Define): Put back call to + TypeManager.AddMethod(), accidentally commented this out. + + * report.cs (Debug): New public method to print debugging information, + this is `[Conditional ("DEBUG")]'. + +2002-07-26 Martin Baulig + + * cs-parser.jay (CSharpParser): Added `Stack switch_stack'. + (switch_statement): Push the current_block to the switch_stack and + pop it again when we're done with the switch. + (switch_section): The new block is a child of the current_block. + Fixes bug #24007, added test-152.cs. + +2002-07-27 Martin Baulig + + * expression.cs (Invocation.EmitArguments): When calling a varargs + function with only its fixed arguments, we need to pass an empty + array. + +2002-07-27 Martin Baulig + + Mono 0.13 has been released. + +2002-07-25 Miguel de Icaza + + * driver.cs: Rename --resource to --linkres, because that is what + we do currently, we dont support --resource yet. + + * cs-tokenizer.cs: Fix test for reporting endif mismatches. + +2002-07-25 Martin Baulig + + * class.cs (MethodData): New public class. This is a `method builder' + class for a method or one accessor of a Property/Indexer/Event. + (MethodData.GetMethodFlags): Moved here from MemberBase. + (MethodData.ApplyAttributes): Likewise. + (MethodData.ApplyObsoleteAttribute): Likewise. + (MethodData.ApplyConditionalAttribute): Likewise. + (MethodData.ApplyDllImportAttribute): Likewise. + (MethodData.CheckAbstractAndExternal): Likewise. + (MethodData.Define): Formerly knows as MemberBase.DefineMethod(). + (MethodData.Emit): Formerly known as Method.Emit(). + (MemberBase): Moved everything which was specific to a single + accessor/method to MethodData. + (Method): Create a new MethodData and call Define() and Emit() on it. + (Property, Indexer, Event): Create a new MethodData objects for each + accessor and call Define() and Emit() on them. + +2002-07-25 Martin Baulig + + Made MethodCore derive from MemberBase to reuse the code from there. + MemberBase now also checks for attributes. + + * class.cs (MethodCore): Derive from MemberBase, not MemberCore. + (MemberBase.GetMethodFlags): Moved here from class Method and marked + as virtual. + (MemberBase.DefineAccessor): Renamed to DefineMethod(), added + `CallingConventions cc' and `Attributes opt_attrs' arguments. + (MemberBase.ApplyAttributes): New virtual method; applies the + attributes to a method or accessor. + (MemberBase.ApplyObsoleteAttribute): New protected virtual method. + (MemberBase.ApplyConditionalAttribute): Likewise. + (MemberBase.ApplyDllImportAttribute): Likewise. + (MemberBase.CheckAbstractAndExternal): Likewise. + (MethodCore.ParameterTypes): This is now a property instead of a + method, it's initialized from DoDefineParameters(). + (MethodCore.ParameterInfo): Removed the set accessor. + (MethodCore.DoDefineParameters): New protected virtual method to + initialize ParameterTypes and ParameterInfo. + (Method.GetReturnType): We can now simply return the MemberType. + (Method.GetMethodFlags): Override the MemberBase version and add + the conditional flags. + (Method.CheckBase): Moved some code from Define() here, call + DoDefineParameters() here. + (Method.Define): Use DoDefine() and DefineMethod() from MemberBase + here to avoid some larger code duplication. + (Property.Emit, Indexer.Emit): Call CheckAbstractAndExternal() to + ensure that abstract and external accessors don't declare a body. + + * attribute.cs (Attribute.GetValidPieces): Make this actually work: + `System.Attribute.GetCustomAttributes (attr.Type)' does a recursive + lookup in the attribute's parent classes, so we need to abort as soon + as we found the first match. + (Attribute.Obsolete_GetObsoleteMessage): Return the empty string if + the attribute has no arguments. + + * typemanager.cs (TypeManager.AddMethod): Now takes a MemberBase instead + of a Method. + +2002-07-24 Gonzalo Paniagua Javier + + * cs-parser.jay: reverted previous patch. + +2002-07-24 Gonzalo Paniagua Javier + + * cs-parser.jay: fixed bug #22119. + +2002-07-24 Gonzalo Paniagua Javier + + * attribute.cs: fixed compilation. The error was: + "attribute.cs(571,17): error CS0177: The out parameter 'is_error' must + be assigned to before control leaves the current method." + [FIXME: Filed as bug #28186: MCS must report this error.] + +2002-07-25 Martin Baulig + + * attribute.cs (Attribute.Conditional_GetConditionName): New static + method to pull the condition name ouf of a Conditional attribute. + (Attribute.Obsolete_GetObsoleteMessage): New static method to pull + the obsolete message and error flag out of an Obsolete attribute. + + * class.cs (Method.GetMethodFlags): New public method to get the + TypeManager.MethodFlags for this method. + (Method.ApplyConditionalAttribute, Method.ApplyObsoleteAttribute): New + private methods. + (Method.Define): Get and apply the Obsolete and Conditional attributes; + if we're overriding a virtual function, set the new private variable + `parent_method'; call the new TypeManager.AddMethod(). + + * typemanager.cs (TypeManager.AddMethod): New static method. Stores + the MethodBuilder and the Method in a PtrHashtable. + (TypeManager.builder_to_method): Added for this purpose. + (TypeManager.MethodFlags): Added IsObsoleteError. + (TypeManager.GetMethodFlags): Added `Location loc' argument. Lookup + Obsolete and Conditional arguments in MethodBuilders. If we discover + an Obsolete attribute, emit an appropriate warning 618 / error 619 with + the message from the attribute. + +2002-07-24 Martin Baulig + + * cs-tokenizer.cs: Eat up trailing whitespaces and one-line comments in + preprocessor directives, ensure that the argument to #define/#undef is + exactly one identifier and that it's actually an identifier. + + Some weeks ago I did a `#define DEBUG 1' myself and wondered why this + did not work .... + +2002-07-24 Martin Baulig + + * statement.cs (Foreach.ForeachHelperMethods): Added `Type element_type', + initialize it to TypeManager.object_type in the constructor. + (Foreach.GetEnumeratorFilter): Set `hm.element_type' to the return type + of the `hm.get_current' method if we're using the collection pattern. + (Foreach.EmitCollectionForeach): Use `hm.element_type' as the source type + for the explicit conversion to make it work when we're using the collection + pattern and the `Current' property has a different return type than `object'. + Fixes #27713. + +2002-07-24 Martin Baulig + + * delegate.cs (Delegate.VerifyMethod): Simply return null if the method + does not match, but don't report any errors. This method is called in + order for all methods in a MethodGroupExpr until a matching method is + found, so we don't want to bail out if the first method doesn't match. + (NewDelegate.DoResolve): If none of the methods in the MethodGroupExpr + matches, report the 123. Fixes #28070. + +2002-07-24 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): Moved the + TypeManager.TypeToCoreType() to the top of the method so the + following equality checks will work. Fixes #28107. + +2002-07-24 Martin Baulig + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): "If either + operand is of type uint, and the other operand is of type sbyte, + short or int, the operands are converted to type long." - + Actually do what this comment already told us. Fixes bug #28106, + added test-150.cs. + +2002-07-24 Martin Baulig + + * class.cs (MethodBase): New abstract class. This is now a base + class for Property, Indexer and Event to avoid some code duplication + in their Define() and DefineMethods() methods. + (MethodBase.DoDefine, MethodBase.DefineAccessor): Provide virtual + generic methods for Define() and DefineMethods(). + (FieldBase): Derive from MemberBase, not MemberCore. + (Property): Derive from MemberBase, not MemberCore. + (Property.DefineMethod): Moved all the code from this method to the + new MethodBase.DefineAccessor(), just call it with appropriate + argumetnts. + (Property.Define): Call the new Property.DoDefine(), this does some + sanity checks and we don't need to duplicate the code everywhere. + (Event): Derive from MemberBase, not MemberCore. + (Event.Define): Use the new MethodBase.DefineAccessor() to define the + accessors, this will also make them work with interface events. + (Indexer): Derive from MemberBase, not MemberCore. + (Indexer.DefineMethod): Removed, call MethodBase.DefineAccessor() insstead. + (Indexer.Define): Use the new MethodBase functions. + + * interface.cs (InterfaceEvent.InterfaceEvent): Added `Location loc' + argument to the constructor. + (Interface.FindMembers): Added support for interface events. + (Interface.PopluateEvent): Implemented. + + Added test-149.cs for this. This also fixes bugs #26067 and #24256. + +2002-07-22 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod): Adding methods do not use IsValid, + but this is required to check for a method name being the same as + the containing class. + + Handle this now. + +2002-07-22 Gonzalo Paniagua Javier + + * interface.cs: initialize variable. + +2002-07-23 Martin Baulig + + Implemented the IndexerName attribute in interfaces. + + * class.cs (TypeContainer.DefineIndexers): Don't set the indexer + name if this is an explicit interface implementation. + (Indexer.InterfaceIndexerName): New public variable. If we're + implementing an interface indexer, this is the IndexerName in that + interface. Otherwise, it's the IndexerName. + (Indexer.DefineMethod): If we're implementing interface indexer, + set InterfaceIndexerName. Use the new Pending.IsInterfaceIndexer + and Pending.ImplementIndexer methods. + (Indexer.Define): Also define the PropertyBuilder if we're + implementing an interface indexer and this is neither an explicit + interface implementation nor do the IndexerName match the one in + the interface. + + * pending.cs (TypeAndMethods): Added `MethodInfo [] need_proxy'. + If a method is defined here, then we always need to create a proxy + for it. This is used when implementing interface indexers. + (Pending.IsInterfaceIndexer): New public method. + (Pending.ImplementIndexer): New public method. + (Pending.InterfaceMethod): Added `MethodInfo need_proxy' argument. + This is used when implementing interface indexers to define a proxy + if necessary. + (Pending.VerifyPendingMethods): Look in the `need_proxy' array and + define a proxy if necessary. + + * interface.cs (Interface.IndexerName): New public variable. + (Interface.PopulateIndexer): Set the IndexerName. + (Interface.DefineIndexers): New private method. Populate all the + indexers and make sure their IndexerNames match. + + * typemanager.cs (IndexerPropertyName): Added support for interface + indexers. + +2002-07-22 Martin Baulig + + * codegen.cs (EmitContext.HasReturnLabel): New public variable. + (EmitContext.EmitTopBlock): Always mark the ReturnLabel and emit a + ret if HasReturnLabel. + (EmitContext.TryCatchLevel, LoopBeginTryCatchLevel): New public + variables. + + * statement.cs (Do.Emit, While.Emit, For.Emit, Foreach.Emit): Save + and set the ec.LoopBeginTryCatchLevel. + (Try.Emit): Increment the ec.TryCatchLevel while emitting the block. + (Continue.Emit): If the ec.LoopBeginTryCatchLevel is smaller than + the current ec.TryCatchLevel, the branch goes out of an exception + block. In this case, we need to use Leave and not Br. + +2002-07-22 Martin Baulig + + * statement.cs (Try.Emit): Emit an explicit ret after the end of the + block unless the block does not always return or it is contained in + another try { ... } catch { ... } block. Fixes bug #26506. + Added verify-1.cs to the test suite. + +2002-07-22 Martin Baulig + + * statement.cs (Switch.TableSwitchEmit): If we don't have a default, + then we do not always return. Fixes bug #24985. + +2002-07-22 Martin Baulig + + * expression.cs (Invocation.OverloadedResolve): Do the BetterFunction() + lookup on a per-class level; ie. walk up the class hierarchy until we + found at least one applicable method, then choose the best among them. + Fixes bug #24463 and test-29.cs. + +2002-07-22 Martin Baulig + + * typemanager.cs (TypeManager.ArrayContainsMethod): Don't check the + return types of the methods. The return type is not part of the + signature and we must not check it to make the `new' modifier work. + Fixes bug #27999, also added test-147.cs. + (TypeManager.TypeToCoreType): Added TypeManager.type_type. + + * expression.cs (Invocation.DoResolve): Call TypeManager.TypeToCoreType() + on the method's return type. + +2002-07-21 Martin Baulig + + * assign.cs: Make this work if the rightmost source is a constant and + we need to do an implicit type conversion. Also adding a few more tests + to test-38.cs which should have caught this. + + * makefile.gnu: Disable debugging, there's already the mcs-mono2.exe + target in the makefile for this. The makefile.gnu is primarily intended + for end-users who don't want to debug the compiler. + +2002-07-21 Martin Baulig + + * assign.cs: Improved the Assign class so it can now handle embedded + assignments (X = Y = Z = something). As a side-effect this'll now also + consume less local variables. test-38.cs now passes with MCS, added + a few new test cases to that test. + +2002-07-20 Martin Baulig + + * expression.cs (Binary.EmitBranchable): Emit correct unsigned branch + instructions. Fixes bug #27977, also added test-146.cs. + +2002-07-19 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: fixed getHex (). + +2002-07-19 Martin Baulig + + * expression.cs (Invocation.EmitParams): Use TypeManager.LookupType(), + not Type.GetType() to lookup the array type. This is needed when + we're constructing an array of a user-defined type. + (ArrayAccess.EmitDynamicInitializers): Only emit the Ldelema for + single-dimensional arrays, but also for single-dimensial arrays of + type decimal. + +2002-07-19 Martin Baulig + + * expression.cs (New.DoEmit): Create a new LocalTemporary each time + this function is called, it's not allowed to share LocalBuilders + among ILGenerators. + +2002-07-19 Martin Baulig + + * expression.cs (Argument.Resolve): Report an error 118 when trying + to pass a type as argument. + +2002-07-18 Martin Baulig + + * ecore.cs (Expression.ImplicitNumericConversion): Don't emit a + Conv_R_Un for the signed `long' type. + +2002-07-15 Miguel de Icaza + + * expression.cs (MemberAccess.DoResolve): Do not reuse the field + `expr' for the temporary result, as that will fail if we do + multiple resolves on the same expression. + +2002-07-05 Miguel de Icaza + + * ecore.cs (SimpleNameResolve): Use ec.DeclSpace instead of + ec.TypeContainer for looking up aliases. + + * class.cs (TypeContainer): Remove LookupAlias from here. + + * decl.cs (DeclSpace); Move here. + +2002-07-01 Miguel de Icaza + + * class.cs (FindMembers): Only call filter if the constructor + bulider is not null. + + Also handle delegates in `NestedTypes' now. Now we will perform + type lookups using the standard resolution process. This also + fixes a bug. + + * decl.cs (DeclSpace.ResolveType): New type resolution routine. + This uses Expressions (the limited kind that can be parsed by the + tree) instead of strings. + + * expression.cs (ComposedCast.ToString): Implement, used to flag + errors since now we have to render expressions. + + (ArrayCreation): Kill FormElementType. Use ComposedCasts in + FormArrayType. + + * ecore.cs (SimpleName.ToString): ditto. + + * cs-parser.jay: Instead of using strings to assemble types, use + Expressions to assemble the type (using SimpleName, ComposedCast, + MemberAccess). This should fix the type lookups in declarations, + because we were using a different code path for this. + + * statement.cs (Block.Resolve): Continue processing statements + even when there is an error. + +2002-07-17 Miguel de Icaza + + * class.cs (Event.Define): Also remove the `remove' method from + the list of pending items. + + * expression.cs (ParameterReference): Use ldarg.N (0..3) to + generate more compact code. + +2002-07-17 Martin Baulig + + * const.cs (Const.LookupConstantValue): Add support for constant + `unchecked' and `checked' expressions. + Also adding test case test-140.cs for this. + +2002-07-17 Martin Baulig + + * statement.cs (Foreach.GetEnumeratorFilter): When compiling corlib, + check whether mi.ReturnType implements the IEnumerator interface; the + `==' and the IsAssignableFrom() will fail in this situation. + +2002-07-16 Ravi Pratap + + * ecore.cs (SimpleName.SimpleNameResolve) : Apply Gonzalo's fix + here too. + +2002-07-16 Gonzalo Paniagua Javier + + * expression.cs: fixed bug #27811. + +2002-07-14 Miguel de Icaza + + * expression.cs (ParameterReference.AddressOf): Patch from Paolo + Molaro: when we are a ref, the value already contains a pointer + value, do not take the address of it. + +2002-07-14 Rafael Teixeira + * removed mb-parser.jay and mb-tokenizer.cs + +Sat Jul 13 19:38:03 CEST 2002 Paolo Molaro + + * expression.cs: check against the building corlib void type. + +Sat Jul 13 19:35:58 CEST 2002 Paolo Molaro + + * ecore.cs: fix for valuetype static readonly fields: when + initializing them, we need their address, not the address of a copy. + +Sat Jul 13 17:32:53 CEST 2002 Paolo Molaro + + * typemanager.cs: register also enum_type in corlib. + +Sat Jul 13 15:59:47 CEST 2002 Paolo Molaro + + * class.cs: allow calling this (but not base) initializers in structs. + +Sat Jul 13 15:12:06 CEST 2002 Paolo Molaro + + * ecore.cs: make sure we compare against the building base types + in GetTypeSize (). + +Sat Jul 13 15:10:32 CEST 2002 Paolo Molaro + + * typemanager.cs: fix TypeToCoreType() to handle void and object + (corlib gets no more typerefs after this change). + +2002-07-12 Miguel de Icaza + + * expression.cs (ArrayCreation.EmitArrayArguments): use + Conv.Ovf.U4 for unsigned and Conv.Ovf.I4 for signed. + + (ArrayAccess.LoadArrayAndArguments): Use Conv_Ovf_I and + Conv_Ovf_I_Un for the array arguments. Even if C# allows longs as + array indexes, the runtime actually forbids them. + + * ecore.cs (ExpressionToArrayArgument): Move the conversion code + for array arguments here. + + * expression.cs (EmitLoadOpcode): System.Char is a U2, use that + instead of the default for ValueTypes. + + (New.DoEmit): Use IsValueType instead of + IsSubclassOf (value_type) + (New.DoResolve): ditto. + (Invocation.EmitCall): ditto. + + * assign.cs (Assign): ditto. + + * statement.cs (Unsafe): Ok, so I got the semantics wrong. + Statements *are* currently doing part of their resolution during + Emit. + + Expressions do always resolve during resolve, but statements are + only required to propagate resolution to their children. + +2002-07-11 Miguel de Icaza + + * driver.cs (CSCParseOption): Finish the /r: and /lib: support. + + (LoadAssembly): Do not add the dll if it is already specified + + (MainDriver): Add the System directory to the link path at the end, + after all the other -L arguments. + + * expression.cs (ArrayAccess.EmitLoadOpcode): I was using the + wrong opcode for loading bytes and bools (ldelem.i1 instead of + ldelem.u1) and using the opposite for sbytes. + + This fixes Digger, and we can finally run it. + + * driver.cs (UnixParseOption): Move the option parsing here. + (CSCParseOption): Implement CSC-like parsing of options. + + We now support both modes of operation, the old Unix way, and the + new CSC-like way. This should help those who wanted to make cross + platform makefiles. + + The only thing broken is that /r:, /reference: and /lib: are not + implemented, because I want to make those have the same semantics + as the CSC compiler has, and kill once and for all the confussion + around this. Will be doing this tomorrow. + + * statement.cs (Unsafe.Resolve): The state is checked during + resolve, not emit, so we have to set the flags for IsUnsfe here. + +2002-07-10 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): Since we can + not catch the Error_ObjectRefRequired in SimpleName (as it is + possible to have a class/instance variable name that later gets + deambiguated), we have to check this here. + +2002-07-10 Ravi Pratap + + * class.cs (TypeContainer.GetFieldFromEvent): Move away from here, + make static and put into Expression. + + (Event.Define): Register the private field of the event with the + TypeManager so that GetFieldFromEvent can get at it. + + (TypeManager.RegisterPrivateFieldOfEvent): Implement to + keep track of the private field associated with an event which + has no accessors. + + (TypeManager.GetPrivateFieldOfEvent): Implement to get at the + private field. + + * ecore.cs (GetFieldFromEvent): RE-write to use the above methods. + +2002-07-10 Miguel de Icaza + + * expression.cs (Binary.EmitBranchable): this routine emits the + Binary expression in a branchable context. This basically means: + we need to branch somewhere, not just get the value on the stack. + + This works together with Statement.EmitBoolExpression. + + * statement.cs (Statement.EmitBoolExpression): Use + EmitBranchable. + +2002-07-09 Miguel de Icaza + + * statement.cs (For): Reduce the number of jumps in loops. + + (For): Implement loop inversion for the For statement. + + (Break): We can be breaking out of a Try/Catch controlled section + (foreach might have an implicit try/catch clause), so we need to + use Leave instead of Br. + + * ecore.cs (FieldExpr.AddressOf): Fix for test-139 (augmented + now). If the instace expression supports IMemoryLocation, we use + the AddressOf method from the IMemoryLocation to extract the + address instead of emitting the instance. + + This showed up with `This', as we were emitting the instance + always (Emit) instead of the Address of This. Particularly + interesting when This is a value type, as we dont want the Emit + effect (which was to load the object). + +2002-07-08 Miguel de Icaza + + * attribute.cs: Pass the entry point to the DefinePInvokeMethod + + * statement.cs (Checked): Set the CheckedState during the resolve + process too, as the ConvCast operations track the checked state on + the resolve process, and not emit. + + * cs-parser.jay (namespace_member_declaration): Flag that we have + found a declaration when we do. This is used to flag error 1529 + + * driver.cs: Report ok when we display the help only. + +2002-07-06 Andrew Birkett + + * cs-tokenizer.cs (xtoken): Improve handling of string literals. + +2002-07-04 Miguel de Icaza + + * cs-tokenizer.cs (define): We also have to track locally the + defines. AllDefines is just used for the Conditional Attribute, + but we also need the local defines for the current source code. + +2002-07-03 Miguel de Icaza + + * statement.cs (While, For, Do): These loops can exit through a + Break statement, use this information to tell whether the + statement is the last piece of code. + + (Break): Flag that we break. + + * codegen.cs (EmitContexts): New `Breaks' state variable. + +2002-07-03 Martin Baulig + + * class.cs (TypeContainer.MethodModifiersValid): Allow override + modifiers in method declarations in structs. Otherwise, you won't + be able to override things like Object.Equals(). + +2002-07-02 Miguel de Icaza + + * class.cs (Method, Property, Indexer): Do not allow the public + modifier to be used in explicit interface implementations. + + (TypeContainer.MethodModifiersValid): Catch virtual, abstract and + override modifiers in method declarations in structs + +2002-07-02 Andrew Birkett + + * cs-tokenizer.cs (adjust_int, adjust_real): Do not abort on + integer or real overflow, report an error + +2002-07-02 Martin Baulig + + * typemanager.cs (TypeManager.InitCoreTypes): When compiling + corlib, dynamically call AssemblyBuilder.SetCorlibTypeBuilders() + to tell the runtime about our newly created System.Object and + System.ValueType types. + +2002-07-02 Miguel de Icaza + + * expression.cs (This): Use Stobj/Ldobj when we are a member of a + struct instead of Ldarg/Starg. + +2002-07-02 Martin Baulig + + * expression.cs (Indirection.Indirection): Call + TypeManager.TypeToCoreType() on `expr.Type.GetElementType ()'. + +2002-07-02 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): If the type is a + ValueType, call TypeManager.TypeToCoreType() on it. + (Invocations.EmitParams): Call TypeManager.TypeToCoreType() on + the OpCodes.Newarr argument. + +2002-07-02 Martin Baulig + + * expression.cs (Invocation.EmitCall): When compiling corlib, + replace all calls to the system's System.Array type to calls to + the newly created one. + + * typemanager.cs (TypeManager.InitCodeHelpers): Added a few more + System.Array methods. + (TypeManager.InitCoreTypes): When compiling corlib, get the methods + from the system's System.Array type which must be replaced. + +Tue Jul 2 19:05:05 CEST 2002 Paolo Molaro + + * typemanager.cs: load unverifiable_code_ctor so we can build + corlib using the correct type. Avoid using GetTypeCode() with + TypeBuilders. + * rootcontext.cs: uses TypeManager.unverifiable_code_ctor and + TypeManager.object_type to allow building corlib. + +Tue Jul 2 19:03:19 CEST 2002 Paolo Molaro + + * ecore.cs: handle System.Enum separately in LoadFromPtr(). + +2002-07-01 Martin Baulig + + * class.cs: Make the last change actually work, we need to check + whether `ifaces != null' to avoid a crash. + +Mon Jul 1 16:15:03 CEST 2002 Paolo Molaro + + * class.cs: when we build structs without fields that implement + interfaces, we need to add the interfaces separately, since there is + no API to both set the size and add the interfaces at type creation + time. + +Mon Jul 1 14:50:47 CEST 2002 Paolo Molaro + + * expression.cs: the dimension arguments to the array constructors + need to be converted if they are a long. + +Mon Jul 1 12:26:12 CEST 2002 Paolo Molaro + + * class.cs: don't emit ldarg.0 if there is no parent constructor + (fixes showstopper for corlib). + +2002-06-29 Martin Baulig + + MCS now compiles corlib on GNU/Linux :-) + + * attribute.cs (Attribute.ApplyAttributes): Treat Accessors like Method, + ie. check for MethodImplOptions.InternalCall. + + * class.cs (TypeContainer.DefineType): When compiling corlib, both parent + and TypeManager.attribute_type are null, so we must explicitly check + whether parent is not null to find out whether it's an attribute type. + (Property.Emit): Always call Attribute.ApplyAttributes() on the GetBuilder + and SetBuilder, not only if the property is neither abstract nor external. + This is necessary to set the MethodImplOptions on the accessor methods. + (Indexer.Emit): Call Attribute.ApplyAttributes() on the GetBuilder and + SetBuilder, see Property.Emit(). + + * rootcontext.cs (RootContext.PopulateTypes): When compiling corlib, don't + populate "System.Object", "System.ValueType" and "System.Attribute" since + they've already been populated from BootCorlib_PopulateCoreTypes(). + +2002-06-29 Martin Baulig + + * ecore.cs (Expression.ImplicitReferenceConversionExists): If expr + is the NullLiteral, we also need to make sure that target_type is not + an enum type. + +2002-06-29 Martin Baulig + + * rootcontext.cs (RootContext.ResolveCore): We must initialize + `TypeManager.multicast_delegate_type' and `TypeManager.delegate_type' + before calling BootstrapCorlib_ResolveDelegate (). + +2002-06-27 Gonzalo Paniagua Javier + + * statement.cs: fixed build-breaker. All tests passed ok. + +2002-06-27 Martin Baulig + + * typemanager.cs (TypeManager.VerifyUnManaged): Added explicit check + for System.Decimal when compiling corlib. + +2002-06-27 Martin Baulig + + * statement.cs (Switch.TableSwitchEmit): Make this work with empty + switch blocks which contain nothing but a default clause. + +2002-06-26 Andrew + + * ../errors/cs1501-3.cs: Added new test for struct ctr typechecks. + +2002-06-27 Martin Baulig + + * ecore.cs (PropertyExpr.PropertyExpr): Call + TypeManager.TypeToCoreType() on the `pi.PropertyType'. + + * typemanager.cs (TypeManager.TypeToCoreType): Return if the type + is already a TypeBuilder. + +2002-06-27 Martin Baulig + + * ecore.cs (Expression.ImplicitReferenceConversionExists): Use + `target_type == TypeManager.array_type', not IsAssignableFrom() in + the "from an array-type to System.Array" case. This makes it work + when compiling corlib. + +2002-06-27 Martin Baulig + + * ecore.cs (Expression.SimpleNameResolve): If the expression is a + non-static PropertyExpr, set its InstanceExpression. This makes + the `ICollection.Count' property work in System/Array.cs. + +2002-06-25 Andrew Birkett + + * driver.cs: Made error handling more consistent. Errors now + tracked by Report class, so many methods which used to return int + now return void. Main() now prints success/failure and + errors/warnings message. + + Renamed '--probe' compiler argument to '--expect-error'. Removed + the magic number return values (123 and 124). Now, if the + expected error occurs, the compiler exits with success (exit value + 0). If the compilation completes without seeing that particular + error, the compiler exits with failure (exit value 1). The + makefile in mcs/errors has been changed to handle the new behaviour. + + * report.cs: Made 'expected error' number a property and renamed + it from 'Probe' to 'ExpectedError'. + + * genericparser.cs: Removed error handling support, since it is + now all done by Report class. + + * cs-parser.jay, mb-parser.jay: Errors are tracked by Report + class, so parse() no longer returns an int. + + * namespace.cs: Use Report.Error instead of GenericParser.error + +2002-06-22 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod, TypeContainer.AddIndexer, + TypeContainer.AddOperator): At the front of the list put the + explicit implementations, so they get resolved/defined first. + +2002-06-21 Miguel de Icaza + + * class.cs (TypeContainer.VerifyImplements): Verifies that a given + interface type is implemented by this TypeContainer. Used during + explicit interface implementation. + + (Property.Define, Indexer.Define, Method.Define): Validate that + the given interface in the explicit implementation is one of the + base classes for the containing type. + + Also if we are explicitly implementing an interface, but there is + no match in the pending implementation table, report an error. + + (Property.Define): Only define the property if we are + not explicitly implementing a property from an interface. Use the + correct name also for those properties (the same CSC uses, + although that is really not needed). + + (Property.Emit): Do not emit attributes for explicitly implemented + properties, as there is no TypeBuilder. + + (Indexer.Emit): ditto. + + Hiding then means that we do not really *implement* a pending + implementation, which makes code fail. + +2002-06-22 Martin Baulig + + * ecore.cs (Expression.Constantify): Call TypeManager.TypeToCoreType() on + the return value of Object.GetType(). [FIXME: we need to do this whenever + we get a type back from the reflection library]. + +Fri Jun 21 13:37:57 CEST 2002 Paolo Molaro + + * typemanager.cs: make ExpandInterfaces() slip duplicated interfaces. + +2002-06-20 Miguel de Icaza + + * attribute.cs: Return null if we can not look up the type. + + * class.cs (TypeContainer.GetClassBases): Use ExpandInterfaces on + the interface types found. + + * interface.cs (Interface.GetInterfaceBases): Use ExpandInterfaces on the + interface types found. + + * typemanager.cs (GetInterfaces): Make this routine returns alll + the interfaces and work around the lame differences between + System.Type and System.Reflection.Emit.TypeBuilder in the results + result for GetInterfaces. + + (ExpandInterfaces): Given an array of interface types, expand and + eliminate repeated ocurrences of an interface. This expands in + context like: IA; IB : IA; IC : IA, IB; the interface "IC" to + be IA, IB, IC. + +2002-06-21 Martin Baulig + + * typemanager.cs (TypeManager.EnumToUnderlying): It's now safe to call this function + on System.Enum. + +2002-06-21 Martin Baulig + + * typemanager.cs (TypeManager.TypeToCoreType): New function. When compiling corlib + and called with one of the core types, return the corresponding typebuilder for + that type. + + * expression.cs (ArrayAccess.DoResolve): Call TypeManager.TypeToCoreType() on the + element type. + +2002-06-21 Martin Baulig + + * ecore.cs (Expression.ExplicitReferenceConversionExists): Use + `target_type.IsArray' instead of `target_type.IsSubclassOf (TypeManager.array_type)'. + (Expression.ConvertReferenceExplicit): Likewise. + + * expression.cs (ElementAccess.DoResolve): Likewise. + (ElementAccess.DoResolveLValue): Likewise. + +2002-06-10 Martin Baulig + + * interface.cs (Interface.PopulateIndexer): When creating the setter, we need to + add the "value" parameter to the parameter list. + + * statement.cs (Fixed.Emit): Pass the return value of the child block's Emit() + to our caller. + +2002-06-19 Miguel de Icaza + + * expression.cs (ArrayCreation.ExpressionToArrayArgument): Convert + the argument to an int, uint, long or ulong, per the spec. Also + catch negative constants in array creation. + +Thu Jun 20 17:56:48 CEST 2002 Paolo Molaro + + * class.cs: do not allow the same interface to appear twice in + the definition list. + +Wed Jun 19 22:33:37 CEST 2002 Paolo Molaro + + * ecore.cs: don't use ldlen with System.Array. + +Wed Jun 19 20:57:40 CEST 2002 Paolo Molaro + + * ecore.cs: stobj requires a type argument. Handle indirect stores on enums. + +Wed Jun 19 20:17:59 CEST 2002 Paolo Molaro + + * modifiers.cs: produce correct field attributes for protected + internal. Easy fix so miguel can work on ther harder stuff:-) + +2002-06-18 Miguel de Icaza + + * pending.cs: New file. Move the code from class.cs here. + Support clearning the pending flag for all methods (when not doing + explicit interface implementation). + +Tue Jun 18 10:36:22 CEST 2002 Paolo Molaro + + * rootcontext.cs: added a couple more types needed to bootstrap. + +2002-06-17 Miguel de Icaza + + * typemanager.cs (GetConstructor): Use DeclaredOnly to look the + constructor in the type, instead of any constructor in the type + hierarchy. Thanks to Paolo for finding this bug (it showed up as + a bug in the Mono runtime when applying the params attribute). + +2002-06-16 Rafael Teixeira + * changed namespace.cs to use "GenericParser.error(...)" instead of "CSharpParser.error(...)" + +2002-06-14 Rachel Hestilow + + * expression.cs (Unary.ResolveOperator): Use TypeManager + to resolve the type. + +2002-06-13 Ravi Pratap + + * cs-parser.jay (enum_member_declaration): Pass in the attributes + attached. + + * enum.cs (AddEnumMember): Add support to store the attributes associated + with each member too. + + * attribute.cs (CheckAttribute, ApplyAttributes): Update to handle + field builders too - this takes care of the enum member case. + +2002-06-10 Rachel Hestilow + + * typemanager.cs (TypeManager.VerifyUnManaged): Allow + address-of operator on both value types and pointers. + +2002-06-10 Martin Baulig + + * interface.cs (Interface.PopulateIndexer): Add the indexer's + PropertyBuilder to the `property_builders' list. + + * expression.cs (Indexers.GetIndexersForTypeOrInterface): New private method. + (Indexers.GetIndexersForType): Call GetIndexersForTypeOrInterface() on the + `lookup_type' and all its interfaces. Unfortunately, Type.FindMembers() won't + find any indexers which are inherited from an interface. + +2002-06-09 Martin Baulig + + * const.cs (Const.LookupConstantValue): Convert `Expr' to a literal of + the same type as the constant if necessary. There's also a test-130.cs + for this. + + * enum.cs (Enum.ChangeEnumType): Moved to typemanager.cs and made public. + + * typemanager.cs (TypeManager.ChangeType): Previously known as + Enum.ChangeEnumType(). + +2002-06-09 Martin Baulig + + * expression.cs (Cast.TryReduce): Added support for consts. + +2002-06-08 Ravi Pratap + + * class.cs (Accessor): Hold attributes information so we can pass + it along. + + * cs-parser.jay (get_accessor_declaration, set_accessor_declaration): + Modify to pass in attributes attached to the methods. + + (add_accessor_declaration, remove_accessor_declaration): Ditto. + + * attribute.cs (ApplyAttributes, CheckAttribute): Update accordingly + to handle the Accessor kind :-) + + * class.cs (Property.Emit, Event.Emit): Apply attributes to the accessors + +2002-06-08 Martin Baulig + + * expression.cs (Unary.TryReduceNegative): Added support for + ULongConstants. + +2002-06-08 Martin Baulig + + * enum.cs (Enum.LookupEnumValue): Don't report an error if the + name can't be found in the `defined_names' - the caller will do a + MemberLookup in this case and thus find methods in System.Enum + such as Enum.IsDefined(). + +2002-06-08 Martin Baulig + + * enum.cs (Enum.ChangeEnumType): This is a custom version of + Convert.ChangeType() which works with TypeBuilder created types. + (Enum.LookupEnumValue, Enum.Define): Use it here. + + * class.cs (TypeContainer.RegisterRequiredImplementations): Added + `TypeBuilder.BaseType != null' check. + (TypeContainer.FindMembers): Only lookup parent members if we + actually have a parent. + (Method.EmitDestructor): Added `ec.ContainerType.BaseType != null' check. + (ConstructorInitializer.Resolve): Likewise. + + * interface.cs (Interface.FindMembers): Added + `TypeBuilder.BaseType != null' check. + + * rootcontext.cs (RootContext.ResolveCore): Added + "System.Runtime.CompilerServices.IndexerNameAttribute" to + classes_second_stage. + + * typemanager.cs (TypeManager.InitCoreTypes): Don't initialize + debug_type and trace_type when compiling with --nostdlib. + +2002-06-07 Martin Baulig + + * class.cs (TypeContainer): Added `have_nonstatic_fields' field. + (AddField): Set it to true when adding a non-static field. + (DefineType): Use `have_nonstatic_fields' to find out whether we + have non-static fields, not `Fields != null'. + +2002-06-02 Miguel de Icaza + + * ecore.cs (SimpleNameResolve): Removed simple bug (we were + dereferencing a null on the static-field code path) + +2002-05-30 Martin Baulig + + * codegen.cs (InitMonoSymbolWriter): Added `string[] args' argument + to take command line arguments. Use reflection to call the new + custom `Initialize' function on the symbol writer and pass it the + command line arguments. + + * driver.cs (--debug-args): New command line argument to pass command + line arguments to the symbol writer. + +2002-05-28 Miguel de Icaza + + * assign.cs (DoResolve): Forgot to do the implicit conversion to + the target type for indexers and properties. Thanks to Joe for + catching this. + +2002-05-27 Miguel de Icaza + + * typemanager.cs (MethodFlags): returns the method flags + (Obsolete/ShouldIgnore) that control warning emission and whether + the invocation should be made, or ignored. + + * expression.cs (Invocation.Emit): Remove previous hack, we should + not do this on matching a base type, we should do this based on an attribute + + Only emit calls to System.Diagnostics.Debug and + System.Diagnostics.Trace if the TRACE and DEBUG defines are passed + on the command line. + + * rootcontext.cs: Global settings for tracing and debugging. + + * cs-tokenizer.cs (define): New utility function to track + defines. Set the global settings for TRACE and DEBUG if found. + +2002-05-25 Ravi Pratap + + * interface.cs (Populate*): Pass in the TypeContainer as well as + the DeclSpace as parameters so that we can create EmitContexts and + then use that to apply attributes etc. + + (PopulateMethod, PopulateEvent, PopulateProperty) + (PopulateIndexer): Apply attributes everywhere. + + * attribute.cs (CheckAttribute): Include InterfaceMethod, InterfaceEvent + etc. + + (ApplyAttributes): Update accordingly. + + We now apply interface attributes for all members too. + +2002-05-26 Miguel de Icaza + + * class.cs (Indexer.Define); Correctly check if we are explicit + implementation (instead of checking the Name for a ".", we + directly look up if the InterfaceType was specified). + + Delay the creation of the PropertyBuilder. + + Only create the PropertyBuilder if we are not an explicit + interface implementation. This means that explicit interface + implementation members do not participate in regular function + lookups, and hence fixes another major ambiguity problem in + overload resolution (that was the visible effect). + + (DefineMethod): Return whether we are doing an interface + implementation. + + * typemanager.cs: Temporary hack until we get attributes in + interfaces (Ravi is working on that) and we get IndexerName + support in interfaces. + + * interface.cs: Register the indexers as properties. + + * attribute.cs (Attribute.Resolve): Catch the error, and emit a + warning, I have verified that this is a bug in the .NET runtime + (JavaScript suffers of the same problem). + + * typemanager.cs (MemberLookup): When looking up members for + interfaces, the parent of an interface is the implicit + System.Object (so we succeed in searches of Object methods in an + interface method invocation. Example: IEnumerable x; x.ToString + ()) + +2002-05-25 Miguel de Icaza + + * class.cs (Event): Events should also register if they do + implement the methods that an interface requires. + + * typemanager.cs (MemberLookup); use the new GetInterfaces + method. + + (GetInterfaces): The code used to lookup interfaces for a type is + used in more than one place, factor it here. + + * driver.cs: Track the errors at the bottom of the file, we kept + on going. + + * delegate.cs (NewDelegate.Emit): We have to emit a null as the + instance if the method we are calling is static! + +2002-05-24 Miguel de Icaza + + * attribute.cs (ApplyAttributes): Make this function filter out + the IndexerName attribute (as that attribute in reality is never + applied) and return the string constant for the IndexerName + attribute. + + * class.cs (TypeContainer.Emit): Validate that all the indexers + have the same IndexerName attribute, and if so, set the + DefaultName attribute on the class. + + * typemanager.cs: The return value might contain other stuff (not + only methods). For instance, consider a method with an "Item" + property and an Item method. + + * class.cs: If there is a problem with the parameter types, + return. + +2002-05-24 Ravi Pratap + + * ecore.cs (ImplicitConversionExists): Wrapper function which also + looks at user defined conversion after making a call to + StandardConversionExists - we need this for overload resolution. + + * expression.cs : Update accordingly the various method calls. + + This fixes 2 bugs filed against implicit user defined conversions + +2002-05-22 Miguel de Icaza + + * statement.cs: Track the result of the assignment. + +2002-05-21 Miguel de Icaza + + * expression.cs (MemberAccess): Improved error reporting for + inaccessible members. + +2002-05-22 Martin Baulig + + * makefile (mcs-mono2.exe): New target. This is mcs compiled with + itself with debugging support. + +2002-05-22 Martin Baulig + + * typemanager.cs ("System.Runtime.InteropServices.StructLayoutAttribute"): + Removed, this isn't needed anymore. + +2002-05-20 Martin Baulig + + * typemanager.cs (InitEnumUnderlyingTypes): "System.Char" can't + be underlying type for an enum. + +2002-05-20 Miguel de Icaza + + * typemanager.cs (InitEnumUnderlyingTypes): New helper function + that splits out the loading of just the core types. + + * rootcontext.cs (ResolveCore): Split the struct resolution in + two, so we can load the enumeration underlying types before any + enums are used. + + * expression.cs (Is): Bandaid until we fix properly Switch (see + bug #24985 for details). + + * typemanager.cs (ImplementsInterface): The hashtable will contain + a null if there are no interfaces implemented. + +2002-05-18 Miguel de Icaza + + * cs-parser.jay (indexer_declarator): It is fine to have array + parameters + +2002-05-17 Miguel de Icaza + + * typemanager.cs: (RegisterBuilder): New function used to register + TypeBuilders that implement interfaces. Since + TypeBuilder.GetInterfaces (as usual) does not work with lame + Reflection.Emit. + (AddUserType): register interfaces. + + (ImplementsInterface): Use the builder_to_ifaces hash if we are + dealing with TypeBuilder. Also, arrays are showing up as + SymbolTypes, which are not TypeBuilders, but whose GetInterfaces + methods can not be invoked on them! + + * ecore.cs (ExplicitReferenceConversionExists): Made public. + (ImplicitReferenceConversionExists): Split out from + StandardConversionExists. + + * expression.cs (As): We were only implementing one of the three + cases for the as operator. We now implement them all. + (Is): Implement the various other cases for Is as well. + + * typemanager.cs (CACHE): New define used to control if we want or + not the FindMembers cache. Seems to have a negative impact on + performance currently + + (MemberLookup): Nested types have full acess to + enclosing type members + + Remove code that coped with instance/static returns for events, we + now catch this in RealFindMembers. + + (RealFindMembers): only perform static lookup if the instance + lookup did not return a type or an event. + +2002-05-17 Miguel de Icaza + + * assign.cs (CompoundAssign): We pass more semantic information + now to Compound Assignments than we did before: now we have all + the information at hand, and now we resolve the target *before* we + do the expression expansion, which allows the "CacheValue" method + to have the effect we intended (before, a [x] += 1 would generate + two differen ArrayAccess expressions from the ElementAccess, + during the resolution process). + + (CompoundAssign.DoResolve): Resolve target and original_source here. + +2002-05-16 Miguel de Icaza + + * expression.cs (ArrayAccess): dropped debugging information. + + * typemanager.cs: Small bug fix: I was always returning i_members, + instead of one of i_members or s_members (depending on which had + the content). + + * assign.cs (IAssignMethod.CacheTemporaries): New method. This + method is invoked before any code generation takes place, and it + is a mechanism to inform that the expression will be invoked more + than once, and that the method should use temporary values to + avoid having side effects + + (Assign.Emit): Call CacheTemporaries in the IAssignMethod. + + * ecore.cs (Expression.CacheTemporaries): Provide empty default + implementation. + + * expression.cs (Indirection, ArrayAccess): Add support for + CacheTemporaries in these two bad boys. + + * ecore.cs (LoadFromPtr): figure out on our own if we need to use + ldobj or ldind_ref. + (StoreFromPtr): Handle stobj as well. + + * expression.cs (UnaryMutator): Share more code. + + * typemanager.cs (FindMembers): Thanks to Paolo for tracking this + down: I was not tracking the Filter function as well, which + was affecting the results of the cache. + +2002-05-15 Miguel de Icaza + + * attribute.cs: Remove the hack to handle the CharSet property on + StructLayouts. + +2002-05-14 Miguel de Icaza + + * attribute.cs (DoResolve): More uglyness, we now only try to + resolve the attribute partially, to extract the CharSet + information (only if we are a StructLayout attribute). Otherwise + + (GetExtraTypeInfo): Add some code to conditionally kill in the + future this. I am more and more convinced that the .NET + framework has special code to handle the attribute setting on + certain elements. + + * expression.cs (IsParamsMethodApplicable): Revert my previous + foreach change here, it was wrong. + +2002-05-13 Miguel de Icaza + + * cs-tokenizer.cs: (pp_primary): Eat the ')' at the end. + (pp_expr): do not abort on unknown input, just return. + (eval): abort if there are pending chars. + + * attribute.cs (Attribute.Resolve): Positional parameters are + optional. Deal with that case. + + * class.cs (DefineType): Call Attribute.GetExtraTypeInfo to fetch + the Ansi/Unicode/Auto information for the type. + + (TypeContainer.DefineType): instantiate the EmitContext here, as + we will be using it during the type definition (to resolve + attributes) and during the emit phase. + + * attribute.cs (Attribute.GetExtraTypeInfo): This routine is used + to pull type information out of the attributes + + (Attribute.Resolve): track the constructor builder, and allow for + multiple invocations (structs and classes will use this). + + * ecore.cs (MemberLookupFinal): new version with all the + parameters customizable. + + * expression.cs (New.DoResolve): Use MemberLookupFinal to locate + constructors. Return if the result value is null (as the error + would have been flagged already by MemberLookupFinal) + + Do not allow instances of abstract classes or interfaces to be + created. + + * class.cs: (MethodSignature.InheritableMemberSignatureCompare): + We have to compare the assembly property here when dealing with + FamANDAssem and Assembly access modifiers, because we might be + creating an assembly from *modules* (that means that we are not + getting TypeBuilders for types defined in other modules that are + part of this assembly). + + (Method.Emit): If the method is marked abstract and has a body, + emit an error. + + (TypeContainer.DefineMembers): If both the defined member and the + parent name match are methods, then do not emit any warnings: let + the Method.Define routine take care of flagging warnings. But if + there is a mismatch (method overrides something else, or method is + overriwritten by something, then emit warning). + + (MethodSignature.MemberSignatureCompare): If the sig.ret_type is + set to null, this means `do not check for the return type on the + signature'. + + (Method.Define): set the return type for the method signature to + null, so that we get methods with the same name and parameters and + different return types. This is used to flag warning 114 (you are + hiding a method, and you probably want to use the new/override + keywords instead). + + * typemanager.cs (MemberLookup): Implemented proper access + control, closing a long standing set of bug reports. The problem + was that the Framework only has two bits: Public and NonPublic, + and NonPublic includes private and protected methods, but we need + to enforce the FamANDAssem, FamOrAssem and Family. + +2002-05-11 Miguel de Icaza + + * statement.cs (GotoCase): Return true: Ammounts to giving up + knowledge on whether we return or not, and letting the other case + be responsible for it. + +2002-05-10 Miguel de Icaza + + * driver.cs: Do not load directories for each file processed, only + do it if there is a pattern. + + * ecore.cs: Report readonly assigns here as well, as we might have + been resolved only by MemberAccess. + + (SimpleName.SimpleNameResolve): Also be useful for LValue + resolution. We need this to propagate assign to local readonly variables + + * typemanager.cs: Use a ptrhashtable for the criteria, because we + do not want to reuse potential criteria memory. + + * class.cs (MyEventBuilder): Set reflected_type; + + * ecore.cs (Constantify): Added support for constifying bools. + + (RootContext.LookupType): Added a cache for values looked up in + the declaration space. + + * typemanager.cs (FindMembers): Now is a front-end to + RealFindMembers, and provides a two-level hashtable-based cache to + the request. + + 15% performance improvement: from 22.5 to 19.2 seconds. + + * expression.cs (IsParamsMethodApplicable): use foreach. + (Invocation.DoResolve): ditto. + (New.DoResolve): ditto. + (ArrayCreation.DoResolve): ditto. + + * ecore.cs (FindMostEncompassingType): use foreach. + + * delegate.cs (NewDelegate.DoResolve): Use foreach + + * ecore.cs (Expression.FindMostSpecificSource): Use foreach. + (RemoveMethods): use foreach. + + * expression.cs (Invocation.MakeUnionSet): Optimization: Use two + nested foreach statements instead of for, and also break out of + the inner loop once a match is found. + + (Invocation.OverloadResolve): Use foreach, simplify the code. + +2002-05-08 Miguel de Icaza + + * cfold.cs (BinaryFold): During an enumeration evaluation context, + we actually unwrap the expression to allow for extra information + to be extracted. + + * expression.cs: Use Shr_Un on unsigned operations. + +2002-05-08 Ravi Pratap + + * ecore.cs (FindMostEncompass*): Fix trivial bug where the set of + applicable operators was not being considered correctly. This closes + the bug Miguel reported. + +Wed May 8 16:40:50 CEST 2002 Paolo Molaro + + * attribute.cs: check that the type derives from System.Attribute + and report the correct error in that case (moved the duplicate code to + its own method, too). + +Wed May 8 11:50:31 CEST 2002 Paolo Molaro + + * attribute.cs: lookup attribute type name as the spec says: first the + bare attribute name and then name + "Attribute" (nant compiles with + mcs after this fix). + +2002-05-07 Miguel de Icaza + + * expression.cs (Unary.TryReduceNegative): Ah! Tricky! Tricky! + Because of the way we parse things, we should try to see if a + UIntConstant can fit in an integer. + +2002-05-07 Ravi Pratap + + * ecore.cs (GetConversionOperators): Do not pick up op_True operators + when we are in an explicit context. + + (ConvertReferenceExplicit): When converting from Iface type S to Class + T make sure the rules are implemented as an OR. + + * parameter.cs (ParameterType): Make it a property for now although the + purpose really isn't anything immediate. + + * expression.cs (Is*Applicable): Do better checking on the parameter type + of a ref/out parameter. The ones from the system assemblies are already + marked with the correct type so we don't need to do any correction. + + * ecore.cs (StandardConversionExists): Conversion from Interface types to + the object type is standard too so include that. + +2002-05-06 Miguel de Icaza + + * ecore.cs (StandardConversionExists): Augment with missing code: + deal with IntConstant, LongConstants and Enumerations. + + * assign.cs: Report the error, instead of failing silently + + * rootcontext.cs (AddGlobalAttributes): Track attributes on the + typecontainer that they are declared, because the + typecontainer/namespace will have the list of using clauses that + need to be applied. + + Assembly Attributes were escaping the normal registration + mechanism. + + (EmitCode): Apply attributes within an EmitContext that represents + the container they were declared on. + + * cs-parser.jay: Track bases for structs. How did I get this wrong? + +2002-05-06 Ravi Pratap + + * ecore.cs (FindMostEncompassingType, FindMostEncompassedType): + Revamp completely - make much cleaner as we now operate only + on a set of Types. + + (FindMostSpecificSource, FindMostSpecificTarget): New methods + to implement the logic detailed in the spec more correctly. + + (UserDefinedConversion): Update accordingly. + +2002-05-06 Miguel de Icaza + + * statement.cs: Return flow analysis information up. + + * cs-tokenizer.cs (adjust_real): Share code between LITERAL_DOUBLE + and the default. + + (token): Do not consume an extra character before calling + decimal_digits. + +2002-05-06 Piers Haken + + * cs-parser.jay: add 'override' attribute to System.Object.Finalize + +2002-05-06 Miguel de Icaza + + * class.cs (Constructor.Emit): Set the IsStatic flag in the + EmitContext during the instance constructor initializer + resolution, to stop access to instance variables. + + This is mandated by the spec, last paragraph of the `constructor + initializers' section. + +2002-05-05 Miguel de Icaza + + * cs-parser.jay, class.cs (Accessor): new class used to represent + an accessor (get or set). In the past we used `null' to represent + a missing accessor. But this is ambiguous because there was no + way to tell in abstract indexers/properties if one of them was + specified. + + Now there is a way of addressing that. + + * expression.cs (Indexers.GetIndexersForType): Use TypeManager.MemberLookup + instead of FindMembers. + + * class.cs (TypeContainer.EmitFieldInitializer): Do not typecast + the result of Assign.Resolve as Assign, but rather as ExpressionStatement. + + * attribute.cs: Treat indexers and properties as the same in terms + of applying attributes + + * ecore.cs (FindMostEncompassedType): Use statically initialized + EmptyExpressions()s like we do elsewhere to avoid creating useless + objects (and we take this out of the tight loop). + + (GetConversionOperators): Move the code to extract the actual + operators to a separate routine to clean things up. + +2002-05-04 Miguel de Icaza + + * ecore.cs (FieldExpr): Remove un-needed tests for null, since now + events are always registered FieldBuilders. + + * class.cs (FieldBase): New class shared by Fields + + * delegate.cs: If we are a toplevel delegate, use our full name. + If we are a nested delegate, then only use our tail name. + +2002-05-02 Ravi Pratap + + * expression.cs (IsApplicable): Ensure that we add the "&" to + ref/out types before comparing it with the type of the argument. + + (IsParamsMethodApplicable): Ditto. + + (Argument.Type): Use TypeManager.LookupType instead of Type.GetType - + silly me ;-) + + * delegate.cs : Handle the case when we have more than one applicable + method. Flag an error only when we finish checking all. + +2002-05-02 Miguel de Icaza + + * expression.cs: Add support for boolean static initializers. + +2002-05-01 Miguel de Icaza + + * attribute.cs: Use proper cast for Events, since we use a MyEventBuilder. + + * parameter.cs (ComputeParameterTypes, + ComputeAndDefineParameterTypes): Better error handling: now we + clear the `types' cache if we fail during any of the type lookups. + We also return the status code correctly to our caller + + * delegate.cs: If we fail to define a delegate, abort the extra + steps. + + * expression.cs (Binary.ResolveOperator): for + operator==(object,object) and operator !=(object, object) we also + have to verify that there is an implicit conversion from one to + the other. + + (ArrayAccess.DoResolve): Array Access can operate on + non-variables. + +2002-04-30 Miguel de Icaza + + * assign.cs (CompoundAssign): A new class used as a "flag" that + the assignment actually is happening as part of a compound + assignment operator. + + During compound assignment, a few new rules exist to enable things + like: + + byte b |= 1 + 2 + + From the spec: + + x op= y can be evaluated as x = (T) (x op y) (ie, an explicit cast + to the type of x) if y is implicitly convertible to the type of x, + and the operator is a builtin operator and the return type of the + operator is explicitly convertible to the type of x. + + * rootcontext.cs: Reset warning level to 2. 4 catches various + "interesting" features in mcs, we must clean this up at some + point, but currently am trying to kill other bugs ;-) + + * ecore.cs (SimpleName.SimpleNameResolve): Perform member lookups + in container classes as well. + + * expression.cs (Binary.ResolveOperator): Handle string case + before anything else (as operator overloading does emit an error + before doing anything else). + + This code could go away when we move to a table driven model, but + i could not come up with a good plan last night. + +2002-04-30 Lawrence Pit + + * typemanager.cs (CSharpName): reimplementation using regex. + * class.cs: added null check for fields in Emit + * rootcontext.cs: set warninglevel to 4 + +2002-04-29 Miguel de Icaza + + * typemanager.cs (CSharpName): reimplemented with Lupus + suggestion. + +2002-04-28 Miguel de Icaza + + * statement.cs (If): correclty implement Resolve, because we were + not catching sem errors in there. The same process is needed + everywhere else. + (Return, StatementExpression, For, While, Do, Throw, Lock): Implement Resolve + + + (Statement.Warning_DeadCodeFound): Factorize code. + (While): Report dead code here too. + + (Statement): Added Resolve virtual method to allow + for resolution split from the emit code. + +2002-04-26 Miguel de Icaza + + * statement.cs (EmitBoolExpression): No longer try to resolve the + expression here. + (MakeBoolean): New utility function that resolve, implicitly + converts to boolean and tags the expression. + + + (If, Do): Implement dead code elimination. + (While): Implement loop inversion + + (Do, While, For, If): Resolve the expression prior to calling our + code generation. + +2002-04-22 Lawrence Pit + + * class.cs: + - added method Report28 (warning: program has more than one entry point) + - added method IsEntryPoint, implements paragraph 10.1 of the spec + - modified method Method.Define, the part at the end of the method + + * rootcontext.cs: added static public Location EntryPointLocation; + + * ../errors/cs0028.cs : Add test case for the above warning. + + * typemanager.cs: + - modified method CSharpName to allow arrays of primitive type to + be printed nicely (e.g. instead of System.Int32[][] it now prints + int[][]) + - added method CSharpSignature: returns the signature of a method + in string format to be used in reporting errors, warnings, etc. + + * support.cs: InternalParameters.ParameterDesc variable tmp initialized + with String.Empty. + +2002-04-26 Ravi Pratap + + * delegate.cs (Define): Fix extremely silly bug where I was + setting the type of the 'object' parameter of the BeginInvoke + method to System.IAsyncResult instead of System.Object ;-) + +2002-04-26 Miguel de Icaza + + * class.cs (ConstructorInitializer.Resolve): Also use DeclaredOnly + here. + + (Constructor.Emit): return if we fail to initialize the + constructor. Another door closed! + + * expression.cs (New.DoResolve): Improve error message (from -6 to + 1501). Use DeclaredOnly lookup to find the exact constructor. + + * typemanager.cs (MemberLookup): If DeclaredOnly is set, do not + loop. This is useful. + + * cs-parser.jay: Adjust the default parameters so that destructors + have the proper signature. + +2002-04-26 Martin Baulig + + * driver.cs (LoadAssembly): If `assembly' contains any characters + which are only valid in path names and not in assembly names + (currently slash, backslash and point), use Assembly.LoadFrom () + instead of Assembly.Load () on the `assembly' (before iteration + over the link_paths). + +2002-04-26 Martin Baulig + + * cs-tokenizer.cs (is_hex): Correctly handle lowercase chars. + +2002-04-25 Miguel de Icaza + + * class.cs (Property): use the new typemanager.MemberLookup + + (TypeContainer.MemberLookup): Implement using the + TypeManager.MemberLookup now. + + * typemanager.cs: Make MemberLookup a function of the TypeManager, + and return MemberInfos, so that these can be used without an + EmitContext (what we had before). + +2002-04-24 Miguel de Icaza + + * expression.cs: Fix the case where the argument to params if the + type of the params. I omitted handling this before. Fixed + +2002-04-22 Miguel de Icaza + + * driver.cs: Call BootCorlib_PopulateCoreType + + * class.cs (Property.CheckBase): Check for properties only, not + for all members. + + * interface.cs: Temporary hack: try/catch around the + CustomAttributeBuilder, because I am getting an exception that I + do not understand. + + * rootcontext.cs (BootCorlib_PopulateCoreType): Populate some + types whose definitions are required to be there (attributes are + defined before standard types). + + Compute definitions as we boot the various types, as they are used + immediately (value_type class will need object_type, but if we do + not initialize object_type, we will pass a null, which will let + the runtime pick the System.Object from the existing corlib, which + is not what we want). + +2002-04-22 Patrik Torstensson + + * cs-tokenizer.cs: fixed a number of trim() issues. + +2002-04-22 Ravi Pratap + + * expression.cs (Argument.Type): Ensure that we return the correct + type when we have out or ref parameters [in which case we + append a "&"]. + +2002-04-22 Miguel de Icaza + + * class.cs (Property, Indexer): Allow extern modifier in there. + + * typemanager.cs (InitBaseTypes): Initializes object_type and + value_type, since those will be used early on during the bootstrap + process to compile corlib. + + (InitCoreTypes): Move code from here to InitBaseTypes. + +2002-04-21 Miguel de Icaza + + * ecore.cs (PropertyExpr): Optimize calls to Array::get_Length on + single-dimension arrays as using the ldlen opcode. + + Daniel Lewis discovered this optimization. + + * typemanager.cs: Add signature for System.Array::get_Length + +2002-04-20 Gonzalo Paniagua Javier + + * statement.cs: report the error when the foreach does not apply to an + array nor a collection. + +2002-04-19 Miguel de Icaza + + * expression.cs: Add implicit conversions to the operator ~. + + * constant.cs (DecimalConstant.Emit): Emit decimal value. + + * typemanager.cs: Locate the decimal constructor. + +2002-04-17 Gonzalo Paniagua Javier + + * attribute.cs: use the new property of TypeOf. + * expression.cs: added 'get' property around typearg. + + These changes fix a build breaker reported by NickD. Is this the + correct way to fix? If not, please, revert my changes and make it + work :-). + +2002-04-17 Miguel de Icaza + + * attribute.cs: Add support for typeof in attribute invocations. + I am not sure that this is right though. + +2002-04-14 Duncan Mak + + * cfold.cs (BinaryFold): Catch DivideByZeroException in the + Binary.Operator.Division case. + +2002-04-13 Ravi Pratap + + * class.cs (DefineType): Ensure that we do a proper check on + attribute types and also register it with the TypeManager. + + (TypeContainer.Targets): The default for attribute types is + AttributeTargets.All. + + * attribute.cs (ApplyAttributes): Registering the attribute type + is done elsewhere, not when we discover we have a Usage attribute. + +2002-04-12 Ravi Pratap + + * expression.cs (VerifyArgumentsCompat): Implement Miguel's suggestion + and get rid of is_delegate parameter. + + * everywhere : update. + +2002-04-12 Ravi Pratap + + * cs-parser.jay (compilation_unit): Revamp completely to use + some new ideas that I got from Rhys' grammar to solve the problems + with assembly level attributes. + + (outer_declaration): New grammar production. + + (attribute_sections): Add. + + (opt_attributes): Base on attribute_sections + + (namespace_declaration): Allow opt_attributes to tackle the case + when we have assembly level attributes - we are clever in this + regard now ;-) + + * attribute.cs (ApplyAttributes): Do not worry about assembly + attributes in the non-global context. + + * rootcontext.cs (AddGlobalAttributes): Go back to using this + instead of SetGlobalAttributes. + + * class.cs, rootcontext.cs : Ensure we define and generate + attribute types before anything else. + + * attribute.cs (CheckAttribute and GetValidPlaces): Handle the exception + and flag the new error -20 for the case when the attribute type + does not have valid targets specified. csc does not catch this. + + * ../errors/errors.txt : update for error # -20 + +2002-04-11 Ravi Pratap + + * support.cs (InternalParameters.ParameterModifier): Do some null + checking and return sane values. + + * class.cs (Method.Define): If we are a PInvoke method, ensure + that we are static and extern. Report error # 601 + + * ../errors/cs0601.cs : Add test case for the above error. + +2002-04-07 Ravi Pratap + + * rootcontext.cs (attribute_types): We need to keep type of + all attribute types separately and emit code for them first. + + (RegisterAttribute) : Implement. + + * class.cs (DefineType): Check if the current Type is a custom + attribute type and register it accordingly. + + * rootcontext.cs (AddGlobalAttributes): Fix silly bug where we were + adding the first attribute twice and rename to + + (SetGlobalAttributes): this. + + * rootcontext.cs (NamespaceLookup): Run through the aliases too and perform + lookups. + + * attribute.cs (ApplyAttributes): Take an additional argument telling us + if we are processing global arguments. Hmm, I am unsure of this. + +2002-04-12 Gonzalo Paniagua Javier + + * expression.cs: added static array of strings to avoid calling + Enum.ToString () for Operator in Binary. Significant recover of + performance. + +2002-04-10 Miguel de Icaza + + * class.cs (FindMembers): Allow the Builders of the various + members to be null. If they are skip them. This only happens + during the PInvoke declaration. + +2002-04-09 Miguel de Icaza + + * parameter.cs (Parameters.ComputeParameterTypes): Flag the + failure, so we do not keep going afterwards. + + * expression.cs: (Invocation.OverloadResolve): I believe Ravi + wanted to pass `false' as the `is_delegate' argument. If this is + the case, why not use delegate_type == null to mean `is_delegate = + false' and anything else as is_delegate = true. + +Tue Apr 9 05:40:12 2002 Piers Haken + + * statement.cs: fixed SimpleSwitchEmit to make 'goto case' goto the + code for the section, not the beginning of the tests. + +2002-04-08 Miguel de Icaza + + * cfold.cs: Handle operator + (Enum x, Underlying x) + + * expression.cs (Binary): same. Warn about errors where we have + Enum/Enum in operator + as well. + +Mon Apr 8 06:29:03 2002 Piers Haken + + * statement.cs: + - added support for switch(bool) + - optimize loading of I8/U8 constants (ldc.i4, iconv_i8) + - add TableSwitchEmit() to handle table-based switch statements + +2002-04-05 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Factor out code which + does parameter compatibility checking with arguments so that we can + re-use the code even from Delegate.VerifyApplicability + + (VerifyArgumentsCompat): Move above code here. + + * delegate.cs (VerifyApplicability): Get rid of duplicate code + and instead make a call to the above method. + +2002-03-31 Ravi Pratap + + * typemanager.cs (attribute_type): Corresponds to System.Attribute. + We use it to keep track of classes which are attribute types. + +2002-04-02 Miguel de Icaza + + * delegate.cs (Delegate.Define): Correctly define the types in the + presence of fixed and array parameters. + + * class.cs (TypeContainers.FindMembers): Use NonPublic flag while + doing FindMembers. + + * ecore.cs (Expression.MemberLookup): Reset binding flags to not + include NonPublic after the first iteration. + + * class.cs (Indexer.CheckBase): Only check if both parents are + non-null. + + * cs-parser.jay (accessor_body): If empty, set to null. + + * ecore.cs (SimpleName.SimpleNameResolve): We did not have the + same code path here to resolve constants names that we did have in + MemberAccess.DoResolve. There is too much code duplicated here. + +2002-04-01 Miguel de Icaza + + * statement.cs, makefile: Drop Statementcollection and just use ArrayLists + + * ecore.cs: Optimize UserDefinedConversion by minimizing the calls + to MakeUnionSet. + + * cs-tokenizer.cs: Reuse a single StringBuilder for assembling + tokens, numbers and strings. + + * ecore.cs (MethodGroupExpr): Make Emit warn about missing + parenthesis. + + * delegate.cs: Use ComputeAndDefineParameterTypes for both the + asyncronous parameters and the regular parameters. + + * codegen.cs (CodeGen.Init): Use the constructor that allows us to + specify the target directory. + + * expression.cs: (This.DoResolve): Simplify + (As.Emit): Optimize, do not generate IsInst if the expression is + always of the given type. + + (Is.DoResolve): Bug fix, we were reporting both always/never for + the is expression. + + * (Invocation.MakeUnionSet): Simplify vastly and optimize, we were + creating too many unnecessary arrays. + +2002-03-31 Miguel de Icaza + + * class.cs (EmitFieldInitializer): Use Assign expression to assign + fields instead of rolling our own initializer. Takes care of all + implicit conversions, and drops unnecessary static checks/argument. + +2002-03-31 Dick Porter + + * driver.cs: use the GetDirectories() return values properly, and + use "/" as path separator. + +2002-03-30 Miguel de Icaza + + * expression.cs (Unary): Optimize - - expr into expr. + (Binary): Optimize a + (-b) into a -b. + + * codegen.cs (CodeGen): Made all methods static. + +2002-03-29 Miguel de Icaza + + * rootcontext.cs: + + * decl.cs: Rename `definition' into `TypeBuilder' and drop the + TypeBuilder property. + + * cs-parser.jay: Drop the use of RecordXXX and use RecordDecl + instead. + + * tree.cs: Removed the various RecordXXXX, and replaced with a + single RecordDecl. Removed all the accessor methods, and just + left a single access point Type + + * enum.cs: Rename DefineEnum to DefineType. + + * decl.cs: New abstract method `DefineType' used to unify the + Defines for Enumerations, Interfaces, TypeContainers and + Delegates. + + (FindType): Moved LookupInterfaceOrClass here. Moved the + LookupBaseClasses method that used to live in class.cs and + interface.cs here, and renamed to FindType. + + * delegate.cs: Implement DefineType. Take advantage of the + refactored pattern for locating the parent builder without taking + the parent_builder argument (which we know does not work if we are + nested, and triggering a toplevel definition). + +2002-03-28 Miguel de Icaza + + * decl.cs (MemberCore.CheckMethodAgainstBase): Test if the + accessibility of a member has changed during override and report + an error if so. + + * class.cs (Method.Define, Property.Define): Only complain on + overrides if the method is private, any other accessibility is + fine (and since we just checked the permission is the same, we are + good to go). + + * cs-tokenizer.cs: only line, region, endregion, if, endif, else + and elif are processed always. The other pre-processing + directives are only processed if we are "taking" the path + +2002-03-29 Martin Baulig + + * class.cs (Method.Emit): Only emit symbolic debugging info if the + current location is not Null. + + * codegen.cs (CodeGen.SaveSymbols): Split out symbol writing code into + a separate method so we can profile it. + + * driver.cs (ShowTime): We need to use `(int) span.TotalSeconds' since + `span.Seconds' are just seconds, but no minutes or hours. + (MainDriver): Profile the CodeGen.SaveSymbols calls. + +2002-03-28 Miguel de Icaza + + * class.cs (Method.Define), (Property.Define), (Indexer.Define): + Remove the gratuitous set of Final: + + // If an interface implementation, then we can set Final. + if (((flags & MethodAttributes.Abstract) == 0) && + implementing.DeclaringType.IsInterface) + flags |= MethodAttributes.Final; + + I do not know what I was smoking when I used that. + + + * cs-parser.jay, delegate.cs: Make Delegate be a DeclSpace, first + step into fixing the name resolution issues for delegates and + unifying the toplevel name resolution. + +2002-03-28 Martin Baulig + + * class.cs (Method.Emit): If we have a symbol writer, call its + OpenMethod(), CloseMethod() and SetMethodSourceRange() methods to + tell it about the current method. + + * codegen.cs (EmitContext.Mark): New public method. Tell the symbol + writer that we're going to emit the first byte of IL code for a new + statement (a new source line). + (EmitContext.EmitTopBlock): If we have a symbol writer, call + EmitContext.Mark() before emitting any code. + + * location.cs (SymbolDocument): Return null when we're Null. + + * statement.cs (Statement): Moved the `Location loc' variable here. + (Statement.EmitBoolExpression): If we have a symbol writer, call + ec.Mark() before emitting any code to tell it that we're at the + beginning of a new statement. + (StatementExpression): Added `Location' argument to the constructor. + (Block): Added public readonly variable `StartLocation' and public + variable `EndLocation'. The latter is to be set using SetEndLocation(). + (Block): Added constructor which takes a start and end location. + (Block.SetEndLocation): New method. This sets the end location. + (Block.EmitMeta): If we have a symbol writer, tell it the names of the + local variables we create. + (Block.Emit): If we have a symbol writer, call ec.Mark() before emitting + each statement and do also mark the begin and end of the block. + + * cs-parser.jay (block : OPEN_BRACE): Use the new `Block' constructor to + tell it the current lexer.Location, use Location.Null for the end of the + block. + (block : OPEN_BRACE opt_statement_list CLOSE_BRACE): When closing the + current block, set its end location using SetEndLocation(). + (statement_expression): StatementExpression constructor now takes the + lexer.Location as additional argument. + (for_statement, declare_local_variables): Likewise. + (declare_local_variables): When creating a new implicit block, use the + new Block constructor and pass it the lexer.Location. + +2002-03-28 Miguel de Icaza + + * ecore.cs (Expression.MemberLookup): On interfaces, lookup + members also on the parent interfaces recursively. + +2002-03-27 Miguel de Icaza + + * report.cs: Use new formats, since Gonzalo finished the missing + bits. + + * expression.cs (Binary.ResolveOperator): added missing operator| + operator& and operator^ for bool/bool. + + * cs-parser.jay: CheckDef now takes a Location argument that is + used to report errors more precisly (instead of reporting the end + of a definition, we try to track something which is a lot closer + to the source of the problem). + + * cs-tokenizer.cs: Track global token use, so we can properly flag + the use of #define/#undef after the first token has been seen. + + Also, rename the reportXXXX to Error_DescriptiveName + + * decl.cs (DeclSpace.IsTopLevel): Move property here from + TypeContainer, so that Enum and Interface can use this too. + + * class.cs (TypeContainer.LookupInterfaceOrClass, + GetInterfaceOrClass, GetClassBases, DefineType): Drop the + `builder' argument. Typically this was used to pass the parent + builder (a ModuleBuilder or a TypeBuilder from whoever triggered + the definition). + + The problem is that a nested class could trigger the definition of + a toplevel class, and the builder would be obviously wrong in that + case. + + So we drop this argument, and we compute dynamically the + TypeBuilder/ModuleBuilder (the correct information was available + to us anyways from DeclSpace.Parent) + + * interface.cs (Interface.DefineInterface): Drop builder + parameter cleanup like class.cs + + * enum.cs (Enum.DefineEnum): Drop builder parameter. Clean up + like class.cs + + * statement.cs (Switch.EmitObjectInteger): Emit short/ushort + values. + + (Try.Emit): Propagate the returns value from the statement. + + (Return.Emit): Even if we are leavning + + * driver.cs: Catch IOExpcetion for Directory.GetFiles as well. + + * modifiers.cs: Fix the computation of MethodAttributes flags. + +Tue Mar 26 21:14:36 CET 2002 Paolo Molaro + + * driver.cs: allow compilation of files that start with '/'. + Add a default case when checking the argument of --target. + +2002-03-25 Miguel de Icaza + + * interface.cs: Implement the same search algorithm for types in + the interface code. + + * delegate.cs: Do not allow multiple definition. + + * Recovered ChangeLog that got accidentally amputated + + * interface.cs (Interface.DefineInterface): Prevent from double definitions. + + * rootcontext.cs: Load manually enum to allow core classes to + contain enumerations. + + * enum.cs, ecore.cs, driver.cs, attribute.cs, class.cs, expression.cs: + Update to new static methods in TypeManager. + + * typemanager.cs (GetMethod, GetConstructor): Use our + implementation of FindMembers to find the members, since during + corlib compilation, the types are TypeBuilders and GetMethod and + GetConstructor do not work. + + Make all methods in TypeManager static. + + (InitCodeHelpers): Split the functionality from + the InitCodeTypes function. + + * driver.cs: Call InitCodeHelpers after we have populated the + types. + + * cs-parser.jay (delegate_declaration): we did not used to compute + the delegate name correctly for void delegates. + +2002-03-24 Miguel de Icaza + + * rootcontext.cs (RootContext): Init the interface_resolve_order + and type_container_resolve_order always. + + (ResolveCore, BootstrapCorlib_ResolveClass, + BootstrapCorlib_ResolveStruct): New functions to bootstrap the + compiler when compiling with --nostdlib + + * class.cs (TypeContainer.DefineType): Check that our parent is + not null. This test is most important when we are bootstraping + the core types. + + * codegen.cs: Split out the symbol writing code. + +2002-03-25 Martin Baulig + + * driver.cs (-g): Made -g an alias for --debug. + +2002-03-24 Martin Baulig + + * codegen.cs (SymbolWriter): New public variable. Returns the + current symbol writer. + (CodeGen): Added `bool want_debugging_support' argument to the + constructor. If true, tell the ModuleBuild that we want debugging + support and ask it for the ISymbolWriter. + (Save): If we have a symbol writer, call it's Close() method after + saving the assembly. + + * driver.c (--debug): New command line argument to create a + debugger information file. + + * location.cs (SymbolDocument): New public property. Returns an + ISymbolDocumentWriter object for the current source file or null + if we don't have a symbol writer. + +2002-03-21 Miguel de Icaza + + * driver.cs (LoadAssembly): Correctly return when all the paths + have been tried and not before. + + * statement.cs (Switch.Emit): return the actual coverage for this + statement (returns/not-returns) + + (Switch.SimpleSwitchEmit): Do not generate jumps to the end of the + switch of the statement if we are the last switch section. That + kills two problems: try/catch problems (we used to emit an empty + nop at the end) and switch statements where all branches would + return. + +2002-03-19 Miguel de Icaza + + * driver.cs: Add default assemblies (the equivalent to the + Microsoft CSC.RSP file) + + * cs-tokenizer.cs: When updating `cols and setting it to zero, + also update tokens_seen and set it to false. + + * driver.cs: Implement --recurse for Mike. + + * driver.cs (SplitPathAndPattern): Small bug fix, I was not + correctly splitting out the paths. + +2002-03-18 Miguel de Icaza + + * interface.cs (Interface.PopulateProperty): Instead of using + `parent' as the declaration space for the set parameters, use + `this' + + * support.cs (InternalParameters): InternalParameters constructor + takes a DeclSpace instead of a TypeContainer. + + * expression.cs (ArrayCreation.EmitDynamicInitializers): If value + types are being initialized, load the address of it before calling + the function. + + (New): Provide a mechanism to disable the generation of local + value type temporaries when the caller will be providing us with + an address to store it. + + (ArrayCreation.EmitDynamicInitializers): Use it. + +2002-03-17 Miguel de Icaza + + * expression.cs (Invocation.EmitArguments): Only probe for array + property if there is more than one argument. Sorry about that. + + * class.cs (Invocation.EmitArguments): Fix to emit arguments for + empty param arrays. + + * class.cs (Method.LabelParameters): Fix incorrect code path that + prevented the `ParamArrayAttribute' from being applied to the + params attribute. + +2002-03-16 Miguel de Icaza + + * support.cs (ReflectionParameters): Correctly compute whether the + last argument is a params array. Fixes the problem with + string.Split ('a') + + * typemanager.cs: Make the assemblies array always be non-null + (empty, but non-null) + + * tree.cs (RecordDecl): New function that abstracts the recording + of names. This reports error 101, and provides a pointer to the + previous declaration. Fixes a crash in the compiler. + + * cs-parser.jay (constructor_declaration): Update to new grammar, + and provide a constructor_body that can be empty. + +2002-03-15 Miguel de Icaza + + * driver.cs: Add support for --resources. + + * expression.cs: (FetchGetMethod, FetchAddressMethod, EmitAssign): + Make all types for the various array helper methods be integer. + + * ecore.cs (Expression.ConvertNumericExplicit): Pass the + CheckState to ConvCast. + + (ConvCast): Now it takes a `checked' state argument, to avoid + depending on the emit context for the conversion, and just using + the resolve time setting. + + * expression.cs (ArrayCreation.EmitArrayArguments): New function, + instead of Invocation.EmitArguments. We do not emit the original + arguments, instead we emit those which have been converted to + unsigned int expressions. + + * statement.cs (Block.EmitMeta): Drop tracking of indexes. + + * codegen.cs: ditto. + + * expression.cs (LocalVariableReference): Drop the use of the + Store function that depended on the variable index. + + * statement.cs (VariableInfo): Drop the `Idx' property from this + class, as this is not taking into account the indexes for + temporaries tat we generate during the execution, getting the + indexes wrong. + + * class.cs: First emit class initializers, then call the parent + constructor. + + * expression.cs (Binary): Fix opcode emision. + (UnaryMutator.EmitCode): Support checked code generation + + * ecore.cs (MemberLookup): TypeManager.FindMembers will return + matches for events for both the Static and Instance scans, + pointing to the same element. Fix that. + +2002-03-14 Miguel de Icaza + + * rootcontext.cs (ResolveTree): Always set the + interface_resolve_order, because nested interfaces will be calling + into us. + + * class.cs (GetInterfaceOrClass): Track the same resolution + process used by TypeManager.LookupType. This fixes the nested + type lookups in class declarations (separate path from + LookupType). + + (TypeContainer.DefineType): Also define nested interfaces. + (TypeContainer.RegisterOrder): New public function used to + register the order in which child interfaces need to be closed. + + Nested interfaces need to be closed after their parents have been + created. + + * interface.cs (InterfaceAttr): Put all the logic for computing + the interface attribute here. + + (DefineInterface): Register our interface order with the + RootContext or with the TypeContainer depending on the case. + +2002-03-12 Miguel de Icaza + + * cs-parser.jay: rework foreach statement to work with the new + changes to the policy on SimpleNames. + + * report.cs: support Stacktrace on warnings as well. + + * makefile: drop --unsafe and /unsafe from the compile. + +2002-03-13 Ravi Pratap + + * ecore.cs (StandardConversionExists): Modify to take an Expression + as the first parameter. Ensure we do null -> reference type conversion + checking. + + * Everywhere : update calls accordingly, making use of MyEmptyExpr to store + temporary Expression objects. + +Wed Mar 13 12:32:40 CET 2002 Paolo Molaro + + * interface.cs: workaround bug in method overloading resolution + (there is already a bugzilla bug for it). + +2002-03-12 Miguel de Icaza + + We could also solve this problem by having a separate path for + performing type lookups, instead of DoResolve, we could have a + ResolveType entry point, and only participating pieces of the + production (simplename, deref, array) would implement this. + + * codegen.cs (EmitContext): New field OnlyLookupTypes used to + signal SimpleName to only resolve type names and not attempt to + resolve anything else. + + * expression.cs (Cast): Set the flag. + + * ecore.cs (SimpleName): Use the OnlyLookupTypes flag + + * class.cs: Only report 108 if there is no `new' modifier. + + * cs-parser.jay: rework foreach statement to work with the new + changes to the policy on SimpleNames. + + * report.cs: support Stacktrace on warnings as well. + + * makefile: drop --unsafe and /unsafe from the compile. + +2002-03-11 Miguel de Icaza + + * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable + lookups here, instead of doing that at parse time. This means + that our grammar will not introduce `LocalVariableReferences' as + expressions at this point. That solves the problem of code like + this: + + class X { + static void Main () + { int X = 1; + { X x = null }}} + + This is only half the fix. The full fix requires parameters to + also be handled in this way. + + * Everywhere: Use ec.DeclSpace on calls to LookupType, as this + makes the use more obvious of the DeclSpace. The + ec.TypeContainer.TypeBuilder is now only used to pull the + TypeBuilder for it. + + My theory is that I can get rid of the TypeBuilder completely from + the EmitContext, and have typecasts where it is used (from + DeclSpace to where it matters). + + The only pending problem is that the code that implements Aliases + is on TypeContainer, and probably should go in DeclSpace. + + * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable + lookups here, instead of doing that at parse time. This means + that our grammar will not introduce `LocalVariableReferences' as + expressions at this point. That solves the problem of code like + this: + + class X { + static void Main () + { int X = 1; + { X x = null }}} + + This is only half the fix. The full fix requires parameters to + also be handled in this way. + + * class.cs (Property.DefineMethod): When implementing an interface + method, set newslot, when implementing an abstract method, do not + set the flag (before we tried never setting it, or always setting + it, which is the difference). + (Indexer.DefineMethod): same. + (Method.DefineMethod): same. + + * ecore.cs: Only set the status used flag if we get back a Field. + + * attribute.cs: Temporary hack, so Paolo can keep working. + +2002-03-08 Ravi Pratap + + * attribute.cs (Attribute.UnmanagedType): This is to keep track of + the unmanaged type in the case we have a MarshalAs attribute. + + (Resolve): Handle the case when we are parsing the special MarshalAs + attribute [we need to store the unmanaged type to use later] + + * typemanager.cs (marshal_as_attr_type): Built in type for the + MarshalAs Attribute. + + * attribute.cs (ApplyAttributes): Recognize the MarshalAs attribute + on parameters and accordingly set the marshalling info. + +2002-03-09 Miguel de Icaza + + * class.cs: Optimizing slightly by removing redundant code after + we switched to the `NoTypes' return value. + (Property.DefineMethod): use NoTypes here too. + + This fixes the bug I introduced in my last batch of changes. + +2002-03-05 Ravi Pratap + + * tree.cs (RecordEnum): Add. We now keep track of enums too. + + * class.cs (LookupInterfaceOrClass): Check against the list of recorded + Enums since those are types too. + + * cs-parser.jay (enum_declaration): Record enums as we parse them. + + * enum.cs (DefineEnum): Return if the TypeBuilder has already been defined + thanks to a call during the lookup process. + +2002-03-07 Miguel de Icaza + + * statement.cs (Foreach): Lots of work to accomodate a particular + kind of foreach statement that I had not kept in mind. It is + possible to have foreachs on classes that provide a GetEnumerator + method that return objects that implement the "pattern" for using + a foreach, there is no need to support GetEnumerator + specifically. + + This is needed to compile nant. + + * decl.cs: Only report 114 if the member is not `Finalize' and if + the warning level is at least 2. + + * class.cs: Moved the compare function from Method to + MethodSignature. + + (MethodSignature.InheritableMemberSignatureCompare): Add new + filter function that is used to extract inheritable methods from a + class. + + (Method.Define): Use the new `inheritable_method_signature_filter' + delegate + + * cs-tokenizer.cs (get_cmd_arg): Do not add white space to the + command. + +2002-03-06 Miguel de Icaza + + * ecore.cs (Expression.ConvertReferenceExplicit): Removed dead code. + + * cs-parser.jay: Add opt_semicolon to the interface declaration. + + * expression.cs: Pass location information to + ConvertImplicitStandard. + + * class.cs: Added debugging code to track return values from + interfaces. + +2002-03-05 Miguel de Icaza + + * expression.cs (Is.DoResolve): If either side of the `is' is an + interface, do not flag the warning. + + * ecore.cs (ImplicitReferenceConversion): We need a separate test + for interfaces + + * report.cs: Allow for --fatal to be used with --probe. + + * typemanager.cs (NoTypes): Move the definition for the empty Type + array here. + + * class.cs (TypeContainer.FindMembers): Also look for methods defined by + properties. + (TypeContainer.DefineProxy): New function used to proxy to parent + implementations when implementing interfaces. + (TypeContainer.ParentImplements): used to lookup if our parent + implements a public function that is required by an interface. + (TypeContainer.VerifyPendingMethods): Hook this up. + + * typemanager.cs (TypeManager, AddModule, AddAssembly): Make the + `modules' and `assemblies' arraylists into arrays. We only grow + these are the very early start up of the program, so this improves + the speedof LookupType (nicely measured). + + * expression.cs (MakeByteBlob): Replaced unsafe code with + BitConverter, as suggested by Paolo. + + * cfold.cs (ConstantFold.Binary): Special case: perform constant + folding of string concatenation, but if either side is a string, + and the other is not, then return null, and let the runtime use + the concatenation on the string plus the object (using + `Object.ToString'). + +2002-03-04 Miguel de Icaza + + Constant Folding has been implemented now. + + * expression.cs (Unary.Reduce): Do not throw an exception, catch + the error instead on types that are not supported in one's + complement. + + * constant.cs (Constant and all children): New set of functions to + perform implict and explicit conversions. + + * ecore.cs (EnumConstant): Implement the new functions to perform + conversion by proxying to the child expression. + + * codegen.cs: (ConstantCheckState): Constant evaluation has its + own separate setting that can not be turned off from the command + line using --unchecked or --checked and is only controlled using + the checked/unchecked statements and expressions. This setting is + used by the constant folder to flag errors. + + * expression.cs (CheckedExpr, UncheckedExpr): Set the + ConstantCheckState as well. + + During Resolve, they also have to flag the state, because the + constant folder runs completely in the Resolve phase. + + * statement.cs (Checked, Unchecked): Set the ConstantCheckState as + well. + +2002-03-01 Miguel de Icaza + + * cfold.cs: New file, this file contains the constant folder. + + * ecore.cs (IMemoryLocation.AddressOf): Now takes an extra + argument to track whether we are using the resulting address to + load or store a value and provide better error messages. + + (FieldExpr.Emit, FieldExpr.EmitAssign, FieldExpr.AddressOf): Use + new AddressOf arguments. + + * statement.cs (Foreach.EmitCollectionForeach): Update + + * expression.cs (Argument.Emit): Call AddressOf with proper + arguments to track usage. + + (New.DoEmit): Call AddressOf with new arguments. + + (Unary.Emit): Adjust AddressOf call. + +2002-03-01 Ravi Pratap + + * cs-parser.jay (member_access): Change the case for pre-defined types + to use a MemberAccess instead of a SimpleName. Thanks to Felix again for + this suggestion. + + * class.cs (Operator::Emit): If we are abstract or extern, we don't have + a method body. + + * attribute.cs (CheckAttribute, ApplyAttribute): Ensure that we treat operators + essentially like methods and apply attributes like MethodImplOptions to them too. + + * ecore.cs (SimpleName.SimpleNameResolve): Perform a check on ec.TypeContainer.TypeBuilder + not being null. + + * codegen.cs (EmitContext): The constructor now takes in an extra argument specifying the + DeclSpace as the distinction is important. We provide sane defaults as usually the TypeContainer + is the DeclSpace. + + * Update code everywhere accordingly. + + * ecore.cs : Change references to ec.TypeContainer to ec.DeclSpace where appropriate. + + * cs-parser.jay (enum_declaration): Set the current namespace of the enum. + +2002-02-28 Ravi Pratap + + * rootcontext.cs (LookupType): As we cycle through the chain of namespaces + try performing lookups against those instead of jumping straight into using + the 'using' clauses. + + (ImplicitParent): Add. Thanks to Felix Arrese-Igor for this idea. + + (LookupType): Perform lookups in implicit parents too. + + * class.cs (GetInterfaceOrClass): Modify to perform the exact same lookup + sequence as RootContext.LookupType. + + * rootcontext.cs (NamespaceLookup): Split out code from LookupType which tries + the various cases of namespace lookups into this method. + +2002-03-01 Miguel de Icaza + + * cs-parser.jay: Add support for [Attribute ()] (empty arguments + in positional arguments) + + * class.cs (Operator): Update the AllowedModifiers to contain + extern. + + * cs-parser.jay: Update operator declaration to allow for the + operator body to be empty. + + * cs-tokenizer.cs: Added '\u' unicode support in strings and hex + values. + +2002-02-27 Miguel de Icaza + + * class.cs (Method.Emit): Label parameters. + + * driver.cs: Return 1 or 0 as the program exit code. + +2002-02-26 Miguel de Icaza + + * expression.cs: Special case the `null' object when trying to + auto-compute the type, as anything can be explicitly converted to + that. + + * ecore.cs (Expression.ConvertExplicit): Bug fix, thanks for + spotting this Paolo. + + (Expression.ImplicitNumericConversion): Perform comparissions of + the type using the underlying type in the case of an enumeration + rather than using the enumeration type for the compare. + + Cope with the underlying == type case, which is not possible to + catch before. + + (Expression.ConvertNumericExplicit): Perform comparissions of + the type using the underlying type in the case of an enumeration + rather than using the enumeration type for the compare. + + * driver.cs: If the user does not supply an extension, assume .exe + + * cs-parser.jay (if_statement): Rewrote so that we can track the + location for the if statement. + + * expression.cs (Binary.ConstantFold): Only concat strings when + the operation is "+", not everything ;-) + + * statement.cs (Statement.EmitBoolExpression): Take a location + argument. + (If, While, Do): Track location. + + * expression.cs (Binary.ResolveOperator): In the object + string + case, I was missing a call to ConvertImplicit + +2002-02-25 Ravi Pratap + + * parameter.cs (Parameter.ExternalType): Take in extra DeclSpace and + Location arguments. Ensure we use RootContext.LookupType to do our work + and not try to do a direct Type.GetType and ModuleBuilder.GetType + + * interface.cs (PopulateMethod): Handle the type of the parameter being + null gracefully. + + * expression.cs (Invocation.BetterFunction): Handle the case when we + have a params method with no fixed arguments and a call is made with no + arguments. + +2002-02-25 Miguel de Icaza + + * cs-tokenizer.cs: Add support for the quote-escape-sequence in + the verbatim-string-literal + + * support.cs (InternalParameters.ParameterModifier): handle null + fixed parameters. + (InternalParameters.ParameterType): ditto. + + * parameter.cs (VerifyArgs): Also check if the fixed parameter is + duplicating the name of the variable parameter. + (GetParameterByName): Fix bug where we were not looking up array + paramters if they were the only present (thanks Paolo!). + (GetParameterInfo): We only have an empty set of types if both + fixed and array are set to null. + (GetParameterInfo-idx): Handle FixedParameter == null + + * cs-parser.jay: Handle the case where there is no catch + statements (missing null test). + +2002-02-22 Miguel de Icaza + + * driver.cs (MainDriver): Be conservative on our command line + handling. + + Catch DirectoryNotFoundException when calling GetFiles. + + (SplitPathAndPattern): Used to split the input specification into + a path and a pattern that we can feed to Directory.GetFiles. + +2002-02-21 Miguel de Icaza + + * statement.cs (Fixed): Implement the last case of the Fixed + statement (string handling). + + * expression.cs (StringPtr): New class used to return a char * to + a string; Used by the Fixed statement. + + * typemanager.cs: Add char_ptr_type. Add get_OffsetToStringData method. + + * expression.cs (Binary.ResolveOperator): Remove redundant + MemberLookup pn parent type. + Optimize union call, we do not need a union if the types are the same. + (Unary.ResolveOperator): REmove redundant MemberLookup on parent + type. + + Specialize the use of MemberLookup everywhere, instead of using + the default settings. + + (StackAlloc): Implement stackalloc keyword. + + * cs-parser.jay: Add rule to parse stackalloc. + + * driver.cs: Handle /h, /help, /? + + * expression.cs (MakeByteBlob): Removed the hacks we had in place + before we supported unsafe code. + + * makefile: add --unsafe to the self compilation of mcs. + +2002-02-20 Miguel de Icaza + + * expression.cs (PointerArithmetic): New class that is used to + perform pointer arithmetic. + (Binary.Resolve): Handle pointer arithmetic + Handle pointer comparission. + (ArrayPtr): Utility expression class that is used to take the + address of an array. + + (ElementAccess): Implement array access for pointers + + * statement.cs (Fixed): Implement fixed statement for arrays, we + are missing one more case before we are done. + + * expression.cs (Indirection): Implement EmitAssign and set the + ExprClass to Variable. This allows pointer dereferences to be + treated as variables, and to have values assigned to them. + + * ecore.cs (Expression.StoreFromPtr): New utility function to + store values dereferencing. + +2002-02-20 Ravi Pratap + + * expression.cs (Binary.ResolveOperator): Ensure that we are + not trying to operate on a void type - this fixes the reported + bug. + + * decl.cs (CheckMethodAgainstBase): Do not allow overriding if + the parent implementation is sealed. + + * ../errors/cs0239.cs : Add. + + * attribute.cs (ApplyAttributes): Handle Modulebuilders too. + + * typemanager.cs (unverifiable_code_type): Corresponds to + System.Security.UnverifiableCodeAttribute. We need to emit this for modules + which have unsafe code in them. + + * rootcontext.cs (EmitCode): Emit the above attribute when we are in an + unsafe context. + +2002-02-19 Miguel de Icaza + + * cs-tokenizer.cs: Add support for @"litreal strings" + + Make tokenizer accept pre-processor directives + on any column (remove the old C-like limitation). + + * rootcontext.cs (EmitCode): Emit any global attributes. + (AddGlobalAttributes): Used to keep track of assembly attributes. + + * attribute.cs (ApplyAttributes): Support AssemblyAttributes. + + * cs-parser.jay: Add support for global attributes. + +2002-02-17 Miguel de Icaza + + * expression.cs (Indirection): New helper class. Unary will + create Indirection classes to be able to implement the + IMemoryLocation interface on it. + +2002-02-16 Miguel de Icaza + + * cs-parser.jay (fixed_statement): reference the right statement. + + * statement.cs (Fixed.Emit): Finish implementing the fixed + statement for the &x case. + +2002-02-14 Miguel de Icaza + + * class.cs (Property.Define, Method.Define): Remove newslot when + `implementing'. + + * modifiers.cs: My use of NewSlot when `Abstract' was set was + wrong. NewSlot should only be used if the `new' keyword is present. + + * driver.cs (GetSystemDir): Use CodeBase instead of FullName for + locating our system dir. Sorry about this. + +2002-02-13 Miguel de Icaza + + * driver.cs (GetSystemDir): Compute correctly the location of our + system assemblies. I was using the compiler directory instead of + the library directory. + +2002-02-13 Ravi Pratap + + * expression.cs (BetterFunction): Put back in what Miguel commented out + since it is the correct fix. The problem is elsewhere ;-) + + (IsParamsMethodApplicable): Fix bug where we were not checking that the fixed + parameters of the parms method are themselves compatible or not ! + + (StandardConversionExists): Fix very dangerous bug where we were forgetting + to check that a class implements an interface before saying that an implicit + conversion was allowed. Use ImplementsInterface to do the checking. + +2002-02-13 Miguel de Icaza + + * class.cs (Method.Define): Track whether we are an explicit + implementation or not. And only call DefineMethodOverride if we + are an explicit implementation. + + (Property.DefineMethod): Ditto. + +2002-02-11 Ravi Pratap + + * expression.cs (BetterFunction): Catch hideous bug which was + preventing us from detecting ambiguous calls due to implicit casts i.e + cs0121. + +2002-01-29 Miguel de Icaza + + * support.cs (Pair): Remove un-needed method. I figured why I was + getting the error in cs-parser.jay, the variable in a foreach loop + is readonly, and the compiler does not really treat this as a variable. + + * cs-parser.jay (fixed_statement): Fix grammar. Use ASSIGN + instead of EQUALS in grammar. + + * typemanager.cs (VerifyUnmanaged): Report correct error (208) + + * expression.cs (Unary.DoResolve): Check whether the argument is + managed or not. + +2002-01-28 Miguel de Icaza + + * support.cs: Api for Pair to set a value. Despite the fact that + the variables are public the MS C# compiler refuses to compile + code that accesses the field if the variable is part of a foreach + statement. + + * statement.cs (Fixed): Begin implementation of the fixed + statement. + + (Block.AddVariable): Return the VariableInfo on success and null + on failure instead of true/false. + + * cs-parser.jay (foreach): Catch errors on variables already + defined (we were ignoring this value before) and properly unwind + the block hierarchy + + (fixed_statement): grammar for the fixed statement. + +2002-01-25 Miguel de Icaza + + * expression.cs (UnaryMutator.IsIncrementableNumber): Allow also + pointer types to be incretemented. + + (SizeOf): Implement. + + * cs-parser.jay (pointer_member_access): Implement + expr->IDENTIFIER production. + + * expression.cs (IndexerAccess.DoResolve, ArrayAccess.DoResolve, + MemberAccess.DoResolve, Invocation.DoResolve): Check for pointers + on safe contexts. + + (Unary): Implement indirection. + + * ecore.cs (Expression.UnsafeError): Reports error 214 (pointer + use in non-unsafe context). + + (SimpleName.DoResolve): Check for pointers in field access on safe + contexts. + + (Expression.LoadFromPtr): Factor the load-indirect code in this + function. This was duplicated in UnboxCast and ParameterReference + +2002-01-24 Miguel de Icaza + + * expression.cs (ComposedCast): report an error if a pointer cast + is used in a safe region. + + * ecore.cs (Expression.ConvertExplicit): Add rules for implicit + pointer type casts in unsafe context. + + * codegen.cs (EmitContext): Set up IsUnsafe. + + * cs-parser.jay (non_expression_type): Add productions for pointer + casts. + + * expression.cs (Invocation.EmitCall): Remove chunk of buggy + code. We should not use force into static mode if the method is + not virtual. Fixes bug in MIS + + * statement.cs (Do.Emit, While.Emit, For.Emit, + Statement.EmitBoolExpression): Add support to Do and While to + propagate infinite loop as `I do return' semantics. + + Improve the For case to also test for boolean constants. + + * attribute.cs (Attribute.ApplyAttributes): Add ParameterBuilder + to the list of attributes we can add. + + Remove `EmitContext' argument. + + * class.cs (Method.Define): Apply parameter attributes. + (Constructor.Define): Apply parameter attributes. + (MethodCore.LabelParameters): Move here the core of labeling + parameters. + + * support.cs (ReflectionParameters.ParameterModifier, + InternalParameters.ParameterModifier): Use IsByRef on the type and + only return the OUT bit for these parameters instead of in/out/ref + flags. + + This is because I miss-understood things. The ParameterInfo.IsIn + and IsOut represent whether the parameter has the [In] and [Out] + attributes set. + +2002-01-22 Miguel de Icaza + + * ecore.cs (FieldExpr.Emit): Release temporaries. + + * assign.cs (LocalTemporary.Release): new function. + + * codegen.cs (EmitContext.GetTemporaryStorage, + EmitContext.FreeTemporaryStorage): Rework the way we deal with + temporary storage. Now we can "put back" localbuilders when we + are done with them + +2002-01-21 Miguel de Icaza + + * ecore.cs (FieldExpr.Emit): Handle initonly fields specially: we + need to make a copy of the variable to generate verifiable code. + +2002-01-19 Miguel de Icaza + + * driver.cs: Compute dynamically the system directory. + + * ecore.cs (CopyNewMethods): reworked, exposed, made public. + Slower, but more generally useful. Used by the abstract + registering implementation. + + * expression.cs (ResolveMemberAccess): Reorder the way we evaluate + the rules for the special rule on Type/instances. First check if + we have the same name, and if so, try that special static path + rather than the instance path. + +2002-01-18 Miguel de Icaza + + * cs-parser.jay: Emit 642 (warning: possible empty statement) for + for, while and if. + + * class.cs (TypeBuilder.DefineType): Do not allow inheritance from + Enum, ValueType, Delegate or Array for non-corlib compiles. + + * cs-tokenizer.cs: Catch long identifiers (645) + + * typemanager.cs (IndexerPropetyName): Ravi never tested this + piece of code. + + * class.cs (TypeContainer.RegisterRequiredImplementations): Bug + fix, we were returning too early, so we were not registering + pending methods from abstract classes. + + Do not register pending methods if the class is abstract. + + * expression.cs (Conditional.DoResolve): Report circular implicit + conversions when we neecd to compute it for conditional + expressions. + + (Is.DoResolve): If the expression is always of the provided type, + flag warning 183. If the expression can not ever be of the + provided type flag warning 184. + + * class.cs: Catch 169 as well. + + * ecore.cs (FieldExpr): For now in AddressOf mark as assigned and + read. + +2002-01-18 Nick Drochak + + * makefile: remove path to beta2 csc.exe. path to csc.exe must be in PATH instead. + +2002-01-17 Miguel de Icaza + + * interface.cs: (PopulateMethod): Check for pointers being defined + only if the unsafe context is active. + (PopulateProperty): ditto. + (PopulateIndexer): ditto. + + * class.cs (Method, Method.Define): Allow `unsafe' modifier to be + specified. If pointers are present, make sure that they are + present in an unsafe context. + (Constructor, Constructor.Define): ditto. + (Field, Field.Define): ditto. + (Property, Property.Define): ditto. + (Event, Event.Define): ditto. + + * interface.cs (Interface.GetInterfaceTypeByName): Only lookup the + hashtable if there are classes or structs defined. + + * expression.cs (LocalVariableReference.DoResolve): Simplify this + code, as the constant resolution moved. + + * statement.cs (Block.EmitMeta): Resolve all constants as we emit + the metadata, so we can flag error 133. + + * decl.cs (MemberCore.UnsafeOK): New function to test that a + pointer is being declared in an unsafe context. + +2002-01-16 Miguel de Icaza + + * modifiers.cs (Modifiers.Check): Require a Location argument. + Report error 227 for Unsafe use. + + * typemanager.cs: Remove IsPointerType, we should be using Type.IsPointer + + * statement.cs (For.Emit): If the test is null, then report that + we do `return', as we wont reach anything afterwards. + + (Switch.SwitchGoverningType): Track the expression that matched + the conversion. + + * driver.cs: Allow negative numbers as an error code to flag. + + * cs-parser.jay: Handle 1551. + + * namespace.cs: Add 1537 checking (repeated using alias namespaces). + +2002-01-15 Miguel de Icaza + + * cs-parser.jay: Report 1518 (type declaration can only contain + class, struct, interface, enum or delegate) + + (switch_label): Report 1523 (keywords `case' or `default' must + preced code) + + (opt_switch_sections): Report 1522 (empty switch) + + * driver.cs: Report 1515 (response file specified multiple times) + Report 1516 (Source file specified multiple times). + + * expression.cs (Argument.Resolve): Signal 1510 + + (BaseAccess.Resolve, BaseIndexer.Resolve): Signal 1511 (base + access not allowed in static code) + +2002-01-11 Ravi Pratap + + * typemanager.cs (IsPointerType): Utility method which we are going + to need a lot. + + * ecore.cs (ImplicitReferenceConversion): A pointer type cannot be cast to + the object type, so we take care of that. + + * expression.cs (FullMethodDesc): Also include the return type in descriptions. + + * support.cs (ParameterDesc): Fix minor bug which was causing params tags to be + added to non-params parameters :-) + + * typemanager.cs (CSharpName): Include 'void' type too. + + (void_ptr_type): Include in the set of core types. + + * ecore.cs (ConvertImplicit): Make use of ConvertImplicitStandard instead of + duplicating code. + + (ConvertImplicitStandard): Handle standard implicit pointer conversions when we have + an unsafe context. + + * cs-parser.jay (local_variable_pointer_type): Add support for 'void *' as I had + completely forgotten about it. + +2002-01-10 Ravi Pratap + + * cs-parser.jay (pointer_type): Add. This begins our implementation + of parsing rules for unsafe code. + + (unsafe_statement): Implement. + + (embedded_statement): Modify to include the above. + + * statement.cs (Unsafe): Implement new class for unsafe blocks. + + * codegen.cs (EmitContext.InUnsafe): Add. This determines + if the current context is an unsafe one. + + * cs-parser.jay (local_variable_pointer_type): Since local variable types + are handled differently, we need separate rules for them. + + (local_variable_declaration): Update to use local_variable_pointer_type + to allow variable declarations of unmanaged pointer types. + + * expression.cs (Unary.ResolveOperator): Ensure that the '&' operator is used only + in unsafe contexts. + + * ../errors/cs0214.cs : Add. + +2002-01-16 Nick Drochak + + * makefile: remove 'response' file when cleaning. + +2002-01-15 Miguel de Icaza + + * cs-parser.jay: Report 1524. + +2002-01-14 Miguel de Icaza + + * typemanager.cs (RegisterMethod): drop checking if we have + registered this from here + +2002-01-12 Miguel de Icaza + + * class.cs (Method.EmitDestructor): Implement calling our base + destructor. + + * statement.cs (Try.Emit): Fix to reset the InFinally to the old + value of InFinally. + + * codegen.cs (EmitContext.EmitTopBlock): Destructors will call + this routine and will wrap the call in a try/catch block. Deal + with the case. + +2002-01-11 Miguel de Icaza + + * ecore.cs (Expression.MemberLookup): instead of taking a + parameter `same_type' that was used to tell whether we could + access private members we compute our containing type from the + EmitContext. + + (FieldExpr): Added partial support for volatile fields. This does + not work for volatile fields exposed from assemblies, as I can not + figure out how to extract the modreq from it. + + Updated all the source files to use this. + + * codegen.cs (EmitContext): Compute ContainerType ahead of time, + because it is referenced by MemberLookup very often. + +2002-01-09 Ravi Pratap + + * typemanager.cs (IndexerPropertyName): If we have a TypeBuilder, use + TypeBuilder.GetCustomAttributes to retrieve what we need. + + Get rid of redundant default_member_attr_type as this is the same as + default_member_type which already exists. + + * interface.cs, attribute.cs : Update accordingly. + +2002-01-08 Miguel de Icaza + + * typemanager.cs: Enable IndexerPropertyName again. It does not + work for TYpeBuilders though. Ravi, can you please fix this? + + * cs-tokenizer.cs: Accept _ as a name in pp-expressions. + + * expression.cs (Argument.Emit): Handle the case of ref objects + being passed to ref functions; + + (ParameterReference.EmitLoad): Loads the content of the pointer + without dereferencing. + +2002-01-07 Miguel de Icaza + + * cs-tokenizer.cs: Implemented the pre-processing expressions. + +2002-01-08 Ravi Pratap + + * class.cs (Indexer.DefineMethod): Incorporate the interface + type in the name of the method if we are doing explicit interface + implementation. + + * expression.cs (ConversionExists): Remove as it is completely obsolete. + + (BetterConversion): Fix extremely trivial bug where we were referring to + ConversionExists instead of StandardConversionExists ! Hooray, things are fine + again ! + + * ../errors/bug16.cs : Add although we have fixed it. + +2002-01-07 Miguel de Icaza + + * expression.cs (BaseIndexer): Begin implementation. + + * class.cs (TypeContainer.IsInterfaceMethod): Bug fix. + + * cs-parser.jay (indexer_declarator): Use qualified_identifier + production directly to remove a shift/reduce, and implement + explicit interface implementation. + + * cs-tokenizer.cs: Fix tokenizer, it was consuming one extra char + after a floating point suffix. + + * expression.cs (DoNumericPromotions): Improved the conversion for + uint/uint. If we have a constant, we avoid doing a typecast to a + larger type. + + * class.cs (Indexer): Implement explicit interface implementation + for indexers. + +Sat Jan 5 16:08:23 CET 2002 Paolo Molaro + + * class.cs: make the default instance constructor public and hidebysig. + +2001-01-03 Ravi Pratap + + * interface.cs (EmitDefaultMemberAttr): Make this helper method static + so we can call it from elsewhere. + + * class.cs (TypeContainer.Emit): Emit the attribute here too. The rule is that + we emit it internally if the class has a defined indexer; otherwise the user + emits it by decorating the class definition with the DefaultMemberAttribute. + + * attribute.cs (ApplyAttributes): Perform checks to see that the DefaultMember + attribute is not used on a type which defines an indexer. + + * cs-tokenizer.cs (get_cmd_arg): Ensure we trim whitespace and also include the tab + character when we skip whitespace. + + * ../errors/cs0646.cs : Add. + +2002-01-03 Miguel de Icaza + + * ecore.cs (SimpleName.ResolveSimpleName): Report error 120 + again. + + * makefile: Add practical target `mcs3.exe' which builds the third + generation compiler. + + * expression.cs (New): Fix structures constructor calling. + + * class.cs (Property, Method, Indexer): Emit Final flag on the + method if we are an interface implementation and we are not + abstract. + + * ecore.cs (PropertyExpr): New public field `IsBase', tells + whether this property is referencing a `base' method. + + * expression.cs (Invocation.EmitCall): take an extra argument: + is_base, this is used to determine whether the `call' or + `callvirt' opcode should be used. + + + * delegate.cs: update EmitCall. + + * class.cs (Method.Define): Set NewSlot for the cases where we are + not implementing an interface method. + + (Property.Define): ditto. + +2002-01-02 Miguel de Icaza + + * cs-tokenizer.cs: (Tokenizer.escape): Escape '\r' as '\r' not as + 'r'. Allows mcs to parse itself fully. + +2002-01-02 Ravi Pratap + + * expression.cs (ArrayCreation.num_automatic_initializers): Keep track + of the number of initializers that require the InitializeArray method. + + (CheckIndices): Store the Expression in all cases - not the plain value. Also + update the above field where necessary. + + (MakeByteBlob): Update accordingly. + + (DoEmit): Call EmitStaticInitializers only if the number of initializers is + greater than 2. + + (EmitDynamicInitializers): Update in accordance with the new optimization. + + (ArrayAccess.EmitStoreOpcode): Include char type along with short and ushort - the + same OpCode applies. + + * cs-parser.jay : Fix some glaring errors I introduced. + +2002-01-01 Ravi Pratap + + * parameters.cs (AddVariable, AddConstant): Pass in current_local_parameters + so that we can check for name clashes there too. + + * typemanager.cs (default_member_attr_type): The attribute that we need to emit + for interface indexers. + + * interfaces.cs (Define): Emit the default member attribute. + + * expression.cs (MakeByteBlob): Fix extremely trivial bug where the wrong + variable was being referred to while setting the value ;-) + +2002-01-01 Miguel de Icaza + + * expression.cs (MakeByteBlob): Optimize: we do not need to fill + byte-by-byte information when we know the data is zero. + + Make the block always a multiple of 4, because + DefineInitializedData has a bug. + + * assign.cs: Fix, we should assign from the temporary, not from + the source. + + * expression.cs (MakeByteBlob): Fix my incorrect code. + +2001-12-31 Miguel de Icaza + + * typemanager.cs (EnumToUnderlying): This function is used to get + the underlying type from an enumeration, because it does not + always work. + + * constant.cs: Use the I4_S form for values between -128 and 127. + + * statement.cs (Block.LookupLabel): Looks up a label. + (Block): Drop support for labeled blocks. + + (LabeledStatement): New kind of statement that represents a label + only. + + (Goto): Finally implement this bad boy. + + * cs-parser.jay: Update to reflect new mechanism to implement + labels. + +2001-12-30 Miguel de Icaza + + * codegen.cs (EmitContext.This): a codegen property that keeps the + a single instance of this instead of creating many different this + instances. + + * delegate.cs (Delegate.DoResolve): Update to use the property; + + * ecore.cs (SimpleName.SimpleNameResolve): Ditto + + * expression.cs (BaseAccess.DoResolve): Ditto. + +2001-12-29 Ravi Pratap + + * typemanager.cs (methodimpl_attr_type): Add to hold the type + corresponding to System.Runtime.CompilerServices.MethodImplAttribute. + + (InitCoreTypes): Update accordingly. + + * attribute.cs (Resolve): Remember if the attribute is a MethodImplAttribute + so we can quickly store the state. + + (ApplyAttributes): Set the correct implementation flags + for InternalCall methods. + +2001-12-29 Miguel de Icaza + + * expression.cs (EmitCall): if a method is not virtual, then do + not use callvirt on it. + + (ArrayAccess.EmitAssign): storing non-builtin value types (ie, + user defined stuff) requires the use of stobj, which takes an + address on the stack instead of an array and an index. So emit + the Ldelema operation for it. + + (EmitStoreOpcode): Use stobj for valuetypes. + + (UnaryMutator.EmitCode): Use the right 1 value depending on + whether we are dealing with int64/uint64, float or doubles. + + * class.cs (TypeContainer.AddConstructor): Fix the logic to define + constructors that I implemented last night. + + (Constructor.IsDefault): Fix to work properly for static + constructors. + + * cs-parser.jay (CheckDef): report method signature errors. + Update error number 103 to be 132. + + * decl.cs: New AdditionResult enumeration value: MethodExists. + Although we do this check for methods later on in the semantic + analysis, catching repeated default constructors is so easy that + we catch these here. + + * expression.cs (Binary.DoNumericPromotions): Fix the uint64 type + promotions code. + + (ParameterReference.EmitAssign, Emit): handle + bools as bytes. + + (ArrayAccess.EmitLoadOpcode): Handle bool type here. + (ArrayAccess.EmitStoreOpcode): ditto. + + * cs-tokenizer.cs (is_punct): Eliminated empty computation. + + * expression.cs (MakeByteBlob): Complete all the missing types + (uint, short, ushort, byte, sbyte) + + * class.cs: Only init instance field initializers on instance + constructors. + + Rename `constructors' to instance_constructors. + + (TypeContainer.AddConstructor): Only add constructors to the list + if it is not static. + + Make sure that we handle default_static_constructor independently + everywhere where we handle instance_constructors + +2001-12-28 Miguel de Icaza + + * class.cs: Do not lookup or create a base initializer for a + static constructor. + + (ConstructorInitializer.Resolve): use the proper type to lookup + for constructors. + + * cs-parser.jay: Report error 1585 (modifiers between type and name). + + * enum.cs, interface.cs: Remove CloseType, this is taken care by + in DeclSpace. + + * decl.cs: CloseType is now an virtual method, the default + implementation just closes this type. + +2001-12-28 Ravi Pratap + + * attribute.cs (DefinePInvokeMethod): Set the implementation flags + to PreserveSig by default. Also emit HideBySig on such methods. + + Basically, set the defaults to standard values. + + * expression.cs (Invocation.BetterFunction): We need to make sure that for each + argument, if candidate is better, it can't be worse than the best ! + + (Invocation): Re-write bits to differentiate between methods being + applicable in their expanded form and their normal form - for params + methods of course. + + Get rid of use_standard everywhere as only standard conversions are allowed + in overload resolution. + + More spec conformance. + +2001-12-27 Miguel de Icaza + + * driver.cs: Add --timestamp, to see where the compiler spends + most of its time. + + * ecore.cs (SimpleName.DoResolve): Do not create an implicit + `this' in static code. + + (SimpleName.DoResolve): Implement in terms of a helper function + that allows static-references to be passed upstream to + MemberAccess. + + (Expression.ResolveWithSimpleName): Resolve specially simple + names when called by MemberAccess to implement the special + semantics. + + (Expression.ImplicitReferenceConversion): Handle conversions from + Null to reference types before others, as Null's type is + System.Object. + + * expression.cs (Invocation.EmitCall): Handle the special case of + calling methods declared on a reference type from a ValueType + (Base classes System.Object and System.Enum) + + (MemberAccess.Resolve): Only perform lookups on Enumerations if + the left hand side is a TypeExpr, not on every enumeration. + + (Binary.Resolve): If types are reference types, then do a cast to + object on operators != and == of both arguments. + + * typemanager.cs (FindMembers): Extract instance and static + members if requested. + + * interface.cs (PopulateProperty): Use void_type instead of null + as the return type for the setter method. + + (PopulateIndexer): ditto. + +2001-12-27 Ravi Pratap + + * support.cs (ReflectionParameters): Fix minor bug where we + were examining the wrong parameter for the ParamArray attribute. + + Cope with requests for the type of the parameter at position + greater than the params parameter's. We now return the element + type of the params array as that makes more sense. + + * expression.cs (Invocation.IsParamsMethodApplicable): Update + accordingly as we no longer have to extract the element type + ourselves. + + (Invocation.OverloadResolve): Update. + +2001-12-27 Miguel de Icaza + + * statement.cs (Foreach.GetEnumeratorFilter): Do not compare + against IEnumerator, test whether the return value is a descendant + of the IEnumerator interface. + + * class.cs (Indexer.Define): Use an auxiliary method to implement + the other bits of the method definition. Begin support for + explicit interface implementation. + + (Property.DefineMethod): Use TypeManager.void_type instead of null + for an empty return value. + +2001-12-26 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): if we are + dealing with a FieldExpr which is composed of a FieldBuilder, in + the code path we did extract the constant, but we should have + obtained the underlying value to be able to cast it (otherwise we + end up in an infinite loop, this is what Ravi was running into). + + (ArrayCreation.UpdateIndices): Arrays might be empty. + + (MemberAccess.ResolveMemberAccess): Add support for section + 14.5.4.1 that deals with the special case of E.I when E is a type + and something else, that I can be a reference to a static member. + + (ArrayCreation.MakeByteBlob): It is not an error to not be able to + handle a particular array type to create byte blobs, it is just + something we dont generate byteblobs for. + + * cs-tokenizer.cs (get_cmd_arg): Ignore \r in commands and + arguments. + + * location.cs (Push): remove the key from the hashtable that we + are about to add. This happens for empty files. + + * driver.cs: Dispose files after we have parsed them. + + (tokenize): new function that only runs the tokenizer on its + input, for speed testing. + +2001-12-26 Ravi Pratap + + * class.cs (Event.Define): Define the private field only if there + are no accessors defined. + + * expression.cs (ResolveMemberAccess): If there is no associated + field with the event, that means we have an event defined with its + own accessors and we should flag error cs0070 since transforming + ourselves into a field is not valid in that case. + + * ecore.cs (SimpleName.DoResolve): Same as above. + + * attribute.cs (DefinePInvokeMethod): Set the default calling convention + and charset to sane values. + +2001-12-25 Ravi Pratap + + * assign.cs (DoResolve): Perform check on events only if they + are being accessed outside the declaring type. + + * cs-parser.jay (event_declarations): Update rules to correctly + set the type of the implicit parameter etc. + + (add_accessor, remove_accessor): Set current local parameters. + + * expression.cs (Binary): For delegate addition and subtraction, + cast the return value from the method into the appropriate delegate + type. + +2001-12-24 Ravi Pratap + + * typemanager.cs (RegisterDelegateData, GetDelegateData): Get rid + of these as the workaround is unnecessary. + + * delegate.cs (NewDelegate.DoResolve): Get rid of bits which registered + delegate data - none of that is needed at all. + + Re-write bits to extract the instance expression and the delegate method + correctly. + + * expression.cs (Binary.ResolveOperator): Handle the '-' binary operator + on delegates too. + + * attribute.cs (ApplyAttributes): New method to take care of common tasks + of attaching attributes instead of duplicating code everywhere. + + * everywhere : Update code to do attribute emission using the above method. + +2001-12-23 Miguel de Icaza + + * expression.cs (IsParamsMethodApplicable): if there are not + parameters, return immediately. + + * ecore.cs: The 0 literal can be implicity converted to an enum + type. + + (SimpleName.DoResolve): First lookup the type, then lookup the + members. + + (FieldExpr.Emit): If the InstanceExpression is a ValueType, we + want to get its address. If the InstanceExpression is not + addressable, store the result in a temporary variable, then get + the address of it. + + * codegen.cs: Only display 219 errors on warning level or above. + + * expression.cs (ArrayAccess): Make it implement the + IMemoryLocation interface. + + (Binary.DoResolve): handle the operator == (object a, object b) + and operator != (object a, object b) without incurring into a + BoxedCast (because 5 != o should never be performed). + + Handle binary enumerator operators. + + (EmitLoadOpcode): Use Ldelema if the object we are loading is a + value type, otherwise use Ldelem_ref. + + Use precomputed names; + + (AddressOf): Implement address of + + * cs-parser.jay (labeled_statement): Fix recursive block + addition by reworking the production. + + * expression.cs (New.DoEmit): New has a special case: + + If we are dealing with a ValueType, we have a few + situations to deal with: + + * The target of New is a ValueType variable, that is + easy, we just pass this as the variable reference + + * The target of New is being passed as an argument, + to a boxing operation or a function that takes a + ValueType. + + In this case, we need to create a temporary variable + that is the argument of New. + + +2001-12-23 Ravi Pratap + + * rootcontext.cs (LookupType): Check that current_type is not null before + going about looking at nested types. + + * ecore.cs (EventExpr.EmitAddOrRemove): Rename from EmitAssign as we do + not implement the IAssignMethod interface any more. + + * expression.cs (MemberAccess.ResolveMemberAccess): Handle EventExprs specially + where we tranform them into FieldExprs if they are being resolved from within + the declaring type. + + * ecore.cs (SimpleName.DoResolve): Do the same here. + + * assign.cs (DoResolve, Emit): Clean up code considerably. + + * ../errors/bug10.cs : Add. + + * ../errors/cs0070.cs : Add. + + * typemanager.cs : Use PtrHashtable for Delegate data hashtable etc. + + * assign.cs : Get rid of EventIsLocal everywhere. + +2001-12-23 Miguel de Icaza + + * ecore.cs (ConvertIntLiteral): finished the implementation. + + * statement.cs (SwitchLabel): Convert the value we are using as a + key before looking up the table. + +2001-12-22 Miguel de Icaza + + * codegen.cs (EmitTopBlock): Require a Location argument now. + + * cs-parser.jay (constructor_declarator): We need to setup + current_local_parameters before we parse the + opt_constructor_initializer, to allow the variables to be bound + to the constructor arguments. + + * rootcontext.cs (LookupType): First lookup nested classes in our + class and our parents before we go looking outside our class. + + * expression.cs (ConstantFold): Extract/debox the values at the + beginnning. + + * rootcontext.cs (EmitCode): Resolve the constants first before we + resolve the types. This is not really needed, but it helps debugging. + + * statement.cs: report location. + + * cs-parser.jay: pass location to throw statement. + + * driver.cs: Small bug fix. + + * report.cs: Updated format to be 4-zero filled digits. + +2001-12-22 Ravi Pratap + + * expression.cs (CheckIndices): Fix minor bug where the wrong + variable was being referred to ;-) + + (DoEmit): Do not call EmitStaticInitializers when the + underlying type is System.Object. + +2001-12-21 Ravi Pratap + + * ecore.cs (EventExpr.Resolve): Implement to correctly set the type + and do the usual workaround for SRE. + + * class.cs (MyEventBuilder.EventType): New member to get at the type + of the event, quickly. + + * expression.cs (Binary.ResolveOperator): Handle delegate addition. + + * assign.cs (Assign.DoResolve): Handle the case when the target + is an EventExpr and perform the necessary checks. + + * ecore.cs (EventExpr.EmitAssign): Implement the IAssignMethod + interface. + + (SimpleName.MemberStaticCheck): Include check for EventExpr. + + (EventExpr): Set the type in the constructor itself since we + are meant to be born fully resolved. + + (EventExpr.Define): Revert code I wrote earlier. + + * delegate.cs (NewDelegate.Resolve): Handle the case when the MethodGroup's + instance expression is null. The instance expression is a This in that case + or a null, depending on whether it is a static method or not. + + Also flag an error if the reference to a method is ambiguous i.e the MethodGroupExpr + refers to more than one method. + + * assign.cs (DoResolve): Check whether the event belongs to the same Type container + and accordingly flag errors. + +2001-12-21 Miguel de Icaza + + * statement.cs (Throw.Emit): Add support for re-throwing exceptions. + +2001-12-22 Miguel de Icaza + + * location.cs (ToString): Provide useful rutine. + +2001-12-21 Miguel de Icaza + + * ecore.cs (Expression.ConvertIntLiteral): Do not return Constant + objects, return the actual integral boxed. + + * statement.cs (SwitchLabel): define an ILLabel for each + SwitchLabel. + + (Switch.CheckSwitch): If the value is a Literal, extract + the underlying literal. + + Also in the unused hashtable we had, add the SwitchLabel so we can + quickly look this value up. + + * constant.cs: Implement a bunch of new constants. Rewrite + Literal based on this. Made changes everywhere to adapt to this. + + * expression.cs (Expression.MakeByteBlob): Optimize routine by + dereferencing array only once, and also copes with enumrations. + + bytes are two bytes wide, not one. + + (Cast): Perform constant conversions. + + * ecore.cs (TryImplicitIntConversion): Return literals instead of + wrappers to the literals here. + + * expression.cs (DoNumericPromotions): long literals can converted + to ulong implicity (this is taken care of elsewhere, but I was + missing this spot). + + * ecore.cs (Expression.Literalize): Make the return type Literal, + to improve type checking. + + * rootcontext.cs: Lookup for nested classes in our class hierarchy. + +2001-12-20 Miguel de Icaza + + * literal.cs: Revert code from ravi that checked the bounds. The + bounds are sane by the definition of the type itself. + + * typemanager.cs: Fix implementation of ImplementsInterface. We + need to actually look up in our parent hierarchy for interfaces + implemented. + + * const.cs: Use the underlying type for enumerations + + * delegate.cs: Compute the basename for the delegate creation, + that should fix the delegate test case, and restore the correct + Type Lookup semantics in rootcontext + + * rootcontext.cs: Revert Ravi's last patch. The correct way of + referencing a nested type with the Reflection API is using the "+" + sign. + + * cs-parser.jay: Do not require EOF token at the end. + +2001-12-20 Ravi Pratap + + * rootcontext.cs (LookupType): Concatenate type names with + a '.' instead of a '+' The test suite passes again. + + * enum.cs (Enum.DefineEnum): Set RTSpecialName on the 'value__' + field of the enumeration. + + * expression.cs (MemberAccess.ResolveMemberAccess): Add support for + the case when the member is an EventExpr. + + * ecore.cs (EventExpr.InstanceExpression): Every event which is not + static has an associated instance expression. + + * typemanager.cs (RegisterEvent): The usual workaround, now for events. + + (GetAddMethod, GetRemoveMethod): Workarounds, as usual. + + * class.cs (Event.Define): Register event and perform appropriate checks + for error #111. + + We define the Add and Remove methods even if the use provides none because + in that case, we provide default implementations ourselves. + + Define a private field of the type of the event. This is done by the CSC compiler + and we should be doing it too ;-) + + * typemanager.cs (delegate_combine_delegate_delegate, delegate_remove_delegate_delegate): + More methods we use in code we generate. + + (multicast_delegate_type, delegate_type): Two separate types since the distinction + is important. + + (InitCoreTypes): Update accordingly for the above. + + * class.cs (Event.Emit): Generate code for default accessors that we provide + + (EmitDefaultMethod): Do the job in the above. + + * delegate.cs (DefineDelegate): Use TypeManager.multicast_delegate_type in the + appropriate place. + +2001-12-20 Miguel de Icaza + + * class.cs (Indexer.Define): Fix bug, we were setting both Get/Set + builders even if we were missing one. + + * interface.cs, class.cs, enum.cs: When calling DefineNestedType + pass the Basename as our class name instead of the Name. The + basename will be correctly composed for us. + + * parameter.cs (Paramters): Now takes a Location argument. + + * decl.cs (DeclSpace.LookupType): Removed convenience function and + make all the code call directly LookupType in RootContext and take + this chance to pass the Location information everywhere. + + * Everywhere: pass Location information. + +2001-12-19 Miguel de Icaza + + * class.cs (Constructor.Define): Updated way of detecting the + length of the parameters. + + (TypeContainer.DefineType): Use basename as the type name for + nested types. + + (TypeContainer.Define): Do not recursively define types here, as + definition is taken care in order by the RootContext. + + * tree.cs: Keep track of namespaces in a per-file basis. + + * parameter.cs (Parameter.ComputeSignature): Update to use + DeclSpace. + + (Parameters.GetSignature): ditto. + + * interface.cs (InterfaceMethod.GetSignature): Take a DeclSpace + instead of a TypeContainer. + + (Interface.SemanticAnalysis): Use `this' instead of our parent to + resolve names. Because we need to be resolve in our context, not + our parents. + + * driver.cs: Implement response files. + + * class.cs (TypeContainer.DefineType): If we are defined, do not + redefine ourselves. + + (Event.Emit): Emit the code for add/remove handlers. + (Event.Define): Save the MethodBuilders for add/remove. + + * typemanager.cs: Use pair here too. + + * cs-parser.jay: Replaced use of DictionaryEntry for Pair because + DictionaryEntry requires the first argument to be non-null. + + (enum_declaration): Compute full name for registering the + enumeration. + + (delegate_declaration): Instead of using + formal_parameter_list, use opt_formal_parameter_list as the list + can be empty. + + * cs-tokenizer.cs (PropertyParsing): renamed from `properties' + (EventParsing): New property that controls whether `add' and + `remove' are returned as tokens or identifiers (for events); + +2001-12-19 Ravi Pratap + + * class.cs (Event.Define): Revamp use of EventBuilder completely. We now + use MyEventBuilder only and let it wrap the real builder for us. + + (MyEventBuilder): Revamp constructor etc. + + Implement all operations that we perform on EventBuilder in precisely the same + way here too. + + (FindMembers): Update to use the EventBuilder member. + + (Event.Emit): Update accordingly. + +2001-12-18 Ravi Pratap + + * class.cs (MyEventBuilder.Set*): Chain to the underlying builder + by calling the appropriate methods. + + (GetCustomAttributes): Make stubs as they cannot possibly do anything + useful. + + (Event.Emit): Use MyEventBuilder everywhere - even to set attributes. + +2001-12-17 Ravi Pratap + + * delegate.cs (Delegate.Populate): Check that the return type + and various parameters types are indeed accessible. + + * class.cs (Constructor.Define): Same here. + + (Field.Define): Ditto. + + (Event.Define): Ditto. + + (Operator.Define): Check that the underlying Method defined itself + correctly - so it's MethodBuilder should not be null. + + * delegate.cs (DelegateInvocation.DoResolve): Bale out if the type of the Instance + expression happens to be null. + + * class.cs (MyEventBuilder): Workaround for SRE lameness. Implement various abstract + members but as of now we don't seem to be able to do anything really useful with it. + + (FindMembers): Handle events separately by returning the MyEventBuilder of the event, + not the EventBuilder. + +2001-12-18 Miguel de Icaza + + * cs-tokenizer.cs: Add support for defines. + Add support for #if, #elif, #else, #endif + + (eval_var): evaluates a variable. + (eval): stubbed for evaluating functions. + + * cs-parser.jay: Pass the defines information + + * driver.cs: Add --define command line option. + + * decl.cs: Move MemberCore here. + + Make it the base class for DeclSpace. This allows us to catch and + report 108 and 109 for everything now. + + * class.cs (TypeContainer.Define): Extract all the members + before populating and emit the warning 108 (new keyword required + to override) instead of having each member implement this. + + (MemberCore.Define): New abstract method, we will be using this in + the warning reporting engine in Populate. + + (Operator.Define): Adjust to new MemberCore protocol. + + * const.cs (Const): This does not derive from Expression, it is a + temporary object we use to create fields, it is a MemberCore. + + * class.cs (Method.Define): Allow the entry point to be in a + specific class. + + * driver.cs: Rewrite the argument handler to clean it up a bit. + + * rootcontext.cs: Made it just an auxiliary namespace feature by + making everything static. + + * driver.cs: Adapt code to use RootContext type name instead of + instance variable. + + * delegate.cs: Remove RootContext argument. + + * class.cs: (Struct, TypeContainer, Class): Remove RootContext + argument. + + * class.cs (Event.Define): The lookup can fail. + + * cs-tokenizer.cs: Begin implementation of pre-procesor. + + * expression.cs: Resolve the this instance before invoking the code. + +2001-12-17 Miguel de Icaza + + * cs-parser.jay: Add a production in element_access that allows + the thing to become a "type" reference. This way we can parse + things like "(string [])" as a type. + + Note that this still does not handle the more complex rules of + casts. + + + * delegate.cs (Delegate.Populate): Register the delegage constructor builder here. + + * ecore.cs: (CopyNewMethods): new utility function used to + assemble the list of methods from running FindMembers. + + (MemberLookup): Rework FindMembers so that + +2001-12-16 Miguel de Icaza + + * class.cs (TypeContainer): Remove Delegates who fail to be + defined. + + * delegate.cs (Populate): Verify that we dont get null return + values. TODO: Check for AsAccessible. + + * cs-parser.jay: Use basename to emit error 574 (destructor should + have the same name as container class), not the full name. + + * cs-tokenizer.cs (adjust_int): Fit the integer in the best + possible representation. + + Also implements integer type suffixes U and L. + +2001-12-15 Miguel de Icaza + + * expression.cs (ArrayCreation.DoResolve): We need to do the + argument resolution *always*. + + * decl.cs: Make this hold the namespace. Hold the root context as + well. + (LookupType): Move here. + + * enum.cs, class.cs, interface.cs: Adapt to new hierarchy. + + * location.cs (Row, Name): Fixed the code, it was always returning + references to the first file. + + * interface.cs: Register properties defined through interfaces. + + * driver.cs: Add support for globbing on the command line + + * class.cs (Field): Make it derive from MemberCore as well. + (Event): ditto. + +2001-12-15 Ravi Pratap + + * class.cs (Event::Define): Check that the type of the event is a delegate + type else flag error #66. + + Also, re-use TypeContainer.MethodModifiersValid here too as the rules are the + same. + + * attribute.cs (DefinePInvokeMethod): Handle named arguments and process + values of EntryPoint, CharSet etc etc. + + Pass in the values to TypeBuilder.DefinePInvokeMethod; determine Type etc neatly. + + * class.cs (FindMembers): If a method is in transit, its MethodBuilder will + be null and we should ignore this. I am not sure if this is really clean. Apparently, + there's no way of avoiding hitting this because the call is coming from SimpleName.DoResolve, + which needs this to do its work. + + * ../errors/cs0066.cs : Add. + +2001-12-14 Miguel de Icaza + + * typemanager.cs: (GetPropertyGetter, GetPropertyGetter): New + helper functions. + + * class.cs: (MethodSignature.MethodSignature): Removed hack that + clears out the parameters field. + (MemberSignatureCompare): Cleanup + + (MemberCore): New base class used to share code between MethodCore + and Property. + + (RegisterRequiredImplementations) BindingFlags.Public requires + either BindingFlags.Instace or Static. Use instance here. + + (Property): Refactored code to cope better with the full spec. + + * parameter.cs (GetParameterInfo): Return an empty array instead + of null on error. + + * class.cs (Property): Abstract or extern properties have no bodies. + + * parameter.cs (GetParameterInfo): return a zero-sized array. + + * class.cs (TypeContainer.MethodModifiersValid): Move all the + method modifier validation to the typecontainer so we can reuse + this on properties. + + (MethodCore.ParameterTypes): return an empty sized array of types. + + (Property.Define): Test property modifier validity. + + Add tests for sealed/override too. + + (Method.Emit): abstract or extern methods have no bodies. + +2001-12-14 Ravi Pratap + + * class.cs (Method.IsPInvoke): Get rid of it as it is an expensive + thing. + + (Method::Define, ::Emit): Modify accordingly. + + * expression.cs (Invocation::OverloadResolve): Handle error # 121. + + (ArrayCreation::MakeByteBlob): Handle floats and doubles. + + * makefile: Pass in /unsafe. + +2001-12-13 Miguel de Icaza + + * class.cs (MakeKey): Kill routine. + + * class.cs (TypeContainer.Define): Correctly define explicit + method implementations (they require the full interface name plus + the method name). + + * typemanager.cs: Deply the PtrHashtable here and stop using the + lame keys. Things work so much better. + + This of course broke everyone who depended on `RegisterMethod' to + do the `test for existance' test. This has to be done elsewhere. + + * support.cs (PtrHashtable): A hashtable that avoid comparing with + the object stupid Equals method (because, that like fails all over + the place). We still do not use it. + + * class.cs (TypeContainer.SetRequiredInterface, + TypeContainer.RequireMethods): Killed these two routines and moved + all the functionality to RegisterRequiredImplementations. + + (TypeContainer.RegisterRequiredImplementations): This routine now + registers all the implementations required in an array for the + interfaces and abstract methods. We use an array of structures + which can be computed ahead of time to reduce memory usage and we + also assume that lookups are cheap as most classes will not + implement too many interfaces. + + We also avoid creating too many MethodSignatures. + + (TypeContainer.IsInterfaceMethod): Update and optionally does not + clear the "pending" bit if we find that there are problems with + the declaration. + + (TypeContainer.VerifyPendingMethods): Update to report errors of + methods that look like implementations but are not. + + (TypeContainer.Define): Add support for explicit interface method + implementation. + +2001-12-12 Miguel de Icaza + + * typemanager.cs: Keep track of the parameters here instead of + being a feature of the TypeContainer. + + * class.cs: Drop the registration of parameters here, as + InterfaceMethods are also interface declarations. + + * delegate.cs: Register methods with the TypeManager not only with + the TypeContainer. This code was buggy. + + * interface.cs: Full registation here. + +2001-12-11 Miguel de Icaza + + * expression.cs: Remove reducer for binary expressions, it can not + be done this way. + + * const.cs: Put here the code that used to go into constant.cs + + * constant.cs: Put here the code for constants, this is a new base + class for Literals. + + * literal.cs: Make Literal derive from Constant. + +2001-12-09 Miguel de Icaza + + * statement.cs (Return.Emit): Report error 157 if the user + attempts to return from a finally block. + + (Return.Emit): Instead of emitting a return, jump to the end of + the function. + + * codegen.cs (EmitContext): ReturnValue, ReturnLabel: new + LocalBuilder to store the result of the function. ReturnLabel is + the target where we jump. + + +2001-12-09 Radek Doulik + + * cs-parser.jay: remember alias in current namespace + + * ecore.cs (SimpleName::DoResolve): use aliases for types or + namespaces + + * class.cs (LookupAlias): lookup alias in my_namespace + + * namespace.cs (UsingAlias): add alias, namespace_or_type pair to + aliases hashtable + (LookupAlias): lookup alias in this and if needed in parent + namespaces + +2001-12-08 Miguel de Icaza + + * support.cs: + + * rootcontext.cs: (ModuleBuilder) Made static, first step into + making things static. I need this to avoid passing the + TypeContainer when calling ParameterType. + + * support.cs (InternalParameters.ParameterType): Remove ugly hack + that did string manipulation to compute the type and then call + GetType. Use Parameter.ParameterType instead. + + * cs-tokenizer.cs: Consume the suffix for floating values. + + * expression.cs (ParameterReference): figure out whether this is a + reference parameter or not. Kill an extra variable by computing + the arg_idx during emission. + + * parameter.cs (Parameters.GetParameterInfo): New overloaded + function that returns whether a parameter is an out/ref value or not. + + (Parameter.ParameterType): The type of the parameter (base, + without ref/out applied). + + (Parameter.Resolve): Perform resolution here. + (Parameter.ExternalType): The full type (with ref/out applied). + + * statement.cs (Using.Emit, Using.EmitExpression): Implement + support for expressions on the using statement. + +2001-12-07 Miguel de Icaza + + * statement.cs (Using.EmitLocalVariableDecls): Split the + localvariable handling of the using statement. + + (Block.EmitMeta): Keep track of variable count across blocks. We + were reusing slots on separate branches of blocks. + + (Try.Emit): Emit the general code block, we were not emitting it. + + Check the type of the declaration to be an IDisposable or + something that can be implicity converted to it. + + Emit conversions if required. + + * ecore.cs (EmptyExpression): New utility class. + (Expression.ImplicitConversionExists): New utility function. + +2001-12-06 Miguel de Icaza + + * statement.cs (Using): Implement. + + * expression.cs (LocalVariableReference): Support read only variables. + + * statement.cs: Remove the explicit emit for the Leave opcode. + (VariableInfo): Add a readonly field. + +2001-12-05 Miguel de Icaza + + * ecore.cs (ConvCast): new class used to encapsulate the various + explicit integer conversions that works in both checked and + unchecked contexts. + + (Expression.ConvertNumericExplicit): Use new ConvCast class to + properly generate the overflow opcodes. + +2001-12-04 Miguel de Icaza + + * statement.cs: The correct type for the EmptyExpression is the + element_type, not the variable type. Ravi pointed this out. + +2001-12-04 Ravi Pratap + + * class.cs (Method::Define): Handle PInvoke methods specially + by using DefinePInvokeMethod instead of the usual one. + + * attribute.cs (DefinePInvokeMethod): Implement as this is what is called + above to do the task of extracting information and defining the method. + +2001-12-04 Ravi Pratap + + * expression.cs (ArrayCreation::EmitStaticInitializers): Get rid + of the condition for string type. + + (Emit): Move that here. + + (ArrayCreation::CheckIndices): Keep string literals in their expression + form. + + (EmitDynamicInitializers): Handle strings appropriately. + +2001-12-04 Miguel de Icaza + + * codegen.cs (EmitContext): Replace multiple variables with a + single pointer to the current Switch statement. + + * statement.cs (GotoDefault, Switch): Adjust to cleaned up + EmitContext. + +2001-12-03 Miguel de Icaza + + * statement.cs + + * statement.cs (GotoDefault), cs-parser.jay: Implement `goto + default'. + + (Foreach.Emit): Foreach on arrays was not setting + up the loop variables (for break/continue). + + (GotoCase): Semi-implented. + +2001-12-03 Ravi Pratap + + * attribute.cs (CheckAttribute): Handle system attributes by using + Attribute.GetAttributes to examine information we need. + + (GetValidPlaces): Same here. + + * class.cs (Method::Define): Catch invalid use of extern and abstract together. + + * typemanager.cs (dllimport_type): Core type for System.DllImportAttribute. + + * class.cs (Method.IsPinvoke): Used to determine if we are a PInvoke method. + + (Method::Define): Set appropriate flags if we have a DllImport attribute. + + (Method::Emit): Handle the case when we are a PInvoke method. + +2001-12-03 Miguel de Icaza + + * expression.cs: Use ResolveWithSimpleName on compound names. + +2001-12-02 Ravi Pratap + + * constant.cs (EmitConstant): Make sure we resolve the associated expression + before trying to reduce it. + + * typemanager.cs (RegisterConstant, LookupConstant): Implement. + + * constant.cs (LookupConstantValue): Implement. + + (EmitConstant): Use the above in emitting the constant. + + * expression.cs (MemberAccess::ResolveMemberAccess): Handle constants + that are user-defined by doing a LookupConstantValue on them. + + (SimpleName::DoResolve): When we have a FieldExpr, cope with constants + too, like above. + +2001-11-29 Miguel de Icaza + + * expression.cs (BaseAccess, BaseIndexer): Also split this out. + + (BaseAccess.DoResolve): Implement. + + (MemberAccess.DoResolve): Split this routine into a + ResolveMemberAccess routine that can be used independently + +2001-11-28 Miguel de Icaza + + * expression.cs (Probe, Is, As): Split Probe in two classes Is and + As that share bits of the implementation. Is returns a boolean, + while As returns the Type that is being probed. + +2001-12-01 Ravi Pratap + + * enum.cs (LookupEnumValue): Re-write various bits, return an object value + instead of a Literal - much easier. + + (EnumInTransit): Remove - utterly useless :-) + + (Populate): Re-write bits - remove duplicate code etc. The code is much neater now. + + * expression.cs (MemberLookup): Cope with user-defined enums when they are in transit. + + * enum.cs (LookupEnumValue): Auto-compute next values by going down the dependency + chain when we have no associated expression. + +2001-11-30 Ravi Pratap + + * constant.cs (Define): Use Location while reporting the errror. + + Also emit a warning when 'new' is used and there is no inherited + member to hide. + + * enum.cs (EnumInTransit): Used to tell if an enum type is in the process of being + populated. + + (LookupEnumValue): Implement to lookup an enum member's value and define it + if necessary. + + (Populate): Re-write accordingly to use the above routine. + +2001-11-27 Miguel de Icaza + + * expression.cs (This): Fix prototype for DoResolveLValue to + override the base class DoResolveLValue. + + * cs-parser.cs: Report errors cs574 and cs575 (destructor + declarations) + + * ecore.cs (FieldExpr.EmitAssign): Handle value types specially + (we need to load the address of the field here). This fixes + test-22. + + (FieldExpr.DoResolveLValue): Call the DoResolve + function to initialize the Instance expression. + + * statement.cs (Foreach.Emit): Fix the bug where we did not invoke + correctly the GetEnumerator operation on a value type. + + * cs-parser.jay: Add more simple parsing error catches. + + * statement.cs (Switch): Add support for string switches. + Handle null specially. + + * literal.cs (NullLiteral): Make NullLiteral objects singletons. + +2001-11-28 Ravi Pratap + + * cs-parser.jay (local_constant_declaration): Use declare_local_constant. + + (declare_local_constant): New helper function. + + * statement.cs (AddConstant): Keep a separate record of constants + + (IsConstant): Implement to determine if a variable is a constant. + + (GetConstantExpression): Implement. + + * expression.cs (LocalVariableReference): Handle the case when it is a constant. + + * statement.cs (IsVariableDefined): Re-write. + +2001-11-27 Ravi Pratap + + * class.cs (TypeContainer::FindMembers): Look for constants + in the case when we are looking for MemberTypes.Field + + * expression.cs (MemberAccess::DoResolve): Check that in the + case we are a FieldExpr and a Literal, we are not being accessed + by an instance reference. + + * cs-parser.jay (local_constant_declaration): Implement. + + (declaration_statement): Implement for constant declarations. + +2001-11-26 Miguel de Icaza + + * statement.cs (Switch): Catch double defaults. + + (Switch): More work on the switch() statement + implementation. It works for integral values now, need to finish + string support. + + +2001-11-24 Miguel de Icaza + + * ecore.cs (Expression.ConvertIntLiteral): New function to convert + integer literals into other integer literals. To be used by + switch. + +2001-11-24 Ravi Pratap + + * expression.cs (ArrayCreation): Get rid of ArrayExprs : we save + some memory. + + (EmitDynamicInitializers): Cope with the above since we extract data + directly from ArrayData now. + + (ExpectInitializers): Keep track of whether initializers are mandatory + or not. + + (Bounds): Make it a hashtable to prevent the same dimension being + recorded for every element in that dimension. + + (EmitDynamicInitializers): Fix bug which prevented the Set array method + from being found. + + Also fix bug which was causing the indices to be emitted in the reverse + order. + +2001-11-24 Miguel de Icaza + + * expression.cs (ArrayCreation): Implement the bits that Ravi left + unfinished. They do not work, because the underlying code is + sloppy. + +2001-11-22 Miguel de Icaza + + * cs-parser.jay: Remove bogus fixme. + + * statement.cs (Switch, SwitchSection, SwithLabel): Started work + on Switch statement. + +2001-11-23 Ravi Pratap + + * typemanager.cs (IsDelegateType, IsEnumType): Fix logic to determine + the same. + + * expression.cs (ArrayCreation::CheckIndices): Get rid of the require_constant + parameter. Apparently, any expression is allowed. + + (ValidateInitializers): Update accordingly. + + (CheckIndices): Fix some tricky bugs thanks to recursion. + + * delegate.cs (NewDelegate::DoResolve): Re-write large portions as + I was being completely brain-dead. + + (VerifyMethod, VerifyApplicability, VerifyDelegate): Make static + and re-write acordingly. + + (DelegateInvocation): Re-write accordingly. + + * expression.cs (ArrayCreation::Emit): Handle string initialization separately. + + (MakeByteBlob): Handle types more correctly. + + * expression.cs (ArrayCreation:Emit): Write preliminary code to do + initialization from expressions but it is incomplete because I am a complete + Dodo :-| + +2001-11-22 Miguel de Icaza + + * statement.cs (If.Emit): Fix a bug that generated incorrect code + on If. Basically, we have to return `true' (ie, we do return to + our caller) only if both branches of the if return. + + * expression.cs (Binary.Emit): LogicalOr and LogicalAnd are + short-circuit operators, handle them as short circuit operators. + + (Cast.DoResolve): Resolve type. + (Cast.Cast): Take an expression as the target type. + + * cs-parser.jay (cast_expression): Remove old hack that only + allowed a limited set of types to be handled. Now we take a + unary_expression and we resolve to a type during semantic + analysis. + + Use the grammar productions from Rhys to handle casts (this is + not complete like Rhys syntax yet, we fail to handle that corner + case that C# has regarding (-x), but we will get there. + +2001-11-22 Ravi Pratap + + * class.cs (EmitFieldInitializer): Take care of the case when we have a + field which is an array type. + + * cs-parser.jay (declare_local_variables): Support array initialization too. + + * typemanager.cs (MakeKey): Implement. + + (everywhere): Use the above appropriately. + + * cs-parser.jay (for_statement): Update for array initialization while + declaring variables. + + * ecore.cs : The error message was correct, it's the variable's names that + were misleading ;-) Make the code more readable. + + (MemberAccess::DoResolve): Fix the code which handles Enum literals to set + the correct type etc. + + (ConvertExplicit): Handle Enum types by examining the underlying type. + +2001-11-21 Ravi Pratap + + * parameter.cs (GetCallingConvention): Always return + CallingConventions.Standard for now. + +2001-11-22 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Update the values of `l' + and `r' after calling DoNumericPromotions. + + * ecore.cs: Fix error message (the types were in the wrong order). + + * statement.cs (Foreach.ProbeCollectionType): Need to pass + BindingFlags.Instance as well + + * ecore.cs (Expression.TryImplicitIntConversion): Wrap the result + implicit int literal conversion in an empty cast so that we + propagate the right type upstream. + + (UnboxCast): new class used to unbox value types. + (Expression.ConvertExplicit): Add explicit type conversions done + by unboxing. + + (Expression.ImplicitNumericConversion): Oops, forgot to test for + the target type before applying the implicit LongLiterals to ULong + literal cast. + +2001-11-21 Miguel de Icaza + + * cs-parser.jay (for_statement): Reworked the way For works: now + we declare manually any variables that are introduced in + for_initializer to solve the problem of having out-of-band code + emition (that is what got for broken). + + (declaration_statement): Perform the actual variable declaration + that used to be done in local_variable_declaration here. + + (local_variable_declaration): Do not declare anything, just pass + the information on a DictionaryEntry + +2001-11-20 Ravi Pratap + + * expression.cs (ArrayCreation::CheckIndices): The story continues :-) Complete + re-write of the logic to now make it recursive. + + (UpdateIndices): Re-write accordingly. + + Store element data in a separate ArrayData list in the above methods. + + (MakeByteBlob): Implement to dump the array data into a byte array. + +2001-11-19 Ravi Pratap + + * expression.cs (ArrayCreation): Factor out some code from ValidateInitializers + into CheckIndices. + + * constant.cs (Define): Implement. + + (EmitConstant): Re-write fully. + + Pass in location info. + + * class.cs (Populate, Emit): Call Constant::Define and Constant::EmitConstant + respectively. + + * cs-parser.jay (constant_declarator): Use VariableDeclaration instead of + DictionaryEntry since we need location info too. + + (constant_declaration): Update accordingly. + + * expression.cs (ArrayCreation): Make ValidateInitializers simpler by factoring + code into another method : UpdateIndices. + +2001-11-18 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Update to perform + some type checking etc. + +2001-11-17 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Implement + bits to provide dimension info if the user skips doing that. + + Update second constructor to store the rank correctly. + +2001-11-16 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Poke around + and try to implement. + + * ../errors/cs0150.cs : Add. + + * ../errors/cs0178.cs : Add. + +2001-11-16 Miguel de Icaza + + * statement.cs: Implement foreach on multi-dimensional arrays. + + * parameter.cs (Parameters.GetParameterByName): Also lookup the + name of the params argument. + + * expression.cs: Use EmitStoreOpcode to get the right opcode while + initializing the array. + + (ArrayAccess.EmitStoreOpcode): move the opcode generation here, so + we can use this elsewhere. + + * statement.cs: Finish implementation of foreach for single + dimension arrays. + + * cs-parser.jay: Use an out-of-band stack to pass information + around, I wonder why I need this. + + foreach_block: Make the new foreach_block the current_block. + + * parameter.cs (Parameters.GetEmptyReadOnlyParameters): New + function used to return a static Parameters structure. Used for + empty parameters, as those are created very frequently. + + * cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters + +2001-11-15 Ravi Pratap + + * interface.cs : Default modifier is private, not public. The + make verify test passes again. + +2001-11-15 Ravi Pratap + + * support.cs (ReflectionParameters): Fix logic to determine + whether the last parameter is a params one. Test 9 passes again. + + * delegate.cs (Populate): Register the builders we define with + RegisterParameterForBuilder. Test 19 passes again. + + * cs-parser.jay (property_declaration): Reference $6 instead + of $$ to get at the location. + + (indexer_declaration): Similar stuff. + + (attribute): Ditto. + + * class.cs (Property): Register parameters for the Get and Set methods + if they exist. Test 23 passes again. + + * expression.cs (ArrayCreation::Emit): Pass null for the method in the + call to EmitArguments as we are sure there aren't any params arguments. + Test 32 passes again. + + * suppor.cs (ParameterDesc, ParameterModifier): Fix trivial bug causing + IndexOutOfRangeException. + + * class.cs (Property::Define): Register property using TypeManager.RegisterProperty + Test 33 now passes again. + +2001-11-15 Miguel de Icaza + + * cs-parser.jay: Kill horrendous hack ($??? = lexer.Location) that + broke a bunch of things. Will have to come up with a better way + of tracking locations. + + * statement.cs: Implemented foreach for single dimension arrays. + +2001-11-09 Miguel de Icaza + + * enum.cs (Enum.Emit): Delay the lookup of loc until we run into + an error. This removes the lookup from the critical path. + + * cs-parser.jay: Removed use of temporary_loc, which is completely + broken. + +2001-11-14 Miguel de Icaza + + * support.cs (ReflectionParameters.ParameterModifier): Report + whether the argument is a PARAMS argument or not. + + * class.cs: Set the attribute `ParamArrayAttribute' on the + parameter argument. + + * typemanager.cs: Define param_array_type (ParamArrayAttribute) + and cons_param_array_attribute (ConstructorInfo for + ParamArrayAttribute)., + + * codegen.cs: Emit the return using the `Return' statement, that + way we can report the error correctly for missing return values. + + * class.cs (Method.Emit): Clean up. + + * expression.cs (Argument.Resolve): Take another argument: the + location where this argument is used. Notice that this is not + part of the "Argument" class as to reduce the size of the + structure (we know the approximate location anyways). + + Test if the argument is a variable-reference, if not, then + complain with a 206. + + (Argument.Emit): Emit addresses of variables. + + (Argument.FullDesc): Simplify. + + (Invocation.DoResolve): Update for Argument.Resolve. + + (ElementAccess.DoResolve): ditto. + + * delegate.cs (DelegateInvocation.Emit): Invocation of Invoke + method should be virtual, as this method is always virtual. + + (NewDelegate.DoResolve): Update for Argument.Resolve. + + * class.cs (ConstructorInitializer.DoResolve): ditto. + + * attribute.cs (Attribute.Resolve): ditto. + +2001-11-13 Miguel de Icaza + + * statement.cs (Foreach.Emit): Use EmitAssign instead of Store. + + * expression.cs (ParameterReference): Drop IStackStorage and implement + IAssignMethod instead. + + (LocalVariableReference): ditto. + + * ecore.cs (FieldExpr): Drop IStackStorage and implement + IAssignMethod instead. + +2001-11-13 Miguel de Icaza + + * parameter.cs, expression.cs, class.cs, ecore.cs: Made all + enumerations that are used in heavily used structures derive from + byte in a laughable and pathetic attempt to reduce memory usage. + This is the kind of pre-optimzations that you should not do at + home without adult supervision. + + * expression.cs (UnaryMutator): New class, used to handle ++ and + -- separatedly from the other unary operators. Cleans up the + code, and kills the ExpressionStatement dependency in Unary. + + (Unary): Removed `method' and `Arguments' from this class, making + it smaller, and moving it all to SimpleCall, so I can reuse this + code in other locations and avoid creating a lot of transient data + strucutres when not required. + + * cs-parser.jay: Adjust for new changes. + +2001-11-11 Miguel de Icaza + + * enum.cs (Enum.Populate): If there is a failure during + definition, return + + * cs-parser.jay (opt_enum_base): we used to catch type errors + here, but this is really incorrect. The type error should be + catched during semantic analysis. + +2001-12-11 Ravi Pratap + + * cs-parser.jay (operator_declarator, conversion_operator_declarator): Set + current_local_parameters as expected since I, in my stupidity, had forgotten + to do this :-) + + * attribute.cs (GetValidPlaces): Fix stupid bug. + + * class.cs (Method::Emit): Perform check on applicability of attributes. + + (Constructor::Emit): Ditto. + + (Field::Emit): Ditto. + + (Field.Location): Store location information. + + (Property, Event, Indexer, Operator): Ditto. + + * cs-parser.jay (field_declaration): Pass in location for each field. + + * ../errors/cs0592.cs : Add. + +2001-11-12 Ravi Pratap + + * typemanager.cs (attribute_usage_type): New static member for System.AttributeUsage. + + (InitCoreTypes): Update accordingly. + + (RegisterAttrType, LookupAttr): Implement. + + * attribute.cs (Attribute.Targets, AllowMultiple, Inherited): New fields to hold + info about the same. + + (Resolve): Update to populate the above as necessary. + + (Error592): Helper. + + (GetValidPlaces): Helper to the above. + + (CheckAttribute): Implement to perform validity of attributes on declarative elements. + + * class.cs (TypeContainer::Emit): Update attribute emission code to perform checking etc. + +2001-11-12 Ravi Pratap + + * attribute.cs (Attribute::Resolve): Expand to handle named arguments too. + + * ../errors/cs0617.cs : Add. + +2001-11-11 Ravi Pratap + + * enum.cs (Emit): Rename to Populate to be more consistent with what + we expect it to do and when exactly it is called. + + * class.cs, rootcontext.cs : Update accordingly. + + * typemanager.cs (RegisterField, GetValue): Workarounds for the fact that + FieldInfo.GetValue does not work on dynamic types ! S.R.E lameness strikes again ! + + * enum.cs (Populate): Register fields with TypeManager.RegisterField. + + * expression.cs (MemberAccess.DoResolve): Adjust code to obtain the value + of a fieldinfo using the above, when dealing with a FieldBuilder. + +2001-11-10 Ravi Pratap + + * ../errors/cs0031.cs : Add. + + * ../errors/cs1008.cs : Add. + + * ../errrors/cs0543.cs : Add. + + * enum.cs (DefineEnum): Check the underlying type and report an error if not a valid + enum type. + + (FindMembers): Implement. + + * typemanager.cs (FindMembers): Re-write to call the appropriate methods for + enums and delegates too. + + (enum_types): Rename to builder_to_enum. + + (delegate_types): Rename to builder_to_delegate. + + * delegate.cs (FindMembers): Implement. + +2001-11-09 Ravi Pratap + + * typemanager.cs (IsEnumType): Implement. + + * enum.cs (Emit): Re-write parts to account for the underlying type + better and perform checking etc. + + (GetNextDefaultValue): Helper to ensure we don't overshoot max value + of the underlying type. + + * literal.cs (GetValue methods everywhere): Perform bounds checking and return + value + + * enum.cs (error31): Helper to report error #31. + + * cs-parser.jay (enum_declaration): Store location of each member too. + + * enum.cs (member_to_location): New hashtable. + + (AddEnumMember): Update location hashtable. + + (Emit): Use the location of each member while reporting errors. + +2001-11-09 Miguel de Icaza + + * cs-parser.jay: A for_initializer if is a + local_variable_declaration really ammount to have an implicit + block with the variable declaration and no initializer for for. + + * statement.cs (For.Emit): Cope with null initializers. + + This fixes the infinite loop on for initializers. + +2001-11-08 Miguel de Icaza + + * enum.cs: More cleanup. + + * ecore.cs: Remove dead code. + + * class.cs (Property.Emit): More simplification. + (Event.Emit): ditto. + + Reworked to have less levels of indentation. + +2001-11-08 Ravi Pratap + + * class.cs (Property): Emit attributes. + + (Field): Ditto. + + (Event): Ditto. + + (Indexer): Ditto. + + (Operator): Ditto. + + * enum.cs (Emit): Ditto. + + * rootcontext.cs (ResolveTree, EmitCode, CloseTypes): Do the same for + Enums too. + + * class.cs (Field, Event, etc.): Move attribute generation into the + Emit method everywhere. + + * enum.cs (Enum): Revamp to use the same definition semantics as delegates so + we have a DefineEnum, CloseEnum etc. The previous way of doing things was not right + as we had no way of defining nested enums ! + + * rootcontext.cs : Adjust code accordingly. + + * typemanager.cs (AddEnumType): To keep track of enum types separately. + +2001-11-07 Ravi Pratap + + * expression.cs (EvalConstantExpression): Move into ecore.cs + + * enum.cs (Enum): Rename some members and make them public and readonly + according to our convention. + + * modifiers.cs (EnumAttr): Implement as we need to set only visibility flags, + nothing else. + + * enum.cs (Enum::Define): Use the above instead of TypeAttr. + + (Enum::Emit): Write a simple version for now which doesn't try to compute + expressions. I shall modify this to be more robust in just a while. + + * class.cs (TypeContainer::Emit): Make sure we include Enums too. + + (TypeContainer::CloseType): Create the Enum types too. + + * attribute.cs (Resolve): Use the new Reduce method instead of EvalConstantExpression. + + * expression.cs (EvalConstantExpression): Get rid of completely. + + * enum.cs (Enum::Emit): Use the new expression reducer. Implement assigning + user-defined values and other cases. + + (IsValidEnumLiteral): Helper function. + + * expression.cs (ExprClassfromMemberInfo): Modify to not do any literalizing + out there in the case we had a literal FieldExpr. + + (MemberAccess:DoResolve): Do the literalizing of the FieldExpr here. + + (Literalize): Revamp a bit to take two arguments. + + (EnumLiteral): New class which derives from Literal to wrap enum literals. + +2001-11-06 Ravi Pratap + + * cs-parser.jay (compilation_unit): Remove extra opt_attributes for now. + + * expression.cs (ArrayCreation::ValidateInitializers): Implement. + + (Resolve): Use the above to ensure we have proper initializers. + +2001-11-05 Ravi Pratap + + * expression.cs (Expression::EvalConstantExpression): New method to + evaluate constant expressions. + + * attribute.cs (Attribute::Resolve): Modify bits to use the above function. + +2001-11-07 Miguel de Icaza + + * expression.cs (ArrayCreation.Emit): Some bits to initialize data + in an array. + + (Binary.ResolveOperator): Handle operator != (object a, object b) + and operator == (object a, object b); + + (Binary.DoNumericPromotions): Indicate whether the numeric + promotion was possible. + + (ArrayAccess.DoResolve, ArrayAccess.Emit, ArrayAccess.EmitAssign): + Implement. + + Made the ArrayAccess implement interface IAssignMethod instead of + IStackStore as the order in which arguments are passed reflects + this. + + * assign.cs: Instead of using expr.ExprClass to select the way of + assinging, probe for the IStackStore/IAssignMethod interfaces. + + * typemanager.cs: Load InitializeArray definition. + + * rootcontext.cs (RootContext.MakeStaticData): Used to define + static data that can be used to initialize arrays. + +2001-11-05 Miguel de Icaza + + * expression.cs: Handle operator== and operator!= for booleans. + + (Conditioal.Reduce): Implement reducer for the ?: operator. + + (Conditional.Resolve): Implement dead code elimination. + + (Binary.Resolve): Catch string literals and return a new + concatenated string. + + (Unary.Reduce): Implement reduction of unary expressions. + + * ecore.cs: Split out the expression core handling here. + + (Expression.Reduce): New method used to perform constant folding + and CSE. This is needed to support constant-expressions. + + * statement.cs (Statement.EmitBoolExpression): Pass true and false + targets, and optimize for !x. + +2001-11-04 Ravi Pratap + + * attribute.cs (Attribute::Resolve): Implement guts. Note that resolution + of an attribute gives us a CustomAttributeBuilder which we use accordingly to + set custom atttributes. + + * literal.cs (Literal::GetValue): New abstract method to return the actual + value of the literal, cast as an object. + + (*Literal): Implement GetValue method. + + * cs-parser.jay (positional_argument_list, named_argument_list): Add not just plain + expressions to the arraylist but objects of type Argument. + + * class.cs (TypeContainer::Emit): Emit our attributes too. + + (Method::Emit, Constructor::Emit): Ditto. + + * cs-parser.jay (constructor_declaration): Set attributes too, which we seemed + to be ignoring earlier. + +2001-11-03 Ravi Pratap + + * attribute.cs (AttributeSection::Define): Implement to do the business + of constructing a CustomAttributeBuilder. + + (Attribute): New trivial class. Increases readability of code. + + * cs-parser.jay : Update accordingly. + + (positional_argument_list, named_argument_list, named_argument): New rules + + (attribute_arguments): Use the above so that we are more correct. + +2001-11-02 Ravi Pratap + + * expression.cs (Invocation::IsParamsMethodApplicable): Implement + to perform all checks for a method with a params parameter. + + (Invocation::OverloadResolve): Update to use the above method and therefore + cope correctly with params method invocations. + + * support.cs (InternalParameters::ParameterDesc): Provide a desc for + params too. + + * class.cs (ConstructorInitializer::Resolve): Make sure we look for Non-public + constructors in our parent too because we can't afford to miss out on + protected ones ;-) + + * attribute.cs (AttributeSection): New name for the class Attribute + + Other trivial changes to improve readability. + + * cs-parser.jay (opt_attributes, attribute_section etc.): Modify to + use the new class names. + +2001-11-01 Ravi Pratap + + * class.cs (Method::Define): Complete definition for params types too + + (Indexer::Define): Ditto. + + * support.cs (InternalParameters::ParameterType, ParameterDesc, ParameterModifier): + Cope everywhere with a request for info about the array parameter. + +2001-11-01 Ravi Pratap + + * tree.cs (RecordNamespace): Fix up to check for the correct key. + + * cs-parser.jay (GetQualifiedIdentifier): New Helper method used in + local_variable_type to extract the string corresponding to the type. + + (local_variable_type): Fixup the action to use the new helper method. + + * codegen.cs : Get rid of RefOrOutParameter, it's not the right way to + go. + + * expression.cs : Clean out code which uses the above. + +2001-10-31 Ravi Pratap + + * typemanager.cs (RegisterMethod): Check if we already have an existing key + and bale out if necessary by returning a false. + + (RegisterProperty): Ditto. + + * class.cs (everywhere): Check the return value from TypeManager.RegisterMethod + and print out appropriate error messages. + + * interface.cs (everywhere): Ditto. + + * cs-parser.jay (property_declaration, event_declaration, indexer_declaration): Pass + location to constructor. + + * class.cs (Property, Event, Indexer): Update accordingly. + + * ../errors/cs111.cs : Added. + + * expression.cs (Invocation::IsApplicable): New static method to determine applicability + of a method, as laid down by the spec. + + (Invocation::OverloadResolve): Use the above method. + +2001-10-31 Ravi Pratap + + * support.cs (InternalParameters): Get rid of crap taking in duplicate info. We + now take a TypeContainer and a Parameters object. + + (ParameterData): Modify return type of ParameterModifier method to be + Parameter.Modifier and not a string. + + (ReflectionParameters, InternalParameters): Update accordingly. + + * expression.cs (Argument::GetParameterModifier): Same here. + + * support.cs (InternalParameters::ParameterType): Find a better way of determining + if we are a ref/out parameter. Actually, the type shouldn't be holding the '&' + symbol in it at all so maybe this is only for now. + +2001-10-30 Ravi Pratap + + * support.cs (InternalParameters): Constructor now takes an extra argument + which is the actual Parameters class. + + (ParameterDesc): Update to provide info on ref/out modifiers. + + * class.cs (everywhere): Update call to InternalParameters to pass in + the second argument too. + + * support.cs (ParameterData): Add ParameterModifier, which is a method + to return the modifier info [ref/out etc] + + (InternalParameters, ReflectionParameters): Implement the above. + + * expression.cs (Argument::ParameterModifier): Similar function to return + info about the argument's modifiers. + + (Invocation::OverloadResolve): Update to take into account matching modifiers + too. + + * class.cs (Indexer::Define): Actually define a Parameter object and put it onto + a new SetFormalParameters object which we pass to InternalParameters. + +2001-10-30 Ravi Pratap + + * expression.cs (NewArray): Merge into the ArrayCreation class. + +2001-10-29 Ravi Pratap + + * expression.cs (NewArray): Merge classes NewBuiltinArray and + NewUserdefinedArray into one as there wasn't much of a use in having + two separate ones. + + * expression.cs (Argument): Change field's name to ArgType from Type. + + (Type): New readonly property which returns the proper type, taking into + account ref/out modifiers. + + (everywhere): Adjust code accordingly for the above. + + * codegen.cs (EmitContext.RefOrOutParameter): New field to determine + whether we are emitting for a ref or out parameter. + + * expression.cs (Argument::Emit): Use the above field to set the state. + + (LocalVariableReference::Emit): Update to honour the flag and emit the + right stuff. + + * parameter.cs (Attributes): Set the correct flags for ref parameters. + + * expression.cs (Argument::FullDesc): New function to provide a full desc. + + * support.cs (ParameterData): Add method ParameterDesc to the interface. + + (ReflectionParameters, InternalParameters): Implement the above method. + + * expression.cs (Invocation::OverloadResolve): Use the new desc methods in + reporting errors. + + (Invocation::FullMethodDesc): Ditto. + +2001-10-29 Miguel de Icaza + + * cs-parser.jay: Add extra production for the second form of array + creation. + + * expression.cs (ArrayCreation): Update to reflect the above + change. + + * Small changes to prepare for Array initialization. + +2001-10-28 Miguel de Icaza + + * typemanager.cs (ImplementsInterface): interface might be null; + Deal with this problem; + + Also, we do store negative hits on the cache (null values), so use + this instead of calling t.GetInterfaces on the type everytime. + +2001-10-28 Ravi Pratap + + * typemanager.cs (IsBuiltinType): New method to help determine the same. + + * expression.cs (New::DoResolve): Get rid of array creation code and instead + split functionality out into different classes. + + (New::FormArrayType): Move into NewBuiltinArray. + + (Invocation::EmitArguments): Get rid of the MethodBase argument. Appears + quite useless. + + (NewBuiltinArray): New class to handle creation of built-in arrays. + + (NewBuiltinArray::DoResolve): Implement guts of array creation. Also take into + account creation of one-dimensional arrays. + + (::Emit): Implement to use Newarr and Newobj opcodes accordingly. + + (NewUserdefinedArray::DoResolve): Implement. + + * cs-parser.jay (local_variable_type): Fix up to add the rank to the variable too. + + * typemanager.cs (AddModule): Used to add a ModuleBuilder to the list of modules + we maintain inside the TypeManager. This is necessary to perform lookups on the + module builder. + + (LookupType): Update to perform GetType on the module builders too. + + * driver.cs (Driver): Add the ModuleBuilder to the list maintained by the TypeManager. + + * exprssion.cs (NewUserdefinedArray::Emit): Implement. + +2001-10-23 Ravi Pratap + + * expression.cs (New::DoResolve): Implement guts of array creation. + + (New::FormLookupType): Rename to FormArrayType and modify ever so slightly. + +2001-10-27 Miguel de Icaza + + * expression.cs: Fix bug I introduced lsat night that broke + Delegates. + + (Expression.Resolve): Report a 246 error (can not resolve name) + if we find a SimpleName in the stream. + + (Expression.ResolveLValue): Ditto. + + (Expression.ResolveWithSimpleName): This function is a variant of + ResolveName, this one allows SimpleNames to be returned without a + warning. The only consumer of SimpleNames is MemberAccess + +2001-10-26 Miguel de Icaza + + * expression.cs (Invocation::DoResolve): Catch SimpleNames that + might arrive here. I have my doubts that this is correct. + + * statement.cs (Lock): Implement lock statement. + + * cs-parser.jay: Small fixes to support `lock' and `using' + + * cs-tokenizer.cs: Remove extra space + + * driver.cs: New flag --checked, allows to turn on integer math + checking. + + * typemanger.cs: Load methodinfos for Threading.Monitor.Enter and + Threading.Monitor.Exit + +2001-10-23 Miguel de Icaza + + * expression.cs (IndexerAccess::DoResolveLValue): Set the + Expression Class to be IndexerAccess. + + Notice that Indexer::DoResolve sets the eclass to Value. + +2001-10-22 Miguel de Icaza + + * class.cs (TypeContainer::Emit): Emit code for indexers. + + * assign.cs (IAssignMethod): New interface implemented by Indexers + and Properties for handling assignment. + + (Assign::Emit): Simplify and reuse code. + + * expression.cs (IndexerAccess, PropertyExpr): Implement + IAssignMethod, clean up old code. + +2001-10-22 Ravi Pratap + + * typemanager.cs (ImplementsInterface): New method to determine if a type + implements a given interface. Provides a nice cache too. + + * expression.cs (ImplicitReferenceConversion): Update checks to use the above + method. + + (ConvertReferenceExplicit): Ditto. + + * delegate.cs (Delegate::Populate): Update to define the parameters on the + various methods, with correct names etc. + + * class.cs (Operator::OpType): New members Operator.UnaryPlus and + Operator.UnaryNegation. + + * cs-parser.jay (operator_declarator): Be a little clever in the case where + we have a unary plus or minus operator. + + * expression.cs (Unary): Rename memebers of Operator enum to UnaryPlus and + UnaryMinus. + + * everywhere : update accordingly. + + * everywhere : Change Negate and BitComplement to LogicalNot and OnesComplement + respectively. + + * class.cs (Method::Define): For the case where we are implementing a method + inherited from an interface, we need to set the MethodAttributes.Final flag too. + Also set MethodAttributes.NewSlot and MethodAttributes.HideBySig. + +2001-10-21 Ravi Pratap + + * interface.cs (FindMembers): Implement to work around S.R.E + lameness. + + * typemanager.cs (IsInterfaceType): Implement. + + (FindMembers): Update to handle interface types too. + + * expression.cs (ImplicitReferenceConversion): Re-write bits which + use IsAssignableFrom as that is not correct - it doesn't work. + + * delegate.cs (DelegateInvocation): Derive from ExpressionStatement + and accordingly override EmitStatement. + + * expression.cs (ConvertReferenceExplicit): Re-write similary, this time + using the correct logic :-) + +2001-10-19 Ravi Pratap + + * ../errors/cs-11.cs : Add to demonstrate error -11 + +2001-10-17 Miguel de Icaza + + * assign.cs (Assign::Resolve): Resolve right hand side first, and + then pass this as a hint to ResolveLValue. + + * expression.cs (FieldExpr): Add Location information + + (FieldExpr::LValueResolve): Report assignment to readonly + variable. + + (Expression::ExprClassFromMemberInfo): Pass location information. + + (Expression::ResolveLValue): Add new method that resolves an + LValue. + + (Expression::DoResolveLValue): Default invocation calls + DoResolve. + + (Indexers): New class used to keep track of indexers in a given + Type. + + (IStackStore): Renamed from LValue, as it did not really describe + what this did. Also ResolveLValue is gone from this interface and + now is part of Expression. + + (ElementAccess): Depending on the element access type + + * typemanager.cs: Add `indexer_name_type' as a Core type + (System.Runtime.CompilerServices.IndexerNameAttribute) + + * statement.cs (Goto): Take a location. + +2001-10-18 Ravi Pratap + + * delegate.cs (Delegate::VerifyDelegate): New method to verify + if two delegates are compatible. + + (NewDelegate::DoResolve): Update to take care of the case when + we instantiate a delegate from another delegate. + + * typemanager.cs (FindMembers): Don't even try to look up members + of Delegate types for now. + +2001-10-18 Ravi Pratap + + * delegate.cs (NewDelegate): New class to take care of delegate + instantiation. + + * expression.cs (New): Split the delegate related code out into + the NewDelegate class. + + * delegate.cs (DelegateInvocation): New class to handle delegate + invocation. + + * expression.cs (Invocation): Split out delegate related code into + the DelegateInvocation class. + +2001-10-17 Ravi Pratap + + * expression.cs (New::DoResolve): Implement delegate creation fully + and according to the spec. + + (New::DoEmit): Update to handle delegates differently. + + (Invocation::FullMethodDesc): Fix major stupid bug thanks to me + because of which we were printing out arguments in reverse order ! + + * delegate.cs (VerifyMethod): Implement to check if the given method + matches the delegate. + + (FullDelegateDesc): Implement. + + (VerifyApplicability): Implement. + + * expression.cs (Invocation::DoResolve): Update to accordingly handle + delegate invocations too. + + (Invocation::Emit): Ditto. + + * ../errors/cs1593.cs : Added. + + * ../errors/cs1594.cs : Added. + + * delegate.cs (InstanceExpression, TargetMethod): New properties. + +2001-10-16 Ravi Pratap + + * typemanager.cs (intptr_type): Core type for System.IntPtr + + (InitCoreTypes): Update for the same. + + (iasyncresult_type, asynccallback_type): Ditto. + + * delegate.cs (Populate): Fix to use System.Intptr as it is indeed + correct. + + * typemanager.cs (AddDelegateType): Store a pointer to the Delegate class + too. + + * delegate.cs (ConstructorBuilder, InvokeBuilder, ...): New members to hold + the builders for the 4 members of a delegate type :-) + + (Populate): Define the BeginInvoke and EndInvoke methods on the delegate + type. + + * expression.cs (New::DoResolve): Implement guts for delegate creation. + + * ../errors/errors.txt : Update for an error (-11) which only we catch :-) + +2001-10-15 Miguel de Icaza + + * statement.cs (Break::Emit): Implement. + (Continue::Emit): Implement. + + (For::Emit): Track old being/end loops; Set Begin loop, ack end loop + (While::Emit): Track old being/end loops; Set Begin loop, ack end loop + (Do::Emit): Track old being/end loops; Set Begin loop, ack end loop + (Foreach::Emit): Track old being/end loops; Set Begin loop, ack + end loop + + * codegen.cs (EmitContext::LoopEnd, EmitContext::LoopBegin): New + properties that track the label for the current loop (begin of the + loop and end of the loop). + +2001-10-15 Ravi Pratap + + * delegate.cs (Emit): Get rid of it as there doesn't seem to be any ostensible + use of emitting anything at all. + + * class.cs, rootcontext.cs : Get rid of calls to the same. + + * delegate.cs (DefineDelegate): Make sure the class we define is also sealed. + + (Populate): Define the constructor correctly and set the implementation + attributes. + + * typemanager.cs (delegate_types): New hashtable to hold delegates that + have been defined. + + (AddDelegateType): Implement. + + (IsDelegateType): Implement helper method. + + * delegate.cs (DefineDelegate): Use AddDelegateType instead of AddUserType. + + * expression.cs (New::DoResolve): Check if we are trying to instantiate a delegate type + and accordingly handle it. + + * delegate.cs (Populate): Take TypeContainer argument. + Implement bits to define the Invoke method. However, I still haven't figured out + how to take care of the native int bit :-( + + * cs-parser.jay (delegate_declaration): Fixed the bug that I had introduced :-) + Qualify the name of the delegate, not its return type ! + + * expression.cs (ImplicitReferenceConversion): Implement guts of implicit array + conversion. + + (StandardConversionExists): Checking for array types turns out to be recursive. + + (ConvertReferenceExplicit): Implement array conversion. + + (ExplicitReferenceConversionExists): New method to determine precisely that :-) + +2001-10-12 Ravi Pratap + + * cs-parser.jay (delegate_declaration): Store the fully qualified + name as it is a type declaration. + + * delegate.cs (ReturnType, Name): Rename members to these. Make them + readonly. + + (DefineDelegate): Renamed from Define. Does the same thing essentially, + as TypeContainer::DefineType. + + (Populate): Method in which all the definition of the various methods (Invoke) + etc is done. + + (Emit): Emit any code, if necessary. I am not sure about this really, but let's + see. + + (CloseDelegate): Finally creates the delegate. + + * class.cs (TypeContainer::DefineType): Update to define delegates. + (Populate, Emit and CloseType): Do the same thing here too. + + * rootcontext.cs (ResolveTree, PopulateTypes, EmitCode, CloseTypes): Include + delegates in all these operations. + +2001-10-14 Miguel de Icaza + + * expression.cs: LocalTemporary: a new expression used to + reference a temporary that has been created. + + * assign.cs: Handle PropertyAccess back here, so that we can + provide the proper semantic access to properties. + + * expression.cs (Expression::ConvertReferenceExplicit): Implement + a few more explicit conversions. + + * modifiers.cs: `NEW' modifier maps to HideBySig. + + * expression.cs (PropertyExpr): Make this into an + ExpressionStatement, and support the EmitStatement code path. + + Perform get/set error checking, clean up the interface. + + * assign.cs: recognize PropertyExprs as targets, and if so, turn + them into toplevel access objects. + +2001-10-12 Miguel de Icaza + + * expression.cs: PropertyExpr::PropertyExpr: use work around the + SRE. + + * typemanager.cs: Keep track here of our PropertyBuilders again to + work around lameness in SRE. + +2001-10-11 Miguel de Icaza + + * expression.cs (LValue::LValueResolve): New method in the + interface, used to perform a second resolution pass for LValues. + + (This::DoResolve): Catch the use of this in static methods. + + (This::LValueResolve): Implement. + + (This::Store): Remove warning, assigning to `this' in structures + is + + (Invocation::Emit): Deal with invocation of + methods on value types. We need to pass the address to structure + methods rather than the object itself. (The equivalent code to + emit "this" for structures leaves the entire structure on the + stack instead of a pointer to it). + + (ParameterReference::DoResolve): Compute the real index for the + argument based on whether the method takes or not a `this' pointer + (ie, the method is static). + + * codegen.cs (EmitContext::GetTemporaryStorage): Used to store + value types returned from functions when we need to invoke a + method on the sturcture. + + +2001-10-11 Ravi Pratap + + * class.cs (TypeContainer::DefineType): Method to actually do the business of + defining the type in the Modulebuilder or Typebuilder. This is to take + care of nested types which need to be defined on the TypeBuilder using + DefineNestedMethod. + + (TypeContainer::GetClassBases): Implement. Essentially the code from the + methods in RootContext, only ported to be part of TypeContainer. + + (TypeContainer::GetInterfaceOrClass): Ditto. + + (TypeContainer::LookupInterfaceOrClass, ::MakeFQN): Ditto. + + * interface.cs (Interface::DefineInterface): New method. Does exactly + what RootContext.CreateInterface did earlier, only it takes care of nested types + too. + + (Interface::GetInterfaces): Move from RootContext here and port. + + (Interface::GetInterfaceByName): Same here. + + * rootcontext.cs (ResolveTree): Re-write. + + (PopulateTypes): Re-write. + + * class.cs (TypeContainer::Populate): Populate nested types too. + (TypeContainer::Emit): Emit nested members too. + + * typemanager.cs (AddUserType): Do not make use of the FullName property, + instead just use the name argument passed in as it is already fully + qualified. + + (FindMembers): Check in the Builders to TypeContainer mapping instead of the name + to TypeContainer mapping to see if a type is user-defined. + + * class.cs (TypeContainer::CloseType): Implement. + + (TypeContainer::DefineDefaultConstructor): Use Basename, not Name while creating + the default constructor. + + (TypeContainer::Populate): Fix minor bug which led to creating default constructors + twice. + + (Constructor::IsDefault): Fix up logic to determine if it is the default constructor + + * interface.cs (CloseType): Create the type here. + + * rootcontext.cs (CloseTypes): Re-write to recursively close types by running through + the hierarchy. + + Remove all the methods which are now in TypeContainer. + +2001-10-10 Ravi Pratap + + * delegate.cs (Define): Re-write bits to define the delegate + correctly. + +2001-10-10 Miguel de Icaza + + * makefile: Renamed the compiler to `mcs.exe' instead of compiler.exe + + * expression.cs (ImplicitReferenceConversion): handle null as well + as a source to convert to any reference type. + + * statement.cs (Return): Perform any implicit conversions to + expected return type. + + Validate use of return statement. + + * codegen.cs (EmitContext): Pass the expected return type here. + + * class.cs (Method, Constructor, Property): Pass expected return + type to EmitContext. + +2001-10-09 Miguel de Icaza + + * expression.cs: Make DoResolve take an EmitContext instead of a + TypeContainer. + + Replaced `l' and `location' for `loc', for consistency. + + (Error, Warning): Remove unneeded Tc argument. + + * assign.cs, literal.cs, constant.cs: Update to new calling + convention. + + * codegen.cs: EmitContext now contains a flag indicating whether + code is being generated in a static method or not. + + * cs-parser.jay: DecomposeQI, new function that replaces the old + QualifiedIdentifier. Now we always decompose the assembled + strings from qualified_identifier productions into a group of + memberaccesses. + +2001-10-08 Miguel de Icaza + + * rootcontext.cs: Deal with field-less struct types correctly now + by passing the size option to Define Type. + + * class.cs: Removed hack that created one static field. + +2001-10-07 Miguel de Icaza + + * statement.cs: Moved most of the code generation here. + +2001-10-09 Ravi Pratap + + * expression.cs (New::DoResolve): Revert changes for array creation, doesn't + seem very right. + + (ElementAccess): Remove useless bits for now - keep checks as the spec + says. + +2001-10-08 Ravi Pratap + + * expression.cs (ElementAccess::DoResolve): Remove my crap code + and start performing checks according to the spec. + +2001-10-07 Ravi Pratap + + * cs-parser.jay (type_suffix*): Remove - they are redundant. Use + rank_specifiers instead. + + (rank_specifiers): Change the order in which the rank specifiers are stored + + (local_variable_declaration): Use opt_rank_specifier instead of type_suffixes. + + * expression.cs (ElementAccess): Implement the LValue interface too. + +2001-10-06 Ravi Pratap + + * expression.cs (ConvertExplicitStandard): Add. Same as ConvertExplicit + except that user defined conversions are not included. + + (UserDefinedConversion): Update to use the ConvertExplicitStandard to + perform the conversion of the return type, if necessary. + + (New::DoResolve): Check whether we are creating an array or an object + and accordingly do the needful. + + (New::Emit): Same here. + + (New::DoResolve): Implement guts of array creation. + + (New::FormLookupType): Helper function. + +2001-10-07 Miguel de Icaza + + * codegen.cs: Removed most of the code generation here, and move the + corresponding code generation bits to the statement classes. + + Added support for try/catch/finalize and throw. + + * cs-parser.jay: Added support for try/catch/finalize. + + * class.cs: Catch static methods having the flags override, + virtual or abstract. + + * expression.cs (UserCast): This user cast was not really doing + what it was supposed to do. Which is to be born in fully resolved + state. Parts of the resolution were being performed at Emit time! + + Fixed this code. + +2001-10-05 Miguel de Icaza + + * expression.cs: Implicity convert the result from UserCast. + +2001-10-05 Ravi Pratap + + * expression.cs (Expression::FindMostEncompassingType): Fix bug which + prevented it from working correctly. + + (ConvertExplicit): Make the first try, a call to ConvertImplicitStandard, not + merely ConvertImplicit. + +2001-10-05 Miguel de Icaza + + * typemanager.cs: Make the LookupTypeContainer function static, + and not per-instance. + + * class.cs: Make static FindMembers (the one that takes a Type + argument). + + * codegen.cs: Add EmitForeach here. + + * cs-parser.jay: Make foreach a toplevel object instead of the + inline expansion, as we need to perform semantic analysis on it. + +2001-10-05 Ravi Pratap + + * expression.cs (Expression::ImplicitUserConversion): Rename to + UserDefinedConversion. + + (Expression::UserDefinedConversion): Take an extra argument specifying + whether we look for explicit user conversions too. + + (Expression::ImplicitUserConversion): Make it a call to UserDefinedConversion. + + (UserDefinedConversion): Incorporate support for user defined explicit conversions. + + (ExplicitUserConversion): Make it a call to UserDefinedConversion + with the appropriate arguments. + + * cs-parser.jay (cast_expression): Record location too. + + * expression.cs (Cast): Record location info. + + (Expression::ConvertExplicit): Take location argument. + + (UserImplicitCast): Change name to UserCast. Take an extra constructor argument + to determine if we are doing explicit conversions. + + (UserCast::Emit): Update accordingly. + + (Expression::ConvertExplicit): Report an error if everything fails. + + * ../errors/cs0030.cs : Add. + +2001-10-04 Miguel de Icaza + + * modifiers.cs: If the ABSTRACT keyword is present, also set the + virtual and newslot bits. + + * class.cs (TypeContainer::RegisterRequiredImplementations): + Record methods we need. + + (TypeContainer::MakeKey): Helper function to make keys for + MethodBases, since the Methodbase key is useless. + + (TypeContainer::Populate): Call RegisterRequiredImplementations + before defining the methods. + + Create a mapping for method_builders_to_methods ahead of time + instead of inside a tight loop. + + (::RequireMethods): Accept an object as the data to set into the + hashtable so we can report interface vs abstract method mismatch. + +2001-10-03 Miguel de Icaza + + * report.cs: Make all of it static. + + * rootcontext.cs: Drop object_type and value_type computations, as + we have those in the TypeManager anyways. + + Drop report instance variable too, now it is a global. + + * driver.cs: Use try/catch on command line handling. + + Add --probe option to debug the error reporting system with a test + suite. + + * report.cs: Add support for exiting program when a probe + condition is reached. + +2001-10-03 Ravi Pratap + + * expression.cs (Binary::DoNumericPromotions): Fix the case when + we do a forcible conversion regardless of type, to check if + ForceConversion returns a null. + + (Binary::error19): Use location to report error. + + (Unary::error23): Use location here too. + + * ../errors/cs0019.cs : Check in. + + * ../errors/cs0023.cs : Check in. + + * expression.cs (Expression.MemberLookup): Return null for a rather esoteric + case of a non-null MethodInfo object with a length of 0 ! + + (Binary::ResolveOperator): Flag error if overload resolution fails to find + an applicable member - according to the spec :-) + Also fix logic to find members in base types. + + (Unary::ResolveOperator): Same here. + + (Unary::report23): Change name to error23 and make first argument a TypeContainer + as I was getting thoroughly confused between this and error19 :-) + + * expression.cs (Expression::ImplicitUserConversion): Re-write fully + (::FindMostEncompassedType): Implement. + (::FindMostEncompassingType): Implement. + (::StandardConversionExists): Implement. + + (UserImplicitCast): Re-vamp. We now need info about most specific + source and target types so that we can do the necessary conversions. + + (Invocation::MakeUnionSet): Completely re-write to make sure we form a proper + mathematical union with no duplicates. + +2001-10-03 Miguel de Icaza + + * rootcontext.cs (RootContext::PopulateTypes): Populate containers + in order from base classes to child classes, so that we can in + child classes look up in our parent for method names and + attributes (required for handling abstract, virtual, new, override + constructs: we need to instrospect our base class, and if we dont + populate the classes in order, the introspection might be + incorrect. For example, a method could query its parent before + the parent has any methods and would determine that the parent has + no abstract methods (while it could have had them)). + + (RootContext::CreateType): Record the order in which we define the + classes. + +2001-10-02 Miguel de Icaza + + * class.cs (TypeContainer::Populate): Also method definitions can + fail now, keep track of this. + + (TypeContainer::FindMembers): Implement support for + DeclaredOnly/noDeclaredOnly flag. + + (Constructor::Emit) Return the ConstructorBuilder. + + (Method::Emit) Return the MethodBuilder. + Check for abstract or virtual methods to be public. + + * rootcontext.cs (RootContext::CreateType): Register all the + abstract methods required for the class to be complete and the + interface methods that must be implemented. + + * cs-parser.jay: Report error 501 (method requires body if it is + not marked abstract or extern). + + * expression.cs (TypeOf::Emit): Implement. + + * typemanager.cs: runtime_handle_type, new global type. + + * class.cs (Property::Emit): Generate code for properties. + +2001-10-02 Ravi Pratap + + * expression.cs (Unary::ResolveOperator): Find operators on base type + too - we now conform exactly to the spec. + + (Binary::ResolveOperator): Same here. + + * class.cs (Operator::Define): Fix minor quirk in the tests. + + * ../errors/cs0215.cs : Added. + + * ../errors/cs0556.cs : Added. + + * ../errors/cs0555.cs : Added. + +2001-10-01 Miguel de Icaza + + * cs-tokenizer.cs: Reimplemented Location to be a struct with a + single integer which is really efficient + +2001-10-01 Ravi Pratap + + * expression.cs (Expression::ImplicitUserConversion): Use location + even in the case when we are examining True operators. + + * class.cs (Operator::Define): Perform extensive checks to conform + with the rules for operator overloading in the spec. + + * expression.cs (Expression::ImplicitReferenceConversion): Implement + some of the other conversions mentioned in the spec. + + * typemanager.cs (array_type): New static member for the System.Array built-in + type. + + (cloneable_interface): For System.ICloneable interface. + + * driver.cs (Driver::Driver): Initialize TypeManager's core types even before + we start resolving the tree and populating types. + + * ../errors/errors.txt : Update for error numbers -7, -8, -9, -10 + +2001-10-01 Miguel de Icaza + + * expression.cs (Expression::ExprClassFromMemberInfo, + Expression::Literalize): Create literal expressions from + FieldInfos which are literals. + + (ConvertNumericExplicit, ImplicitNumericConversion): Fix a few + type casts, because they were wrong. The test suite in tests + caught these ones. + + (ImplicitNumericConversion): ushort to ulong requires a widening + cast. + + Int32 constant to long requires widening cast as well. + + * literal.cs (LongLiteral::EmitLong): Do not generate i4 constants + for integers because the type on the stack is not i4. + +2001-09-30 Miguel de Icaza + + * expression.cs (report118): require location argument. + + * parameter.cs: Do not dereference potential null value. + + * class.cs: Catch methods that lack the `new' keyword when + overriding a name. Report warnings when `new' is used without + anything being there to override. + + * modifiers.cs: Handle `NEW' as MethodAttributes.NewSlot. + + * class.cs: Only add constructor to hashtable if it is non-null + (as now constructors can fail on define). + + (TypeManager, Class, Struct): Take location arguments. + + Catch field instance initialization in structs as errors. + + accepting_filter: a new filter for FindMembers that is static so + that we dont create an instance per invocation. + + (Constructor::Define): Catch errors where a struct constructor is + parameterless + + * cs-parser.jay: Pass location information for various new + constructs. + + * delegate.cs (Delegate): take a location argument. + + * driver.cs: Do not call EmitCode if there were problesm in the + Definition of the types, as many Builders wont be there. + + * decl.cs (Decl::Decl): Require a location argument. + + * cs-tokenizer.cs: Handle properly hex constants that can not fit + into integers, and find the most appropiate integer for it. + + * literal.cs: Implement ULongLiteral. + + * rootcontext.cs: Provide better information about the location of + failure when CreateType fails. + +2001-09-29 Miguel de Icaza + + * rootcontext.cs (RootContext::PopulateTypes): Populates structs + as well. + + * expression.cs (Binary::CheckShiftArguments): Add missing type + computation. + (Binary::ResolveOperator): Add type to the logical and and logical + or, Bitwise And/Or and Exclusive Or code paths, it was missing + before. + + (Binary::DoNumericPromotions): In the case where either argument + is ulong (and most signed types combined with ulong cause an + error) perform implicit integer constant conversions as well. + +2001-09-28 Miguel de Icaza + + * expression.cs (UserImplicitCast): Method should always be + non-null. + (Invocation::BetterConversion): Simplified test for IntLiteral. + + (Expression::ImplicitNumericConversion): Split this routine out. + Put the code that performs implicit constant integer conversions + here. + + (Expression::Resolve): Become a wrapper around DoResolve so we can + check eclass and type being set after resolve. + + (Invocation::Badness): Remove this dead function + + (Binary::ResolveOperator): Do not compute the expensive argumnets + unless we have a union for it. + + (Probe::Emit): Is needs to do an isinst and then + compare against null. + + (::CanConvert): Added Location argument. If the Location argument + is null (Location.Null), then we do not report errors. This is + used by the `probe' mechanism of the Explicit conversion. We do + not want to generate an error for something that the user + explicitly requested to be casted. But the pipeline for an + explicit cast first tests for potential implicit casts. + + So for now, if the Location is null, it means `Probe only' to + avoid adding another argument. Might have to revise this + strategy later. + + (ClassCast): New class used to type cast objects into arbitrary + classes (used in Explicit Reference Conversions). + + Implement `as' as well. + + Reverted all the patches from Ravi below: they were broken: + + * The use of `level' as a mechanism to stop recursive + invocations is wrong. That was there just to catch the + bug with a strack trace but not as a way of addressing + the problem. + + To fix the problem we have to *understand* what is going + on and the interactions and come up with a plan, not + just get things going. + + * The use of the type conversion cache that I proposed + last night had an open topic: How does this work across + protection domains. A user defined conversion might not + be public in the location where we are applying the + conversion, a different conversion might be selected + (ie, private A->B (better) but public B->A (worse), + inside A, A->B applies, but outside it, B->A will + apply). + + * On top of that (ie, even if the above is solved), + conversions in a cache need to be abstract. Ie, `To + convert from an Int to a Short use an OpcodeCast', not + `To convert from an Int to a Short use the OpcodeCast on + the variable 5' (which is what this patch was doing). + +2001-09-28 Ravi Pratap + + * expression.cs (Invocation::ConversionExists): Re-write to use + the conversion cache + + (Expression::ConvertImplicit): Automatic bailing out if level != 0. Also + cache all conversions done, not just user-defined ones. + + (Invocation::BetterConversion): The real culprit. Use ConversionExists + to determine if a conversion exists instead of acutually trying to + perform the conversion. It's faster too. + + (Expression::ConvertExplicit): Modify to use ConversionExists to check + and only then attempt the implicit conversion. + +2001-09-28 Ravi Pratap + + * expression.cs (ConvertImplicit): Use a cache for conversions + already found. Check level of recursion and bail out if necessary. + +2001-09-28 Miguel de Icaza + + * typemanager.cs (string_concat_string_string, string_concat_object_object): + Export standard methods that we expect for string operations. + + * statement.cs (Block::UsageWarning): Track usage of variables and + report the errors for not used variables. + + * expression.cs (Conditional::Resolve, ::Emit): Implement ?: + operator. + +2001-09-27 Miguel de Icaza + + * codegen.cs: remove unnneded code + + * expression.cs: Removed BuiltinTypeAccess class + + Fix the order in which implicit conversions are + done. + + The previous fixed dropped support for boxed conversions (adding a + test to the test suite now) + + (UserImplicitCast::CanConvert): Remove test for source being null, + that code is broken. We should not feed a null to begin with, if + we do, then we should track the bug where the problem originates + and not try to cover it up here. + + Return a resolved expression of type UserImplicitCast on success + rather than true/false. Ravi: this is what I was talking about, + the pattern is to use a static method as a "constructor" for + objects. + + Also, do not create arguments until the very last minute, + otherwise we always create the arguments even for lookups that + will never be performed. + + (UserImplicitCast::Resolve): Eliminate, objects of type + UserImplicitCast are born in a fully resolved state. + + * typemanager.cs (InitCoreTypes): Init also value_type + (System.ValueType). + + * expression.cs (Cast::Resolve): First resolve the child expression. + + (LValue): Add new method AddressOf to be used by + the `&' operator. + + Change the argument of Store to take an EmitContext instead of an + ILGenerator, because things like FieldExpr need to be able to call + their children expression to generate the instance code. + + (Expression::Error, Expression::Warning): Sugar functions for + reporting errors. + + (Expression::MemberLookup): Accept a TypeContainer instead of a + Report as the first argument. + + (Expression::ResolvePrimary): Killed. I still want to improve + this as currently the code is just not right. + + (Expression::ResolveMemberAccess): Simplify, but it is still + wrong. + + (Unary::Resolve): Catch errors in AddressOf operators. + + (LocalVariableReference::Emit, ::Store, ::AddressOf): typecast + index to a byte for the short-version, or the compiler will choose + the wrong Emit call, which generates the wrong data. + + (ParameterReference::Emit, ::Store): same. + + (FieldExpr::AddressOf): Implement. + + * typemanager.cs: TypeManager: made public variable instead of + property. + + * driver.cs: document --fatal. + + * report.cs (ErrorMessage, WarningMessage): new names for the old + Error and Warning classes. + + * cs-parser.jay (member_access): Turn built-in access to types + into a normal simplename + +2001-09-27 Ravi Pratap + + * expression.cs (Invocation::BetterConversion): Fix to cope + with q being null, since this was introducing a bug. + + * expression.cs (ConvertImplicit): Do built-in conversions first. + +2001-09-27 Ravi Pratap + + * expression.cs (UserImplicitCast::Resolve): Fix bug. + +2001-09-27 Ravi Pratap + + * class.cs (TypeContainer::AddConstructor): Fix a stupid bug + I had introduced long ago (what's new ?). + + * expression.cs (UserImplicitCast::CanConvert): Static method to do + the work of all the checking. + (ConvertImplicit): Call CanConvert and only then create object if necessary. + (UserImplicitCast::CanConvert, ::Resolve): Re-write. + + (Unary::Operator): Rename Add and Subtract to Addition and Subtraction because + that is the right way. + + (Invocation::MakeUnionSet): Convenience function to make unions of sets for + overloading resolution. Use everywhere instead of cutting and pasting code. + + (Binary::ResolveOperator): Use MakeUnionSet. + + (UserImplicitCast::CanConvert, ::Resolve): Update to take care of the case when + we have to convert to bool types. Not complete yet. + +2001-09-27 Miguel de Icaza + + * typemanager.cs (TypeManager::CSharpName): support ushort. + + * expression.cs (Expression::TryImplicitIntConversion): Attempts + to provide an expression that performsn an implicit constant int + conversion (section 6.1.6). + (Expression::ConvertImplicitRequired): Reworked to include + implicit constant expression conversions. + + (Expression::ConvertNumericExplicit): Finished. + + (Invocation::Emit): If InstanceExpression is null, then it means + that we perform a call on this. + +2001-09-26 Miguel de Icaza + + * expression.cs (Unary::Emit): Remove some dead code. + (Probe): Implement Resolve and Emit for `is'. + (Expression::ConvertImplicitRequired): Attempt to do constant + expression conversions here. Maybe should be moved to + ConvertImplicit, but I am not sure. + (Expression::ImplicitLongConstantConversionPossible, + Expression::ImplicitIntConstantConversionPossible): New functions + that tell whether is it possible to apply an implicit constant + expression conversion. + + (ConvertNumericExplicit): Started work on explicit numeric + conversions. + + * cs-parser.jay: Update operator constants. + + * parameter.cs (Parameters::GetParameterInfo): Hook up VerifyArgs + (Parameters::GetSignature): Hook up VerifyArgs here. + (Parameters::VerifyArgs): Verifies that no two arguments have the + same name. + + * class.cs (Operator): Update the operator names to reflect the + ones that the spec expects (as we are just stringizing the + operator names). + + * expression.cs (Unary::ResolveOperator): Fix bug: Use + MethodInfo's ReturnType instead of LookupMethodByBuilder as the + previous usage did only work for our methods. + (Expression::ConvertImplicit): Handle decimal implicit numeric + conversions as well. + (Expression::InternalTypeConstructor): Used to invoke constructors + on internal types for default promotions. + + (Unary::Emit): Implement special handling for the pre/post + increment/decrement for overloaded operators, as they need to have + the same semantics as the other operators. + + (Binary::ResolveOperator): ditto. + (Invocation::ConversionExists): ditto. + (UserImplicitCast::Resolve): ditto. + +2001-09-26 Ravi Pratap + + * expression.cs (Unary::Emit and Binary::Emit): If we have an overloaded + operator, return after emitting body. Regression tests pass again ! + + * expression.cs (ConvertImplicit): Take TypeContainer as first argument + (Unary::ForceConversion, Binary::ForceConversion): Ditto. + (Invocation::OverloadResolve): Ditto. + (Invocation::BetterFunction, BetterConversion, ConversionExists): Ditto. + + * everywhere : update calls to the above methods accordingly. + +2001-09-26 Miguel de Icaza + + * assign.cs (Assign): Make it inherit from ExpressionStatement. + + * expression.cs (ExpressionStatement): New base class used for + expressions that can appear in statements, so that we can provide + an alternate path to generate expression that do not leave a value + on the stack. + + (Expression::Emit, and all the derivatives): We no longer return + whether a value is left on the stack or not. Every expression + after being emitted leaves a single value on the stack. + + * codegen.cs (EmitContext::EmitStatementExpression): Use the + facilties of ExpressionStatement if possible. + + * cs-parser.jay: Update statement_expression. + +2001-09-25 Miguel de Icaza + + * driver.cs: Change the wording of message + +2001-09-25 Ravi Pratap + + * expression.cs (Binary::ResolveOperator): Had forgottten to set + the type of the expression to the return type of the method if + we have an overloaded operator match ! The regression tests pass again ! + (Unary::ResolveOperator): Ditto. + + * expression.cs (Invocation::ConversionExists): Correct the member lookup + to find "op_Implicit", not "implicit" ;-) + (UserImplicitCast): New class to take care of user-defined implicit conversions. + (ConvertImplicit, ForceConversion): Take TypeContainer argument + + * everywhere : Correct calls to the above accordingly. + + * expression.cs (UserImplicitCast::Resolve, ::Emit): Implement. + (ConvertImplicit): Do user-defined conversion if it exists. + +2001-09-24 Miguel de Icaza + + * assign.cs: track location. + (Resolve): Use implicit conversions on assignment. + + * literal.cs: Oops. Not good, Emit of short access values should + pass (Bytes) or the wrong argument will be selected. + + * expression.cs (Unary::Emit): Emit code for -expr. + + (Unary::ResolveOperator): Handle `Substract' for non-constants + (substract from zero from the non-constants). + Deal with Doubles as well. + + (Expression::ConvertImplicitRequired): New routine that reports an + error if no implicit conversion exists. + + (Invocation::OverloadResolve): Store the converted implicit + expressions if we make them + +2001-09-24 Ravi Pratap + + * class.cs (ConstructorInitializer): Take a Location argument. + (ConstructorBaseInitializer): Same here. + (ConstructorThisInitializer): Same here. + + * cs-parser.jay : Update all calls accordingly. + + * expression.cs (Unary, Binary, New): Take location argument. + Update accordingly everywhere. + + * cs-parser.jay : Update all calls to the above to take a location + argument. + + * class.cs : Ditto. + +2001-09-24 Ravi Pratap + + * expression.cs (Invocation::BetterFunction): Take TypeContainer argument + (Invocation::BetterConversion): Same here + (Invocation::ConversionExists): Ditto. + + (Invocation::ConversionExists): Implement. + +2001-09-22 Ravi Pratap + + * expression.cs (OverloadResolve): Improve some more to catch errors 1502 and 1503 + Also take an additional TypeContainer argument. + + * All over : Pass in TypeContainer as argument to OverloadResolve. + + * typemanager.cs (CSharpName): Update to check for the string type and return + that too. + + * expression.cs (Invocation::FullMethodDesc): New static method to return a string fully describing + a given method. + +2001-09-21 Ravi Pratap + + * expression.cs (Invocation::OverloadResolve): Re-write to conform more to the spec. + (Invocation::BetterFunction): Implement. + (Invocation::BetterConversion): Implement. + (Invocation::ConversionExists): Skeleton, no implementation yet. + + Okay, things work fine ! + +2001-09-21 Miguel de Icaza + + * typemanager.cs: declare and load enum_type, delegate_type and + void_type. + + * expression.cs (Expression::Emit): Now emit returns a value that + tells whether a value is left on the stack or not. This strategy + might be reveted tomorrow with a mechanism that would address + multiple assignments. + (Expression::report118): Utility routine to report mismatches on + the ExprClass. + + (Unary::Report23): Report impossible type/operator combination + utility function. + + (Unary::IsIncrementableNumber): Whether the type can be + incremented or decremented with add. + (Unary::ResolveOperator): Also allow enumerations to be bitwise + complemented. + (Unary::ResolveOperator): Implement ++, !, ~, + + (Invocation::Emit): Deal with new Emit convetion. + + * All Expression derivatives: Updated their Emit method to return + whether they leave values on the stack or not. + + * codegen.cs (CodeGen::EmitStatement): Pop values left on the + stack for expressions that are statements. + +2001-09-20 Miguel de Icaza + + * expression.cs (LValue): New interface. Must be implemented by + LValue objects. + (LocalVariableReference, ParameterReference, FieldExpr): Implement + LValue interface. + + * assign.cs (Assign::Emit, Assign::Resolve): Use new LValue + interface for generating code, simplifies the code. + +2001-09-20 Ravi Pratap + + * expression.cs (everywhere): Comment out return statements in ::Resolve + methods to avoid the warnings. + +2001-09-20 Miguel de Icaza + + * driver.cs (parse): Report error 2001 if we can not open the + source file. + + * expression.cs (SimpleName::ResolveSimpleName): Error if we can + not resolve it. + + * cs-parser.jay (QualifierIdentifier): Pass location to SimpleName + object. + + * statement.cs (Block::EmitMeta): Reuse the count across all the variables, + otherwise nested blocks end up with the same index. + + * codegen.cs (CodeGen::EmitTopBlock): Pass initial sequence + + * expression.cs: Instead of having FIXMEs in the Resolve + functions, throw exceptions so it is obvious that we are facing a + bug. + + * cs-parser.jay (invocation_expression): Pass Location information. + + * codegen.cs (CodeGen::Save, CodeGen::CodeGen, CodeGen::Basename): + Use a basename for those routines because .NET does not like paths + on them. + + * class.cs (TypeContainer::AddMethod): Do not call DefineName if the name was + already defined. + +2001-09-19 Miguel de Icaza + + * typemanager.cs (TypeManager::CoreLookupType): A function to make sure that we + are loading the correct data types (throws an exception if not). + (TypeManager::InitCoreTypes): Use CoreLookupType + + * expression.cs (Unary::ResolveOperator): return the child + expression for expressions which are just +expr. + (Unary::ResolveOperator): Return negative literals for -LITERAL + expressions (otherwise they are Unary {Literal}). + (Invocation::Badness): Take into account `Implicit constant + expression conversions'. + + * literal.cs (LongLiteral): Implement long literal class. + (IntLiteral): export the `Value' of the intliteral. + +2001-09-19 Ravi Pratap + + * expression.cs (Binary::Emit): Finally get the emission right ! Woo! + + * class.cs (Operator::Define): Change the methodname prefix to 'op_' + instead of 'Operator' + + * expression.cs (Binary::ResolveOperator): Update accordingly. + (Unary::Operator): Change names to 'Add' and 'Subtract' instead 'Plus' + and 'Minus' + + * cs-parser.jay (unary_expression): Update to use the new names. + + * gen-treedump.cs (GetUnary): Same here. + + * expression.cs (Unary::Resolve): Implement. + (Binary::ResolveOperator): Re-write bits to quietly continue if no overloaded + operators are found instead of making noise ;-) + (Unary::ResolveOperator): New method to do precisely the same thing which + Binary::ResolveOperator does for Binary expressions. + (Unary.method, .Arguments): Add. + (Unary::OperName): Implement. + (Unary::ForceConversion): Copy and Paste ! + + * class.cs (Operator::Define): Fix a small bug for the case when we have + a unary operator. + + * expression.cs (Unary::Emit): Implement. Need to find the right Opcodes + for the inbuilt operators. Only overloading works for now ;-) + +2001-09-18 Miguel de Icaza + + * expression.cs (CheckedExpr::Resolve, CheckedExpr::Emit, + UnCheckedExpr::Resolve, UnCheckedExpr::Emit): Implement. + + * expression.cs (This::Emit): Implement. + (This::Resolve): Implement. + (TypeOf:Resolve): Implement. + (Expression::ResolveSimpleName): Add an implicit this to instance + field references. + (MemberAccess::Resolve): Deal with Parameters and Fields. + Bind instance variable to Field expressions. + (FieldExpr::Instance): New field used to track the expression that + represents the object instance. + (FieldExpr::Resolve): Track potential errors from MemberLookup not + binding + (FieldExpr::Emit): Implement. + + * codegen.cs (EmitIf, EmitStatement, EmitBlock): Propagate whether + the last instruction contains a return opcode to avoid generating + the last `ret' instruction (this generates correct code, and it is + nice to pass the peverify output). + + * class.cs (TypeContainer::EmitFieldInitializers): Implement field + initializer for static and instance variables. + (Constructor::Emit): Allow initializer to be null in the case of + static constructors. Only emit initializer for instance + constructors. + + (TypeContainer::FindMembers): Return a null array if there are no + matches. + + Also fix the code for the MemberTypes.Method branch, as it was not + scanning that for operators (or tried to access null variables before). + + * assign.cs (Assign::Emit): Handle instance and static fields. + + * TODO: Updated. + + * driver.cs: Stop compilation if there are parse errors. + + * cs-parser.jay (constructor_declaration): Provide default base + initializer for non-static constructors. + (constructor_declarator): Do not provide a default base + initializers if none was specified. + Catch the fact that constructors should not have parameters. + + * class.cs: Do not emit parent class initializers for static + constructors, that should be flagged as an error. + +2001-09-18 Ravi Pratap + + * class.cs (RegisterMethodBuilder): Remove : it's unnecessary. + Move back code into TypeContainer::Populate. + +2001-09-18 Ravi Pratap + + * class.cs (TypeContainer::AddConstructor): Fix the check to + compare against Name, not Basename. + (Operator::OpType): Change Plus and Minus to Add and Subtract. + + * cs-parser.jay : Update accordingly. + + * class.cs (TypeContainer::FindMembers): For the case where we are searching + for methods, don't forget to look into the operators too. + (RegisterMethodBuilder): Helper method to take care of this for + methods, constructors and operators. + (Operator::Define): Completely revamp. + (Operator.OperatorMethod, MethodName): New fields. + (TypeContainer::Populate): Move the registering of builders into + RegisterMethodBuilder. + (Operator::Emit): Re-write. + + * expression.cs (Binary::Emit): Comment out code path to emit method + invocation stuff for the case when we have a user defined operator. I am + just not able to get it right ! + +2001-09-17 Miguel de Icaza + + * expression.cs (Expression::OverloadResolve): Drop TypeContainer + argument. + + (Expression::MemberLookup): Provide a version that allows to + specify the MemberTypes and BindingFlags. + + * statement.cs (Block::GetVariableInfo): Forgot to recurse here, + so it was not fetching variable information from outer blocks. + + * modifiers.cs: (Modifiers::TypeAttr): Invert condition on + Beforefieldinit as it was buggy. + + * rootcontext.cs (::LookupInterfaceOrClass): Removed an Error -200 + that Ravi put here. + + * class.cs (Constructor::Emit): Only emit if block is not null. + (TypeContainer::EmitDefaultConstructor): Removed routine, now we + deal with this by semantically definining it as if the user had + done it. + + (TypeContainer::FindMembers): Removed ad-hoc hack to deal with + constructors as we now "emit" them at a higher level. + + (TypeContainer::DefineDefaultConstructor): Used to define the + default constructors if none was provided. + + (ConstructorInitializer): Add methods Resolve and Emit. + + * expression.cs: Cast to ConstructorInfo instead of MethodInfo + +2001-09-17 Ravi Pratap + + * class.cs (TypeContainer::EmitDefaultConstructor): Register + the default constructor builder with our hashtable for methodbuilders + to methodcores. + + * expression.cs (Invocation::OverloadResolve): Add a check for pd == null + and argument_count is 0 in which case we have a match. + (Binary::ResolveOperator): More null checking and miscellaneous coding + style cleanup. + +2001-09-17 Ravi Pratap + + * rootcontext.cs (IsNameSpace): Compare against null. + + * everywhere : Correct spelling to 'Greater' and to 'Subtract' + + * class.cs (Operator::OpType): Change names to match the ones in Binary::Operator + and Unary::Operator. + + * cs-parser.jay (operator_declaration, CheckBinaryOperator, CheckUnaryOperator): Update + accordingly. + + * expression.cs (Binary::method): New member to hold the MethodBase for the case when + we have overloaded operators. + (Binary::ResolveOperator): Implement the part which does the operator overload + resolution. + + * class.cs (Operator::Emit): Implement. + (TypeContainer::Emit): Emit the operators we have too. + + * expression.cs (Binary::Emit): Update to emit the appropriate code for + the case when we have a user-defined operator. + +2001-09-17 Miguel de Icaza + + * rootcontext.cs: Fix bug: tree.Namespaces might be null. + +2001-09-16 Ravi Pratap + + * class.cs (EmitStaticFieldInitializers, EmitFieldInitializers): Make public. + (TypeContainer::EmitConstructor): Remove and move code into Contructor::Emit. + (Constructor::Emit): Implement. + (EmitStaticFieldInitializers, EmitFieldInitializers): Ensure we return immediately + if we have no work to do. + (TypeContainer::Emit): Pass in TypeContainer as argument to the constructor's + Emit method. + + * interface.cs (Interface::InterfaceAttr): Re-write to be more correct and complete. + (Interface::IsTopLevel): Add. Same as TypeContainer::IsTopLevel. + + * class.cs (TypeContainer::IsTopLevel): Modify to use parent.Parent instead + of parent.parent. + +2001-09-15 Ravi Pratap + + * tree.cs (Tree::namespaces): New hashtable to keep track of namespaces + in the source. + (Tree::RecordNamespace): Method to do what the name says ;-) + (Tree::Namespaces): Property to get at the namespaces hashtable. + + * cs-parser.jay (namespace_declaration): Call RecordNamespace to + keep track. + + * rootcontext.cs (IsNamespace): Fixed it :-) + +2001-09-14 Miguel de Icaza + + * class.cs (TypeContainer::FindMembers): Add support for + constructors. + (MethodCore): New class that encapsulates both the shared aspects + of a Constructor and a Method. + (Method, Constructor): Factored pieces into MethodCore. + + * driver.cs: Added --fatal which makes errors throw exceptions. + Load System assembly as well as part of the standard library. + + * report.cs: Allow throwing exceptions on errors for debugging. + + * modifiers.cs: Do not use `parent', instead use the real type + container to evaluate permission settings. + + * class.cs: Put Ravi's patch back in. He is right, and we will + have to cope with the + +2001-09-14 Ravi Pratap + + * modifiers.cs (TypeAttr, MethodAttr, FieldAttr): Map protected internal to + FamORAssem, not FamANDAssem. + +2001-09-14 Miguel de Icaza + + * driver.cs: Added --parse option that only parses its input files + and terminates. + + * class.cs: Reverted last change from Ravi to IsTopLevel. That is + incorrect. IsTopLevel is not used to tell whether an object is + root_types or not (that can be achieved by testing this == + root_types). But to see if this is a top-level *class* (not + necessarly our "toplevel" container). + +2001-09-14 Ravi Pratap + + * enum.cs (Enum::Define): Modify to call the Lookup method on the + parent instead of a direct call to GetType. + +2001-09-14 Ravi Pratap + + * class.cs (TypeContainer::TypeAttr): Remove property code and move it into + Modifiers.TypeAttr. This should just be a call to that method. + + * modifiers.cs (TypeAttr): Re-write and take an extra argument, the TypeContainer + object so that we can determine if we are top-level or not. + + * delegate.cs (Delegate::Define): Update call to TypeAttr method to pass in the + TypeContainer too. + + * enum.cs (Enum::Define): Ditto. + + * modifiers.cs (FieldAttr): Re-write. + + * class.cs (TypeContainer::IsTopLevel): Change accessibility to public. + (TypeContainer::HaveStaticConstructor): New property to provide access + to precisely that info. + + * modifiers.cs (MethodAttr): Re-write. + (EventAttr): Remove altogether as there seems to be no ostensible use for it. + + * class.cs (TypeContainer::IsTopLevel): Re-write. root_types doesn't seem to be the parent + of top-level types as claimed. + +2001-09-13 Miguel de Icaza + + * expression.cs (MemberLookup): Fruitless attempt to lookup + constructors. Maybe I need to emit default constructors? That + might be it (currently .NET emits this for me automatically). + (Invocation::OverloadResolve): Cope with Arguments == null. + (Invocation::EmitArguments): new function, shared by the new + constructor and us. + (Invocation::Emit): Handle static and instance methods. Emit + proper call instruction for virtual or non-virtual invocations. + (New::Emit): Implement. + (New::Resolve): Implement. + (MemberAccess:Resolve): Implement. + (MethodGroupExpr::InstanceExpression): used conforming to the spec + to track instances. + (FieldExpr::Resolve): Set type. + + * support.cs: Handle empty arguments. + + * cs-parser.jay (CompositeLookup, QualifierIdentifier, + SimpleLookup): Auxiliary routines to help parse a qualifier + identifier. + + Update qualifier_identifier rule. + + * codegen.cs: Removed debugging messages. + + * class.cs: Make this a global thing, this acts just as a "key" to + objects that we might have around. + + (Populate): Only initialize method_builders_to_methods once. + + * expression.cs (PropertyExpr): Initialize type from the + PropertyType. + + * codegen.cs (EmitContext::EmitBoolExpression): Use propper + Resolve pattern. Attempt to implicitly convert value to boolean. + Emit code. + + * expression.cs: Set the type for the int32/int32 argument case. + (Binary::ResolveOperator): Set the return type to boolean for + comparission operators + + * typemanager.cs: Remove debugging print code. + + (Invocation::Resolve): resolve type. + + * class.cs: Allocate a MemberInfo of the correct size, as the code + elsewhere depends on the test to reflect the correct contents. + + (Method::) Keep track of parameters, due to System.Reflection holes + + (TypeContainer::Populate): Keep track of MethodBuilders to Method + mapping here. + + (TypeContainer::FindMembers): Use ArrayList and then copy an array + of the exact size and return that. + + (Class::LookupMethodByBuilder): New function that maps + MethodBuilders to its methods. Required to locate the information + on methods because System.Reflection bit us again. + + * support.cs: New file, contains an interface ParameterData and + two implementations: ReflectionParameters and InternalParameters + used to access Parameter information. We will need to grow this + as required. + + * expression.cs (Invocation::GetParameterData): implement a cache + and a wrapper around the ParameterData creation for methods. + (Invocation::OverloadResolve): Use new code. + +2001-09-13 Ravi Pratap + + * class.cs (TypeContainer::EmitField): Remove and move into + (Field::Define): here and modify accordingly. + (Field.FieldBuilder): New member. + (TypeContainer::Populate): Update accordingly. + (TypeContainer::FindMembers): Implement. + +2001-09-13 Miguel de Icaza + + * statement.cs: (VariableInfo::VariableType): New field to be + initialized with the full type once it is resolved. + +2001-09-12 Miguel de Icaza + + * parameter.cs (GetParameterInfo): Use a type cache to compute + things only once, and to reuse this information + + * expression.cs (LocalVariableReference::Emit): Implement. + (OpcodeCast::Emit): fix. + + (ParameterReference::Resolve): Implement. + (ParameterReference::Emit): Implement. + + * cs-parser.jay: Fix bug introduced by Ravi, variable initializers + that are expressions need to stay as Expressions. + + * typemanager.cs (CSharpName): Returns the C# name of a type if + possible. + + * expression.cs (Expression::ConvertImplicit): New function that + implements implicit type conversions. + + (Expression::ImplicitReferenceConversion): Implements implicit + reference conversions. + + (EmptyCast): New type for transparent casts. + + (OpcodeCast): New type for casts of types that are performed with + a sequence of bytecodes. + + (BoxedCast): New type used for casting value types into reference + types. Emits a box opcode. + + (Binary::DoNumericPromotions): Implements numeric promotions of + and computation of the Binary::Type. + + (Binary::EmitBranchable): Optimization. + + (Binary::Emit): Implement code emission for expressions. + + * typemanager.cs (TypeManager): Added two new core types: sbyte + and byte. + +2001-09-12 Ravi Pratap + + * class.cs (TypeContainer::FindMembers): Method which does exactly + what Type.FindMembers does, only we don't have to use reflection. No + implementation yet. + + * typemanager.cs (typecontainers): New hashtable to hold the corresponding + typecontainer objects as we need to get at them. + (TypeManager::AddUserType): Overload to take an extra argument, the TypeContainer. + + * rootcontext.cs : Correspondingly modify called to AddUserType to pass the + typecontainer object. + + * expression.cs (MemberLookup): Modify signature to take a RootContext object instead + of just a Report object. + +2001-09-11 Ravi Pratap + + * class.cs (Event::Define): Go back to using the prefixes "add_" and + "remove_" + (TypeContainer::Populate): Now define the delegates of the type too. + (TypeContainer.Delegates): Property to access the list of delegates defined + in the type. + + * delegates.cs (Delegate::Define): Implement partially. + + * modifiers.cs (TypeAttr): Handle more flags. + +2001-09-11 Ravi Pratap + + * class.cs (Indexer::Define): Fix for loop iteration condition to be just < + and not <= + (Operator::Define): Re-write logic to get types by using the LookupType method + instead of blindly doing a Type.GetType ! How stupid can I get ;-) ? + (Indexer::Define): Ditto. + (Event::Define): Ditto. + (Property::Define): Ditto. + +2001-09-10 Ravi Pratap + + * class.cs (TypeContainer::Populate): Now define operators too. + (TypeContainer.Operators): New property to access the list of operators + in a type. + (Operator.OperatorMethodBuilder): New member to hold the method builder + for the operator we are defining. + (Operator::Define): Implement. + +2001-09-10 Ravi Pratap + + * class.cs (Event::Define): Make the prefixes of the accessor methods + addOn_ and removeOn_ + + * genericparser.cs (GenericParser::error): Overloaded method to handle the case + of the location being passed in too. Ideally, this should go later since all + error reporting should be done through the Report object. + + * class.cs (TypeContainer.Indexers): New property to access the list of indexers. + (Populate): Iterate thru the indexers we have and define them too. + (Indexer.GetMethodBuilder, .SetMethodBuilder): New members to hold the method builders + for the get and set accessors. + (Indexer::Define): Implement. + +2001-09-09 Miguel de Icaza + + * expression.cs (Binary::Resolve): Beginning of it. I scratched + my previous implementation, did not work. + + * typemanager.cs: Add a couple of missing types (the longs). + + * literal.cs: Use TypeManager.bool_type instead of getting it. + + * expression.cs (EventExpr): New kind of expressions. + (Expressio::ExprClassFromMemberInfo): finish + +2001-09-08 Miguel de Icaza + + * assign.cs: Emit stores to static fields differently. + +2001-09-08 Ravi Pratap + + * Merge in changes and adjust code to tackle conflicts. Backed out my + code in Assign::Resolve ;-) + +2001-09-08 Ravi Pratap + + * cs-parser.jay (CheckAttributeTarget): Modify call to error to use + instead Report.Error and also pass in the location. + (CSharpParser::Lexer): New readonly property to return the reference + to the Tokenizer object. + (declare_local_variables): Use Report.Error with location instead of plain + old error. + (CheckDef): Ditto. + + * class.cs (Operator::CheckUnaryOperator): Move into cs-parser.jay. + (Operator.CheckBinaryOperator): Ditto. + + * cs-parser.jay (operator_declarator): Update accordingly. + + * cs-parser.jay (CheckUnaryOperator): Modify to use Report.Error + (CheckBinaryOperator): Same here. + + * rootcontext.cs (LookupType): Add an extra lookup which simply does a lookup + on the name without any prefixes of namespace names etc. This is because we + already might have something already fully qualified like + 'System.Console.WriteLine' + + * assign.cs (Resolve): Begin implementation. Stuck ;-) + +2001-09-07 Ravi Pratap + + * cs-tokenizer.cs (location): Return a string which also contains + the file name. + + * expression.cs (ElementAccess): New class for expressions of the + type 'element access.' + (BaseAccess): New class for expressions of the type 'base access.' + (CheckedExpr, UnCheckedExpr): New classes for Checked and Unchecked expressions + respectively. + + * cs-parser.jay (element_access): Implement action. + (base_access): Implement actions. + (checked_expression, unchecked_expression): Implement. + + * cs-parser.jay (local_variable_type): Correct and implement. + (type_suffixes, type_suffix_list, type_suffix): Implement actions. + + * cs-tokenizer.cs (real_type_suffix): Comment out the extra getchar. + + * cs-parser.jay (rank_specifiers): Remove space while concatenating the type's + name and the specifiers. + + * interface.cs (InterfaceAttr): New property to return the corresponding TypeAttributes + + * rootcontext.cs (CreateInterface): Use the InterfaceAttr property instead of + making them all public ;-) + + * cs-parser.jay (error): Remove entirely as we have an implementation in the base + class anyways. + +2001-09-07 Miguel de Icaza + + * expression.cs (ExprClassFromMemberInfo): Return FieldExpr and + PropertyExprs. + (FieldExpr, PropertyExprs): New resolved expressions. + (SimpleName::MemberStaticCheck): Perform static checks for access + to non-static fields on static methods. Maybe this should be + generalized for MemberAccesses. + (SimpleName::ResolveSimpleName): More work on simple name + resolution. + + * cs-parser.jay (primary_expression/qualified_identifier): track + the parameter index. + + * codegen.cs (CodeGen::Save): Catch save exception, report error. + (EmitContext::EmitBoolExpression): Chain to expression generation + instead of temporary hack. + (::EmitStatementExpression): Put generic expression code generation. + + * assign.cs (Assign::Emit): Implement variable assignments to + local variables, parameters and fields. + +2001-09-06 Miguel de Icaza + + * statement.cs (Block::GetVariableInfo): New method, returns the + VariableInfo for a variable name in a block. + (Block::GetVariableType): Implement in terms of GetVariableInfo + + * literal.cs (IntLiteral::Emit, FloatLiteral::Emit, + DoubleLiteral::Emit, CharLiteral::Emit, BoolLiteral::Emit): Implement + +2001-09-06 Ravi Pratap + + * cs-parser.jay (operator_declaration): Continue on my quest : update + to take attributes argument. + (event_declaration): Ditto. + (enum_declaration): Ditto. + (indexer_declaration): Ditto. + + * class.cs (Operator::Operator): Update constructor accordingly. + (Event::Event): Ditto. + + * delegate.cs (Delegate::Delegate): Same here. + + * enum.cs (Enum::Enum): Same here. + +2001-09-05 Ravi Pratap + + * cs-parser.jay (CheckAttributeTarget): Update to use the right error number. + + * ../tests/cs0658.cs : New file to demonstrate error 0658. + + * attribute.cs (Attributes): New class to encapsulate all attributes which were + being passed around as an arraylist. + (Attributes::AddAttribute): Method to add attribute sections. + + * cs-parser.jay (opt_attributes): Modify actions to use the new Attributes class. + (struct_declaration): Update accordingly. + (constant_declaration): Update. + (field_declaration): Update. + (method_header): Update. + (fixed_parameter): Update. + (parameter_array): Ditto. + (property_declaration): Ditto. + (destructor_declaration): Ditto. + + * class.cs (Struct::Struct): Update constructors accordingly. + (Class::Class): Ditto. + (Field::Field): Ditto. + (Method::Method): Ditto. + (Property::Property): Ditto. + (TypeContainer::OptAttribute): update property's return type. + + * interface.cs (Interface.opt_attributes): New member. + (Interface::Interface): Update to take the extra Attributes argument. + + * parameter.cs (Parameter::Parameter): Ditto. + + * constant.cs (Constant::Constant): Ditto. + + * interface.cs (InterfaceMemberBase): New OptAttributes field. + (InterfaceMemberBase::InterfaceMemberBase): Update constructor to take + the attributes as a parameter. + (InterfaceProperty): Update constructor call. + (InterfaceEvent): Ditto. + (InterfaceMethod): Ditto. + (InterfaceIndexer): Ditto. + + * cs-parser.jay (interface_indexer_declaration): Update call to constructor to + pass the attributes too. + (interface_event_declaration): Ditto. + (interface_property_declaration): Ditto. + (interface_method_declaration): Ditto. + (interface_declaration): Ditto. + +2001-09-05 Miguel de Icaza + + * class.cs (Method::Define): Track the "static Main" definition to + create an entry point. + + * rootcontext.cs (RootContext::EntryPoint): MethodInfo that holds the + EntryPoint if we find it. + + * codegen.cs (EmitContext::EmitInvocation): Emit invocations. + (EmitContext::ig): Make this variable public. + + * driver.cs: Make the default output file be the first file name + with the .exe extension. + + Detect empty compilations + + Handle various kinds of output targets. Handle --target and + rename -t to --dumper. + + * expression.cs, literal.cs, assign.cs, constant.cs: All `Resolve' + methods inherited from Expression return now an Expression. This + will is used during the tree rewriting as we resolve them during + semantic analysis. + + (Expression::MemberLookup): Implements the MemberLookup (7.3) from + the spec. Missing entirely is the information about + accessability of elements of it. + + (Expression::ExprClassFromMemberInfo): New constructor for + Expressions that creates a fully initialized Expression based on + a MemberInfo that is one of Eventinfo, FieldINfo, PropertyInfo or + a Type. + + (Invocation::Resolve): Begin implementing resolution of invocations. + + * literal.cs (StringLiteral): Implement Emit. + +2001-09-05 Ravi Pratap + + * cs-parser.jay (error): Add new modifier because we are hiding an inherited + member. + +2001-09-04 Ravi Pratap + + * cs-parser.jay (attribute_arguments): Implement actions. + (attribute): Fix bug in production. Implement action. + (attribute_list): Implement. + (attribute_target): Implement. + (attribute_target_specifier, opt_target_specifier): Implement + (CheckAttributeTarget): New method to check if the attribute target + is valid. + (attribute_section): Implement. + (opt_attributes): Implement. + + * attribute.cs : New file to handle attributes. + (Attribute): Class to hold attribute info. + + * cs-parser.jay (opt_attribute_target_specifier): Remove production + (attribute_section): Modify production to use 2 different rules to + achieve the same thing. 1 s/r conflict down ! + Clean out commented, useless, non-reducing dimension_separator rules. + + * class.cs (TypeContainer.attributes): New member to hold list + of attributes for a type. + (Struct::Struct): Modify to take one more argument, the attribute list. + (Class::Class): Ditto. + (Field::Field): Ditto. + (Method::Method): Ditto. + (Property::Property): Ditto. + + * cs-parser.jay (struct_declaration): Update constructor call to + pass in the attributes too. + (class_declaration): Ditto. + (constant_declaration): Ditto. + (field_declaration): Ditto. + (method_header): Ditto. + (fixed_parameter): Ditto. + (parameter_array): Ditto. + (property_declaration): Ditto. + + * constant.cs (Constant::Constant): Update constructor similarly. + Use System.Collections. + + * parameter.cs (Parameter::Parameter): Update as above. + +2001-09-02 Ravi Pratap + + * class.cs (TypeContainer::AddDelegate): New method to add a delegate. + (TypeContainer.delegates): New member to hold list of delegates. + + * cs-parser.jay (delegate_declaration): Implement the action correctly + this time as I seem to be on crack ;-) + +2001-09-02 Miguel de Icaza + + * rootcontext.cs (RootContext::IsNamespace): new function, used to + tell whether an identifier represents a namespace. + + * expression.cs (NamespaceExpr): A namespace expression, used only + temporarly during expression resolution. + (Expression::ResolveSimpleName, ::ResolvePrimary, ::ResolveName): + utility functions to resolve names on expressions. + +2001-09-01 Miguel de Icaza + + * codegen.cs: Add hook for StatementExpressions. + + * class.cs: Fix inverted test for static flag in methods. + +2001-09-02 Ravi Pratap + + * class.cs (Operator::CheckUnaryOperator): Correct error number used + to make it coincide with MS' number. + (Operator::CheckBinaryOperator): Ditto. + + * ../errors/errors.txt : Remove error numbers added earlier. + + * ../errors/cs1019.cs : Test case for error # 1019 + + * ../errros/cs1020.cs : Test case for error # 1020 + + * cs-parser.jay : Clean out commented cruft. + (dimension_separators, dimension_separator): Comment out. Ostensibly not + used anywhere - non-reducing rule. + (namespace_declarations): Non-reducing rule - comment out. + + * enum.cs (Enum::AddEnum): Rename to AddEnumMember as I was getting confused + with TypeContainer::AddEnum. + + * delegate.cs : New file for delegate handling classes. + (Delegate): Class for declaring delegates. + + * makefile : Update. + + * cs-parser.jay (delegate_declaration): Implement. + +2001-09-01 Ravi Pratap + + * class.cs (Event::Define): Implement. + (Event.EventBuilder): New member. + + * class.cs (TypeContainer::Populate): Update to define all enums and events + we have. + (Events): New property for the events arraylist we hold. Shouldn't we move to using + readonly fields for all these cases ? + +2001-08-31 Ravi Pratap + + * class.cs (Property): Revamp to use the convention of making fields readonly. + Accordingly modify code elsewhere. + + * class.cs : Apply patch from Mr. Mandar for implementing + the Define method of the Property class. + + * class.cs : Clean up applied patch and update references to variables etc. Fix + trivial bug. + (TypeContainer::Populate): Update to define all the properties we have. Also + define all enumerations. + + * enum.cs (Define): Implement. + +2001-08-31 Ravi Pratap + + * cs-parser.jay (overloadable_operator): The semantic value is an + enum of the Operator class. + (operator_declarator): Implement actions. + (operator_declaration): Implement. + + * class.cs (Operator::CheckUnaryOperator): New static method to help in checking + validity of definitions. + (Operator::CheckBinaryOperator): Static method to check for binary operators + (TypeContainer::AddOperator): New method to add an operator to a type. + + * cs-parser.jay (indexer_declaration): Added line to actually call the + AddIndexer method so it gets added ;-) + + * ../errors/errors.txt : Update to include new error numbers. Are these numbers + already taken care of by the MS compiler ? + +2001-08-29 Ravi Pratap + + * class.cs (Operator): New class for operator declarations. + (Operator::OpType): Enum for the various operators. + +2001-08-29 Ravi Pratap + + * class.cs (TypeContainer::AddIndexer): Remove FIXME comment. We + ostensibly handle this in semantic analysis. + + * cs-parser.jay (general_catch_clause): Comment out + (specific_catch_clauses, specific_catch_clause): Ditto. + (opt_general_catch_clause, opt_specific_catch_clauses): Ditto + (catch_args, opt_catch_args): New productions. + (catch_clause): Rewrite to use the new productions above + (catch_clauses): Modify accordingly. + (opt_catch_clauses): New production to use in try_statement + (try_statement): Revamp. Basically, we get rid of one unnecessary rule + and re-write the code in the actions to extract the specific and + general catch clauses by being a little smart ;-) + + * ../tests/try.cs : Fix. It's not 'finalize' my friend, it's 'finally' ! + Hooray, try and catch statements parse fine ! + +2001-08-28 Ravi Pratap + + * statement.cs (Block::GetVariableType): Fix logic to extract the type + string from the hashtable of variables. + + * cs-parser.jay (event_accessor_declarations): Trivial fix. Man, how did + I end up making that mistake ;-) + (catch_clauses): Fixed gross error which made Key and Value of the + DictionaryEntry the same : $1 !! + +2001-08-28 Ravi Pratap + + * cs-tokenizer.cs (initTokens): Add keywords 'add' and 'remove' + + * cs-parser.jay (event_declaration): Correct to remove the semicolon + when the add and remove accessors are specified. + +2001-08-28 Ravi Pratap + + * cs-parser.jay (IndexerDeclaration): New helper class to hold + information about indexer_declarator. + (indexer_declarator): Implement actions. + (parsing_indexer): New local boolean used to keep track of whether + we are parsing indexers or properties. This is necessary because + implicit_parameters come into picture even for the get accessor in the + case of an indexer. + (get_accessor_declaration, set_accessor_declaration): Correspondingly modified. + + * class.cs (Indexer): New class for indexer declarations. + (TypeContainer::AddIndexer): New method to add an indexer to a type. + (TypeContainer::indexers): New member to hold list of indexers for the + type. + +2001-08-27 Ravi Pratap + + * cs-parser.jay (add_accessor_declaration): Implement action. + (remove_accessor_declaration): Implement action. + (event_accessors_declaration): Implement + (variable_declarators): swap statements for first rule - trivial. + + * class.cs (Event): New class to hold information about event + declarations. + (TypeContainer::AddEvent): New method to add an event to a type + (TypeContainer::events): New member to hold list of events. + + * cs-parser.jay (event_declaration): Implement actions. + +2001-08-27 Ravi Pratap + + * cs-parser.jay (dim_separators): Implement. Make it a string + concatenating all the commas together, just as they appear. + (opt_dim_separators): Modify accordingly + (rank_specifiers): Update accordingly. Basically do the same + thing - instead, collect the brackets here. + (opt_rank_sepcifiers): Modify accordingly. + (array_type): Modify to actually return the complete type string + instead of ignoring the rank_specifiers. + (expression_list): Implement to collect the expressions + (variable_initializer): Implement. We make it a list of expressions + essentially so that we can handle the array_initializer case neatly too. + (variable_initializer_list): Implement. + (array_initializer): Make it a list of variable_initializers + (opt_array_initializer): Modify accordingly. + + * expression.cs (New::NType): Add enumeration to help us + keep track of whether we have an object/delegate creation + or an array creation. + (New:NewType, New::Rank, New::Indices, New::Initializers): New + members to hold data about array creation. + (New:New): Modify to update NewType + (New:New): New Overloaded contructor for the array creation + case. + + * cs-parser.jay (array_creation_expression): Implement to call + the overloaded New constructor. + +2001-08-26 Ravi Pratap + + * class.cs (TypeContainer::Constructors): Return member + constructors instead of returning null. + +2001-08-26 Miguel de Icaza + + * typemanager.cs (InitCoreTypes): Initialize the various core + types after we have populated the type manager with the user + defined types (this distinction will be important later while + compiling corlib.dll) + + * expression.cs, literal.cs, assign.cs, constant.cs: Started work + on Expression Classification. Now all expressions have a method + `Resolve' and a method `Emit'. + + * codegen.cs, cs-parser.jay: Fixed the bug that stopped code + generation from working. Also add some temporary debugging + code. + +2001-08-24 Miguel de Icaza + + * codegen.cs: Lots of code generation pieces. This is only the + beginning, will continue tomorrow with more touches of polish. We + handle the fundamentals of if, while, do, for, return. Others are + trickier and I need to start working on invocations soon. + + * gen-treedump.cs: Bug fix, use s.Increment here instead of + s.InitStatement. + + * codegen.cs (EmitContext): New struct, used during code + emission to keep a context. Most of the code generation will be + here. + + * cs-parser.jay: Add embedded blocks to the list of statements of + this block. So code generation proceeds in a top down fashion. + +2001-08-23 Miguel de Icaza + + * statement.cs: Add support for multiple child blocks. + +2001-08-22 Miguel de Icaza + + * codegen.cs (EmitCode): New function, will emit the code for a + Block of code given a TypeContainer and its ILGenerator. + + * statement.cs (Block): Standard public readonly optimization. + (Block::Block constructors): Link children. + (Block::Child): Child Linker. + (Block::EmitVariables): Emits IL variable declarations. + + * class.cs: Drop support for MethodGroups here, delay until + Semantic Analysis. + (Method::): Applied the same simplification that I did before, and + move from Properties to public readonly fields. + (Method::ParameterTypes): Returns the parameter types for the + function, and implements a cache that will be useful later when I + do error checking and the semantic analysis on the methods is + performed. + (Constructor::GetCallingConvention): Renamed from CallingConvetion + and made a method, optional argument tells whether this is a class + or a structure to apply the `has-this' bit. + (Method::GetCallingConvention): Implement, returns the calling + convention. + (Method::Define): Defines the type, a second pass is performed + later to populate the methods. + + (Constructor::ParameterTypes): implement a cache similar to the + one on Method::ParameterTypes, useful later when we do semantic + analysis. + + (TypeContainer::EmitMethod): New method. Emits methods. + + * expression.cs: Removed MethodGroup class from here. + + * parameter.cs (Parameters::GetCallingConvention): new method. + +2001-08-21 Miguel de Icaza + + * class.cs (TypeContainer::Populate): Drop RootContext from the + argument. + + (Constructor::CallingConvention): Returns the calling convention. + (Constructor::ParameterTypes): Returns the constructor parameter + types. + + (TypeContainer::AddConstructor): Keep track of default constructor + and the default static constructor. + + (Constructor::) Another class that starts using `public readonly' + instead of properties. + + (Constructor::IsDefault): Whether this is a default constructor. + + (Field::) use readonly public fields instead of properties also. + + (TypeContainer::TypeAttr, TypeContainer::AddConstructor): Keep + track of static constructors; If none is used, turn on + BeforeFieldInit in the TypeAttributes. + + * cs-parser.jay (opt_argument_list): now the return can be null + for the cases where there are no arguments. + + (constructor_declarator): If there is no implicit `base' or + `this', then invoke the default parent constructor. + + * modifiers.cs (MethodAttr): New static function maps a set of + modifiers flags into a MethodAttributes enum + (FieldAttr): renamed from `Map'. So now we have FieldAttr, + MethodAttr, TypeAttr to represent the various mappings where the + modifiers are used. + (FieldAttr): Map also `readonly' to `FieldAttributes.InitOnly' + +2001-08-19 Miguel de Icaza + + * parameter.cs (GetParameterInfo): Fix bug where there would be no + method arguments. + + * interface.cs (PopulateIndexer): Implemented the code generator + for interface indexers. + +2001-08-17 Miguel de Icaza + + * interface.cs (InterfaceMemberBase): Now we track the new status + here. + + (PopulateProperty): Implement property population. Woohoo! Got + Methods and Properties going today. + + Removed all the properties for interfaces, and replaced them with + `public readonly' fields. + +2001-08-16 Miguel de Icaza + + * interface.cs (AddEvent, AddMethod, AddIndexer, AddProperty): + initialize their hashtables/arraylists only when they are needed + instead of doing this always. + + * parameter.cs: Handle refs and out parameters. + + * cs-parser.jay: Use an ArrayList to construct the arguments + instead of the ParameterCollection, and then cast that to a + Parameter[] array. + + * parameter.cs: Drop the use of ParameterCollection and use + instead arrays of Parameters. + + (GetParameterInfo): Use the Type, not the Name when resolving + types. + +2001-08-13 Miguel de Icaza + + * parameter.cs: Eliminate the properties Name, Type and ModFlags, + and instead use public readonly fields. + + * class.cs: Put back walking code for type containers. + +2001-08-11 Miguel de Icaza + + * class.cs (MakeConstant): Code to define constants. + + * rootcontext.cs (LookupType): New function. Used to locate types + + +2001-08-08 Miguel de Icaza + + * rootcontext.cs: OH MY! My trick works! It is amazing how nice + this System.Reflection code is. Kudos to Microsoft + + * typemanager.cs: Implement a type cache and avoid loading all + types at boot time. Wrap in LookupType the internals. This made + the compiler so much faster. Wow. I rule! + + * driver.cs: Make sure we always load mscorlib first (for + debugging purposes, nothing really important). + + * Renamespaced things that were on `CSC' to `CIR'. Maybe I should + have moved to `CSC' rather than `CIR'. Oh man! The confussion! + + * rootcontext.cs: Lookup types on their namespace; Lookup types + on namespaces that have been imported using the `using' keyword. + + * class.cs (TypeContainer::TypeAttr): Virtualize. + (Class::TypeAttr): Return attributes suitable for this bad boy. + (Struct::TypeAttr): ditto. + Handle nested classes. + (TypeContainer::) Remove all the type visiting code, it is now + replaced with the rootcontext.cs code + + * rootcontext.cs (GetClassBases): Added support for structs. + +2001-08-06 Miguel de Icaza + + * interface.cs, statement.cs, class.cs, parameter.cs, + rootcontext.cs, gen-treedump.cs, enum.cs, cs-parse.jay: + Drop use of TypeRefs, and use strings instead. + +2001-08-04 Miguel de Icaza + + * rootcontext.cs: + + * class.cs (Struct::Struct): set the SEALED flags after + checking the modifiers. + (TypeContainer::TypeAttr): new property, returns the + TypeAttributes for a class. + + * cs-parser.jay (type_list): Oops, list production was creating a + new list of base types. + + * rootcontext.cs (StdLib): New property. + (GetInterfaceTypeByName): returns an interface by type name, and + encapsulates error handling here. + (GetInterfaces): simplified. + (ResolveTree): Encapsulated all the tree resolution here. + (CreateClass, GetClassBases, GetInterfaceOrClass): Create class + types. + + * driver.cs: Add support for --nostdlib, to avoid loading the + default assemblies. + (Main): Do not put tree resolution here. + + * rootcontext.cs: Beginning of the class resolution. + +2001-08-03 Miguel de Icaza + + * rootcontext.cs: Provide better error reporting. + + * cs-parser.jay (interface_base): set our $$ to be interfaces. + + * rootcontext.cs (CreateInterface): Handle the case where there + are no parent interfaces. + + (CloseTypes): Routine to flush types at the end. + (CreateInterface): Track types. + (GetInterfaces): Returns an array of Types from the list of + defined interfaces. + + * typemanager.c (AddUserType): Mechanism to track user types (puts + the type on the global type hash, and allows us to close it at the + end). + +2001-08-02 Miguel de Icaza + + * tree.cs: Removed RecordType, added RecordClass, RecordStruct and + RecordInterface instead. + + * cs-parser.jay: Updated to reflect changes above. + + * decl.cs (Definition): Keep track of the TypeBuilder type that + represents this type here. Not sure we will use it in the long + run, but wont hurt for now. + + * driver.cs: Smaller changes to accomodate the new code. + + Call ResolveInterfaceBases, Call ResolveClassBases, Save assembly + when done. + + * rootcontext.cs (CreateInterface): New method, used to create + the System.TypeBuilder type for interfaces. + (ResolveInterfaces): new entry point to resolve the interface + hierarchy. + (CodeGen): Property, used to keep track of the code generator. + +2001-07-26 Miguel de Icaza + + * cs-parser.jay: Add a second production for delegate_declaration + with `VOID'. + + (enum_body): Put an opt_comma here instead of putting it on + enum_body or enum_member_declarations so we can handle trailing + commas on enumeration members. Gets rid of a shift/reduce. + + (type_list): Need a COMMA in the middle. + + (indexer_declaration): Tell tokenizer to recognize get/set + + * Remove old targets. + + * Re-add the parser target. + +2001-07-13 Simon Cozens + + * cs-parser.jay: Add precendence rules for a number of operators + ot reduce the number of shift/reduce conflicts in the grammar. + +2001-07-17 Miguel de Icaza + + * tree.cs: moved IGenerator interface and renamed it to ITreeDump + and put it here. + + Get rid of old crufty code. + + * rootcontext.cs: Use this to keep track of the parsed + representation and the defined types available to the program. + + * gen-treedump.cs: adjust for new convention. + + * type.cs: Split out the type manager, and the assembly builder + from here. + + * typemanager.cs: the type manager will live here now. + + * cil-codegen.cs: And the code generator here. + +2001-07-14 Sean MacIsaac + + * makefile: Fixed up for easy making. + +2001-07-13 Simon Cozens + + * cs-parser.jay (rank_specifier): Remove a conflict by reordering + the + + (unary_expression): Expand pre_increment_expression and + post_decrement_expression to reduce a shift/reduce. + +2001-07-11 Simon Cozens + + * cs-tokenizer.cs: Hex numbers should begin with a 0. + + Improve allow_keyword_as_indent name. + +2001-06-19 Miguel de Icaza + + * Adjustments for Beta2. + +2001-06-13 Miguel de Icaza + + * decl.cs: Added `Define' abstract method. + (InTransit): new property, used to catch recursive definitions. + + * interface.cs: Implement `Define'. + + * modifiers.cs: Map Modifiers.constants to + System.Reflection.TypeAttribute flags. + + * class.cs: Keep track of types and user-defined types. + (BuilderInit): New method for creating an assembly + (ResolveType): New function to launch the resolution process, only + used by interfaces for now. + + * cs-parser.jay: Keep track of Classes, Structs and Interfaces + that are inserted into the name space. + +2001-06-08 Miguel de Icaza + + * ARGH. I have screwed up my tree so many times due to the use of + rsync rather than using CVS. Going to fix this at once. + + * driver.cs: Objetify driver. Load assemblies, use assemblies to + load types. + +2001-06-07 Miguel de Icaza + + * Experiment successful: Use System.Type rather that our own + version of Type. + +2001-05-25 Miguel de Icaza + + * cs-parser.jay: Removed nsAliases from here. + + Use new namespaces, handle `using XXX;' + + * namespace.cs: Reimplemented namespace handling, use a recursive + definition of the class. Now we can keep track of using clauses + and catch invalid using clauses. + +2001-05-24 Miguel de Icaza + + * gen-treedump.cs: Adapted for all the renaming. + + * expression.cs (Expression): this class now has a Type property + which returns an expression Type. + + (Probe::, New::, TypeOf::, SizeOf::, Constant::): renamed from + `Type', as this has a different meaning now in the base + +2001-05-22 Miguel de Icaza + + * interface.cs, class.cs: Removed from all the sources the + references to signature computation, as we can not do method + signature computation during the parsing time, as we are not + trying to solve at that point distinguishing: + + class X { + void a (Blah x) {} + void a (NS.Blah x) {} + } + + Which depending on the context might be valid or not, as we do not + know if Blah is the same thing as NS.Blah at that point. + + * Redid everything so the code uses TypeRefs now instead of + Types. TypeRefs are just temporary type placeholders, that need + to be resolved. They initially have a pointer to a string and the + current scope in which they are used. This is used later by the + compiler to resolve the reference to an actual Type. + + * DeclSpace is no longer a CIR.Type, and neither are + TypeContainers (Class and Struct) nor Interfaces nor Enums. They + are all DeclSpaces, but no Types. + + * type.cs (TypeRefManager): This implements the TypeRef manager, + which keeps track of all the types that need to be resolved after + the parsing has finished. + +2001-05-13 Miguel de Icaza + + * ARGH. We are going to have to store `foreach' as a class rather + than resolving it, as we need to verify error 1579 after name + resolution. *OR* we could keep a flag that says `This request to + IEnumerator comes from a foreach statement' which we can then use + to generate the error. + +2001-05-10 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod): we now add methods to the + MethodGroup instead of the method hashtable. + + * expression.cs: Add MethodGroup abstraction, which gets us one + step closer to the specification in the way we handle method + declarations. + + * cs-parser.jay (primary_expression): qualified_identifier now + tried to match up an identifier to a local variable reference or + to a parameter reference. + + current_local_parameters is now a parser global variable that + points to the current parameters for the block, used during name + lookup. + + (property_declaration): Now creates an implicit `value' argument to + the set accessor. + +2001-05-09 Miguel de Icaza + + * parameter.cs: Do not use `param' arguments as part of the + signature, per the spec. + +2001-05-08 Miguel de Icaza + + * decl.cs: Base class for classes, structs and interfaces. This + is the "Declaration Space" + + * cs-parser.jay: Use CheckDef for checking declaration errors + instead of having one on each function. + + * class.cs: Factor out some code for handling error handling in + accordance to the "Declarations" section in the "Basic Concepts" + chapter in the ECMA C# spec. + + * interface.cs: Make all interface member classes derive from + InterfaceMemberBase. + +2001-05-07 Miguel de Icaza + + * Many things: all interfaces are parsed and generated in + gen-treedump. Support for member variables, constructors, + destructors, properties, constants is there. + + Beginning of the IL backend, but very little done, just there for + testing purposes. + +2001-04-29 Miguel de Icaza + + * cs-parser.jay: Fix labeled statement. + + * cs-tokenizer.cs (escape): Escape " and ' always. + ref_line, ref_name: keep track of the line/filename as instructed + by #line by the compiler. + Parse #line. + +2001-04-27 Miguel de Icaza + + * System.CodeDOM/CodeBinaryOperatorExpression.cs: Rearrange enum + to match the values in System.CodeDOM. + + Divid renamed to Divide. + + * System.CodeDOM/CodeForLoopStatement.cs: Always have valid + statements. + (Statements.set): remove. + + * System.CodeDOM/CodeCatchClause.cs: always have a valid + statements. + + * System.CodeDOM/CodeIfStatement.cs: trueStatements and + falseStatements always have valid values. + + * cs-parser.jay: Use System.CodeDOM now. + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs new file mode 100644 index 0000000000..a56e94d01e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs @@ -0,0 +1,754 @@ +// +// CryptoConvert.cs - Crypto Convertion Routines +// +// Author: +// Sebastien Pouliot +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Globalization; +using System.Security.Cryptography; +using System.Text; + +namespace Mono.Security.Cryptography { + +#if INSIDE_CORLIB + internal +#else + public +#endif + sealed class CryptoConvert { + + private CryptoConvert () + { + } + + static private int ToInt32LE (byte [] bytes, int offset) + { + return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]; + } + + static private uint ToUInt32LE (byte [] bytes, int offset) + { + return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]); + } + + static private byte [] GetBytesLE (int val) + { + return new byte [] { + (byte) (val & 0xff), + (byte) ((val >> 8) & 0xff), + (byte) ((val >> 16) & 0xff), + (byte) ((val >> 24) & 0xff) + }; + } + + static private byte[] Trim (byte[] array) + { + for (int i=0; i < array.Length; i++) { + if (array [i] != 0x00) { + byte[] result = new byte [array.Length - i]; + Buffer.BlockCopy (array, i, result, 0, result.Length); + return result; + } + } + return null; + } + + // convert the key from PRIVATEKEYBLOB to RSA + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp + // e.g. SNK files, PVK files + static public RSA FromCapiPrivateKeyBlob (byte[] blob) + { + return FromCapiPrivateKeyBlob (blob, 0); + } + + static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + RSAParameters rsap = new RSAParameters (); + try { + if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + byte[] exp = new byte [4]; + Buffer.BlockCopy (blob, offset+16, exp, 0, 4); + Array.Reverse (exp); + rsap.Exponent = Trim (exp); + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); + pos += byteLen; + + // BYTE prime1[rsapubkey.bitlen/16]; + int byteHalfLen = (byteLen >> 1); + rsap.P = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen); + Array.Reverse (rsap.P); + pos += byteHalfLen; + + // BYTE prime2[rsapubkey.bitlen/16]; + rsap.Q = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen); + Array.Reverse (rsap.Q); + pos += byteHalfLen; + + // BYTE exponent1[rsapubkey.bitlen/16]; + rsap.DP = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen); + Array.Reverse (rsap.DP); + pos += byteHalfLen; + + // BYTE exponent2[rsapubkey.bitlen/16]; + rsap.DQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen); + Array.Reverse (rsap.DQ); + pos += byteHalfLen; + + // BYTE coefficient[rsapubkey.bitlen/16]; + rsap.InverseQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen); + Array.Reverse (rsap.InverseQ); + pos += byteHalfLen; + + // ok, this is hackish but CryptoAPI support it so... + // note: only works because CRT is used by default + // http://bugzilla.ximian.com/show_bug.cgi?id=57941 + rsap.D = new byte [byteLen]; // must be allocated + if (pos + byteLen + offset <= blob.Length) { + // BYTE privateExponent[rsapubkey.bitlen/8]; + Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen); + Array.Reverse (rsap.D); + } + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + +#if NET_2_1 + RSA rsa = RSA.Create (); + rsa.ImportParameters (rsap); +#else + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException ce) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + try { + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } + catch { + // rethrow original, not the later, exception if this fails + throw ce; + } + } +#endif + return rsa; + } + + static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob) + { + return FromCapiPrivateKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + DSAParameters dsap = new DSAParameters (); + try { + if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) + (blob [offset + 1] != 0x02) || // Version (0x02) + (blob [offset + 2] != 0x00) || // Reserved (word) + (blob [offset + 3] != 0x00) || + (ToUInt32LE (blob, offset + 8) != 0x32535344)) // DWORD magic + throw new CryptographicException ("Invalid blob header"); + + int bitlen = ToInt32LE (blob, offset + 12); + int bytelen = bitlen >> 3; + int pos = offset + 16; + + dsap.P = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen); + Array.Reverse (dsap.P); + pos += bytelen; + + dsap.Q = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20); + Array.Reverse (dsap.Q); + pos += 20; + + dsap.G = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen); + Array.Reverse (dsap.G); + pos += bytelen; + + dsap.X = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.X, 0, 20); + Array.Reverse (dsap.X); + pos += 20; + + dsap.Counter = ToInt32LE (blob, pos); + pos += 4; + + dsap.Seed = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20); + Array.Reverse (dsap.Seed); + pos += 20; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + +#if NET_2_1 + DSA dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); +#else + DSA dsa = null; + try { + dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); + } + catch (CryptographicException ce) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + try { + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + dsa = new DSACryptoServiceProvider (csp); + dsa.ImportParameters (dsap); + } + catch { + // rethrow original, not the later, exception if this fails + throw ce; + } + } +#endif + return dsa; + } + + static public byte[] ToCapiPrivateKeyBlob (RSA rsa) + { + RSAParameters p = rsa.ExportParameters (true); + int keyLength = p.Modulus.Length; // in bytes + byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)]; + + blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN) + blob [8] = 0x52; // Magic - RSA2 (ASCII in hex) + blob [9] = 0x53; + blob [10] = 0x41; + blob [11] = 0x32; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; // bitlen + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + // public exponent (DWORD) + int pos = 16; + int n = p.Exponent.Length; + while (n > 0) + blob [pos++] = p.Exponent [--n]; + // modulus + pos = 20; + byte[] part = p.Modulus; + int len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + // private key + part = p.P; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.Q; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.DP; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.DQ; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.InverseQ; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.D; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + + return blob; + } + + static public byte[] ToCapiPrivateKeyBlob (DSA dsa) + { + DSAParameters p = dsa.ExportParameters (true); + int keyLength = p.P.Length; // in bytes + + // header + P + Q + G + X + count + seed + byte[] blob = new byte [16 + keyLength + 20 + keyLength + 20 + 4 + 20]; + + blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x22; // ALGID + blob [8] = 0x44; // Magic + blob [9] = 0x53; + blob [10] = 0x53; + blob [11] = 0x32; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + int pos = 16; + byte[] part = p.P; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Q; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + part = p.G; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.X; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4); + pos += 4; + + part = p.Seed; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + + return blob; + } + + static public RSA FromCapiPublicKeyBlob (byte[] blob) + { + return FromCapiPublicKeyBlob (blob, 0); + } + + static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + try { + if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + RSAParameters rsap = new RSAParameters (); + rsap.Exponent = new byte [3]; + rsap.Exponent [0] = blob [offset+18]; + rsap.Exponent [1] = blob [offset+17]; + rsap.Exponent [2] = blob [offset+16]; + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); +#if NET_2_1 + RSA rsa = RSA.Create (); + rsa.ImportParameters (rsap); +#else + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } +#endif + return rsa; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + } + + static public DSA FromCapiPublicKeyBlobDSA (byte[] blob) + { + return FromCapiPublicKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiPublicKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + try { + if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) + (blob [offset + 1] != 0x02) || // Version (0x02) + (blob [offset + 2] != 0x00) || // Reserved (word) + (blob [offset + 3] != 0x00) || + (ToUInt32LE (blob, offset + 8) != 0x31535344)) // DWORD magic + throw new CryptographicException ("Invalid blob header"); + + int bitlen = ToInt32LE (blob, offset + 12); + DSAParameters dsap = new DSAParameters (); + int bytelen = bitlen >> 3; + int pos = offset + 16; + + dsap.P = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen); + Array.Reverse (dsap.P); + pos += bytelen; + + dsap.Q = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20); + Array.Reverse (dsap.Q); + pos += 20; + + dsap.G = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen); + Array.Reverse (dsap.G); + pos += bytelen; + + dsap.Y = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.Y, 0, bytelen); + Array.Reverse (dsap.Y); + pos += bytelen; + + dsap.Counter = ToInt32LE (blob, pos); + pos += 4; + + dsap.Seed = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20); + Array.Reverse (dsap.Seed); + pos += 20; + + DSA dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); + return dsa; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + } + + static public byte[] ToCapiPublicKeyBlob (RSA rsa) + { + RSAParameters p = rsa.ExportParameters (false); + int keyLength = p.Modulus.Length; // in bytes + byte[] blob = new byte [20 + keyLength]; + + blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN) + blob [8] = 0x52; // Magic - RSA1 (ASCII in hex) + blob [9] = 0x53; + blob [10] = 0x41; + blob [11] = 0x31; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; // bitlen + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + // public exponent (DWORD) + int pos = 16; + int n = p.Exponent.Length; + while (n > 0) + blob [pos++] = p.Exponent [--n]; + // modulus + pos = 20; + byte[] part = p.Modulus; + int len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + return blob; + } + + static public byte[] ToCapiPublicKeyBlob (DSA dsa) + { + DSAParameters p = dsa.ExportParameters (false); + int keyLength = p.P.Length; // in bytes + + // header + P + Q + G + Y + count + seed + byte[] blob = new byte [16 + keyLength + 20 + keyLength + keyLength + 4 + 20]; + + blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x22; // ALGID + blob [8] = 0x44; // Magic + blob [9] = 0x53; + blob [10] = 0x53; + blob [11] = 0x31; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + int pos = 16; + byte[] part; + + part = p.P; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Q; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + part = p.G; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Y; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4); + pos += 4; + + part = p.Seed; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + + return blob; + } + + // PRIVATEKEYBLOB + // PUBLICKEYBLOB + static public RSA FromCapiKeyBlob (byte[] blob) + { + return FromCapiKeyBlob (blob, 0); + } + + static public RSA FromCapiKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + switch (blob [offset]) { + case 0x00: + // this could be a public key inside an header + // like "sn -e" would produce + if (blob [offset + 12] == 0x06) { + return FromCapiPublicKeyBlob (blob, offset + 12); + } + break; + case 0x06: + return FromCapiPublicKeyBlob (blob, offset); + case 0x07: + return FromCapiPrivateKeyBlob (blob, offset); + } + throw new CryptographicException ("Unknown blob format."); + } + + static public DSA FromCapiKeyBlobDSA (byte[] blob) + { + return FromCapiKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + switch (blob [offset]) { + case 0x06: + return FromCapiPublicKeyBlobDSA (blob, offset); + case 0x07: + return FromCapiPrivateKeyBlobDSA (blob, offset); + } + throw new CryptographicException ("Unknown blob format."); + } + + static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey) + { + if (keypair == null) + throw new ArgumentNullException ("keypair"); + + // check between RSA and DSA (and potentially others like DH) + if (keypair is RSA) + return ToCapiKeyBlob ((RSA)keypair, includePrivateKey); + else if (keypair is DSA) + return ToCapiKeyBlob ((DSA)keypair, includePrivateKey); + else + return null; // TODO + } + + static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey) + { + if (rsa == null) + throw new ArgumentNullException ("rsa"); + + if (includePrivateKey) + return ToCapiPrivateKeyBlob (rsa); + else + return ToCapiPublicKeyBlob (rsa); + } + + static public byte[] ToCapiKeyBlob (DSA dsa, bool includePrivateKey) + { + if (dsa == null) + throw new ArgumentNullException ("dsa"); + + if (includePrivateKey) + return ToCapiPrivateKeyBlob (dsa); + else + return ToCapiPublicKeyBlob (dsa); + } + + static public string ToHex (byte[] input) + { + if (input == null) + return null; + + StringBuilder sb = new StringBuilder (input.Length * 2); + foreach (byte b in input) { + sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture)); + } + return sb.ToString (); + } + + static private byte FromHexChar (char c) + { + if ((c >= 'a') && (c <= 'f')) + return (byte) (c - 'a' + 10); + if ((c >= 'A') && (c <= 'F')) + return (byte) (c - 'A' + 10); + if ((c >= '0') && (c <= '9')) + return (byte) (c - '0'); + throw new ArgumentException ("invalid hex char"); + } + + static public byte[] FromHex (string hex) + { + if (hex == null) + return null; + if ((hex.Length & 0x1) == 0x1) + throw new ArgumentException ("Length must be a multiple of 2"); + + byte[] result = new byte [hex.Length >> 1]; + int n = 0; + int i = 0; + while (n < result.Length) { + result [n] = (byte) (FromHexChar (hex [i++]) << 4); + result [n++] += FromHexChar (hex [i++]); + } + return result; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile new file mode 100644 index 0000000000..43a2780851 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile @@ -0,0 +1,126 @@ +thisdir := mcs +SUBDIRS := +include ../build/rules.make + +EXTRA_DISTFILES = \ + *mcs.csproj \ + compiler.doc \ + *mcs.sln \ + *cs-parser.jay \ + *.sources \ + NOTES \ + TODO \ + *mcs.exe.config + +COMPILER_NAME = gmcs + +ifeq (net_2_0, $(PROFILE)) +INTERNAL_GMCS = $(RUNTIME) $(RUNTIME_FLAGS) $(topdir)/class/lib/$(BOOTSTRAP_PROFILE)/gmcs.exe +endif + +ifeq (moonlight_bootstrap, $(PROFILE)) +INTERNAL_GMCS = $(RUNTIME) $(RUNTIME_FLAGS) $(topdir)/class/lib/$(BOOTSTRAP_PROFILE)/gmcs.exe +endif + +ifeq (2.1, $(FRAMEWORK_VERSION)) +LOCAL_MCS_FLAGS += -d:SMCS_SOURCE +COMPILER_NAME = smcs +endif + +ifeq (4.0, $(FRAMEWORK_VERSION)) +COMPILER_NAME = dmcs +endif + +PROGRAM = $(topdir)/class/lib/$(PROFILE)/$(COMPILER_NAME).exe + +BUILT_SOURCES = cs-parser.cs + +PROGRAM_COMPILE = $(BOOT_COMPILE) + +CLEAN_FILES += y.output + +%-parser.cs: %-parser.jay $(topdir)/jay/skeleton.cs + $(topdir)/jay/jay -cvt < $(topdir)/jay/skeleton.cs $< > jay-tmp.out && mv jay-tmp.out $@ + + +KEEP_OUTPUT_FILE_COPY = yes + +include ../build/executable.make + +csproj-local: + config_file=`basename $(PROGRAM) .exe`-$(PROFILE).input; \ + echo $(thisdir):$$config_file >> $(topdir)/../mono/msvc/scripts/order; \ + (echo $(is_boot); \ + echo $(BOOTSTRAP_MCS); \ + echo $(USE_MCS_FLAGS) $(LIBRARY_FLAGS) $(LIB_MCS_FLAGS); \ + echo $(PROGRAM); \ + echo $(BUILT_SOURCES); \ + echo $(PROGRAM); \ + echo $(response)) > $(topdir)/../mono/msvc/scripts/inputs/$$config_file + +# +# Below this line we have local targets used for testing and development +# + +# Testing targets + +TIME = time + +# This used to be called test, but that conflicts with the global +# recursive target. + +btest: mcs2.exe mcs3.exe + ls -l mcs2.exe mcs3.exe + +mcs2.exe: $(PROGRAM) + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + +mcs3.exe: mcs2.exe + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + +wc: + wc -l $(BUILT_SOURCES) `cat $(sourcefile)` + +ctest: + rm -f mcs2.exe mcs3.exe + $(MAKE) USE_MCS_FLAGS="-d:NET_1_1 -d:ONLY_1_1" btest + +# we need this because bash tries to use its own crappy timer +FRIENDLY_TIME = $(shell which time) -f'%U seconds' + +do-time : $(PROGRAM) + @ echo -n "Run 1: " + @ rm -f mcs2.exe + @ $(MAKE) TIME="$(FRIENDLY_TIME)" mcs2.exe > /dev/null || (echo FAILED; exit 1) + @ echo -n "Run 2: " + @ rm -f mcs3.exe + @ $(MAKE) TIME="$(FRIENDLY_TIME)" mcs3.exe > /dev/null || (echo FAILED; exit 1) + @ $(MAKE) do-corlib + +do-corlib: + @ echo -n "corlib: " + @ rm -f ../class/lib/mscorlib.dll + @ cd ../class/corlib ; $(MAKE) BOOTSTRAP_MCS='$(FRIENDLY_TIME) mono $$(topdir)/class/lib/$(PROFILE)/mcs.exe' > /dev/null || (echo FAILED; exit 1) + +PROFILER=default + +do-gettext: + xgettext --keyword='Report.Error:3' --keyword='Report.Error:2' --keyword='Report.Warning:3' --keyword='Report.Warning:2' -o mcs.po --language='C#' `cat gmcs.exe.sources | grep -v /` + +profile : $(PROGRAM) + $(RUNTIME) $(RUNTIME_FLAGS) --profile=$(PROFILER) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:mcs2.exe $(BUILT_SOURCES) @$(response) + +# +# quick hack target, to quickly develop the gmcs compiler +# Update manually. + +q: cs-parser.cs qh + echo 'System.Console.WriteLine ("Hello");' | mono csharp.exe + echo -e 'using System;\nConsole.WriteLine ("hello");' | mono csharp.exe + echo -e '"foo" == "bar";' | mono csharp.exe + echo -e 'var a = 1;\na + 2;' | mono csharp.exe + echo -e 'int j;\nj = 1;' | mono csharp.exe + echo -e 'var a = new int[]{1,2,3};\nfrom x in a select x;' | mono csharp.exe + echo -e 'var a = from f in System.IO.Directory.GetFiles ("/tmp") where f == "passwd" select f;' | mono csharp.exe + + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs new file mode 100644 index 0000000000..465f4c7cbe --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs @@ -0,0 +1,723 @@ +// +// Mono.CSharp.Debugger/MonoSymbolFile.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2003 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using SRE = System.Reflection.Emit; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolFileException : Exception + { + public MonoSymbolFileException () + : base () + { } + + public MonoSymbolFileException (string message, params object[] args) + : base (String.Format (message, args)) + { } + } + + internal class MyBinaryWriter : BinaryWriter + { + public MyBinaryWriter (Stream stream) + : base (stream) + { } + + public void WriteLeb128 (int value) + { + base.Write7BitEncodedInt (value); + } + } + + internal class MyBinaryReader : BinaryReader + { + public MyBinaryReader (Stream stream) + : base (stream) + { } + + public int ReadLeb128 () + { + return base.Read7BitEncodedInt (); + } + + public string ReadString (int offset) + { + long old_pos = BaseStream.Position; + BaseStream.Position = offset; + + string text = ReadString (); + + BaseStream.Position = old_pos; + return text; + } + } + + public interface ISourceFile + { + SourceFileEntry Entry { + get; + } + } + + public interface ICompileUnit + { + CompileUnitEntry Entry { + get; + } + } + + public interface IMethodDef + { + string Name { + get; + } + + int Token { + get; + } + } + +#if !CECIL + // TODO: Obsolete under .net 4 + internal class MonoDebuggerSupport + { + static GetMethodTokenFunc get_method_token; + static GetGuidFunc get_guid; + + delegate int GetMethodTokenFunc (MethodBase method); + delegate Guid GetGuidFunc (Module module); + + static Delegate create_delegate (Type type, Type delegate_type, string name) + { + MethodInfo mi = type.GetMethod (name, BindingFlags.Static | + BindingFlags.NonPublic); + if (mi == null) + throw new Exception ("Can't find " + name); + + return Delegate.CreateDelegate (delegate_type, mi); + } + + static MonoDebuggerSupport () + { + get_method_token = (GetMethodTokenFunc) create_delegate ( + typeof (Assembly), typeof (GetMethodTokenFunc), + "MonoDebugger_GetMethodToken"); + + get_guid = (GetGuidFunc) create_delegate ( + typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid"); + } + + public static int GetMethodToken (MethodBase method) + { + return get_method_token (method); + } + + public static Guid GetGuid (Module module) + { + return get_guid (module); + } + } +#endif + + public class MonoSymbolFile : IDisposable + { + List methods = new List (); + List sources = new List (); + List comp_units = new List (); + Dictionary type_hash = new Dictionary (); + Dictionary anonymous_scopes; + + OffsetTable ot; + int last_type_index; + int last_method_index; + int last_namespace_index; + + public readonly string FileName = ""; + public readonly int MajorVersion = OffsetTable.MajorVersion; + public readonly int MinorVersion = OffsetTable.MinorVersion; + + public int NumLineNumbers; + + internal MonoSymbolFile () + { + ot = new OffsetTable (); + } + + internal int AddSource (SourceFileEntry source) + { + sources.Add (source); + return sources.Count; + } + + internal int AddCompileUnit (CompileUnitEntry entry) + { + comp_units.Add (entry); + return comp_units.Count; + } + + internal int DefineType (Type type) + { + int index; + if (type_hash.TryGetValue (type, out index)) + return index; + + index = ++last_type_index; + type_hash.Add (type, index); + return index; + } + + internal void AddMethod (MethodEntry entry) + { + methods.Add (entry); + } + + public MethodEntry DefineMethod (CompileUnitEntry comp_unit, int token, + ScopeVariable[] scope_vars, LocalVariableEntry[] locals, + LineNumberEntry[] lines, CodeBlockEntry[] code_blocks, + string real_name, MethodEntry.Flags flags, + int namespace_id) + { + if (reader != null) + throw new InvalidOperationException (); + + MethodEntry method = new MethodEntry ( + this, comp_unit, token, scope_vars, locals, lines, code_blocks, + real_name, flags, namespace_id); + AddMethod (method); + return method; + } + + internal void DefineAnonymousScope (int id) + { + if (reader != null) + throw new InvalidOperationException (); + + if (anonymous_scopes == null) + anonymous_scopes = new Dictionary (); + + anonymous_scopes.Add (id, new AnonymousScopeEntry (id)); + } + + internal void DefineCapturedVariable (int scope_id, string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedVariable (name, captured_name, kind); + } + + internal void DefineCapturedScope (int scope_id, int id, string captured_name) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedScope (id, captured_name); + } + + internal int GetNextTypeIndex () + { + return ++last_type_index; + } + + internal int GetNextMethodIndex () + { + return ++last_method_index; + } + + internal int GetNextNamespaceIndex () + { + return ++last_namespace_index; + } + + void Write (MyBinaryWriter bw, Guid guid) + { + // Magic number and file version. + bw.Write (OffsetTable.Magic); + bw.Write (MajorVersion); + bw.Write (MinorVersion); + + bw.Write (guid.ToByteArray ()); + + // + // Offsets of file sections; we must write this after we're done + // writing the whole file, so we just reserve the space for it here. + // + long offset_table_offset = bw.BaseStream.Position; + ot.Write (bw, MajorVersion, MinorVersion); + + // + // Sort the methods according to their tokens and update their index. + // + methods.Sort (); + for (int i = 0; i < methods.Count; i++) + ((MethodEntry) methods [i]).Index = i + 1; + + // + // Write data sections. + // + ot.DataSectionOffset = (int) bw.BaseStream.Position; + foreach (SourceFileEntry source in sources) + source.WriteData (bw); + foreach (CompileUnitEntry comp_unit in comp_units) + comp_unit.WriteData (bw); + foreach (MethodEntry method in methods) + method.WriteData (this, bw); + ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset; + + // + // Write the method index table. + // + ot.MethodTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < methods.Count; i++) { + MethodEntry entry = (MethodEntry) methods [i]; + entry.Write (bw); + } + ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset; + + // + // Write source table. + // + ot.SourceTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < sources.Count; i++) { + SourceFileEntry source = (SourceFileEntry) sources [i]; + source.Write (bw); + } + ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset; + + // + // Write compilation unit table. + // + ot.CompileUnitTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < comp_units.Count; i++) { + CompileUnitEntry unit = (CompileUnitEntry) comp_units [i]; + unit.Write (bw); + } + ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset; + + // + // Write anonymous scope table. + // + ot.AnonymousScopeCount = anonymous_scopes != null ? anonymous_scopes.Count : 0; + ot.AnonymousScopeTableOffset = (int) bw.BaseStream.Position; + if (anonymous_scopes != null) { + foreach (AnonymousScopeEntry scope in anonymous_scopes.Values) + scope.Write (bw); + } + ot.AnonymousScopeTableSize = (int) bw.BaseStream.Position - ot.AnonymousScopeTableOffset; + + // + // Fixup offset table. + // + ot.TypeCount = last_type_index; + ot.MethodCount = methods.Count; + ot.SourceCount = sources.Count; + ot.CompileUnitCount = comp_units.Count; + + // + // Write offset table. + // + ot.TotalFileSize = (int) bw.BaseStream.Position; + bw.Seek ((int) offset_table_offset, SeekOrigin.Begin); + ot.Write (bw, MajorVersion, MinorVersion); + bw.Seek (0, SeekOrigin.End); + +#if false + Console.WriteLine ("TOTAL: {0} line numbes, {1} bytes, extended {2} bytes, " + + "{3} methods.", NumLineNumbers, LineNumberSize, + ExtendedLineNumberSize, methods.Count); +#endif + } + + public void CreateSymbolFile (Guid guid, FileStream fs) + { + if (reader != null) + throw new InvalidOperationException (); + + Write (new MyBinaryWriter (fs), guid); + } + + MyBinaryReader reader; + Dictionary source_file_hash; + Dictionary compile_unit_hash; + + List method_list; + Dictionary method_token_hash; + Dictionary source_name_hash; + + Guid guid; + + MonoSymbolFile (string filename) + { + this.FileName = filename; + FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read); + reader = new MyBinaryReader (stream); + + try { + long magic = reader.ReadInt64 (); + int major_version = reader.ReadInt32 (); + int minor_version = reader.ReadInt32 (); + + if (magic != OffsetTable.Magic) + throw new MonoSymbolFileException ( + "Symbol file `{0}' is not a valid " + + "Mono symbol file", filename); + if (major_version != OffsetTable.MajorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}, " + + "but expected {2}", filename, major_version, + OffsetTable.MajorVersion); + if (minor_version != OffsetTable.MinorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}.{2}, " + + "but expected {3}.{4}", filename, major_version, + minor_version, OffsetTable.MajorVersion, + OffsetTable.MinorVersion); + + MajorVersion = major_version; + MinorVersion = minor_version; + guid = new Guid (reader.ReadBytes (16)); + + ot = new OffsetTable (reader, major_version, minor_version); + } catch { + throw new MonoSymbolFileException ( + "Cannot read symbol file `{0}'", filename); + } + + source_file_hash = new Dictionary (); + compile_unit_hash = new Dictionary (); + } + + void CheckGuidMatch (Guid other, string filename, string assembly) + { + if (other == guid) + return; + + throw new MonoSymbolFileException ( + "Symbol file `{0}' does not match assembly `{1}'", + filename, assembly); + } + +#if CECIL + protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module) + : this (filename) + { + CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module) + { + return ReadSymbolFile (module, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module, string filename) + { + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, module); + } +#else + protected MonoSymbolFile (string filename, Assembly assembly) : this (filename) + { + // Check that the MDB file matches the assembly, if we have been + // passed an assembly. + if (assembly == null) + return; + + Module[] modules = assembly.GetModules (); + Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]); + + CheckGuidMatch (assembly_guid, filename, assembly.Location); + } + + public static MonoSymbolFile ReadSymbolFile (Assembly assembly) + { + string filename = assembly.Location; + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, assembly); + } +#endif + + public static MonoSymbolFile ReadSymbolFile (string mdbFilename) + { + return new MonoSymbolFile (mdbFilename, null); + } + + public int CompileUnitCount { + get { return ot.CompileUnitCount; } + } + + public int SourceCount { + get { return ot.SourceCount; } + } + + public int MethodCount { + get { return ot.MethodCount; } + } + + public int TypeCount { + get { return ot.TypeCount; } + } + + public int AnonymousScopeCount { + get { return ot.AnonymousScopeCount; } + } + + public int NamespaceCount { + get { return last_namespace_index; } + } + + public Guid Guid { + get { return guid; } + } + + public OffsetTable OffsetTable { + get { return ot; } + } + + internal int LineNumberCount = 0; + internal int LocalCount = 0; + internal int StringSize = 0; + + internal int LineNumberSize = 0; + internal int ExtendedLineNumberSize = 0; + + public SourceFileEntry GetSourceFile (int index) + { + if ((index < 1) || (index > ot.SourceCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + SourceFileEntry source; + if (source_file_hash.TryGetValue (index, out source)) + return source; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.SourceTableOffset + + SourceFileEntry.Size * (index - 1); + source = new SourceFileEntry (this, reader); + source_file_hash.Add (index, source); + + reader.BaseStream.Position = old_pos; + return source; + } + } + + public SourceFileEntry[] Sources { + get { + if (reader == null) + throw new InvalidOperationException (); + + SourceFileEntry[] retval = new SourceFileEntry [SourceCount]; + for (int i = 0; i < SourceCount; i++) + retval [i] = GetSourceFile (i + 1); + return retval; + } + } + + public CompileUnitEntry GetCompileUnit (int index) + { + if ((index < 1) || (index > ot.CompileUnitCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + CompileUnitEntry unit; + if (compile_unit_hash.TryGetValue (index, out unit)) + return unit; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.CompileUnitTableOffset + + CompileUnitEntry.Size * (index - 1); + unit = new CompileUnitEntry (this, reader); + compile_unit_hash.Add (index, unit); + + reader.BaseStream.Position = old_pos; + return unit; + } + } + + public CompileUnitEntry[] CompileUnits { + get { + if (reader == null) + throw new InvalidOperationException (); + + CompileUnitEntry[] retval = new CompileUnitEntry [CompileUnitCount]; + for (int i = 0; i < CompileUnitCount; i++) + retval [i] = GetCompileUnit (i + 1); + return retval; + } + } + + void read_methods () + { + lock (this) { + if (method_token_hash != null) + return; + + method_token_hash = new Dictionary (); + method_list = new List (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ot.MethodTableOffset; + + for (int i = 0; i < MethodCount; i++) { + MethodEntry entry = new MethodEntry (this, reader, i + 1); + method_token_hash.Add (entry.Token, entry); + method_list.Add (entry); + } + + reader.BaseStream.Position = old_pos; + } + } + + public MethodEntry GetMethodByToken (int token) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry me; + method_token_hash.TryGetValue (token, out me); + return me; + } + } + + public MethodEntry GetMethod (int index) + { + if ((index < 1) || (index > ot.MethodCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + return (MethodEntry) method_list [index - 1]; + } + } + + public MethodEntry[] Methods { + get { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry[] retval = new MethodEntry [MethodCount]; + method_list.CopyTo (retval, 0); + return retval; + } + } + } + + public int FindSource (string file_name) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + if (source_name_hash == null) { + source_name_hash = new Dictionary (); + + for (int i = 0; i < ot.SourceCount; i++) { + SourceFileEntry source = GetSourceFile (i + 1); + source_name_hash.Add (source.FileName, i); + } + } + + int value; + if (!source_name_hash.TryGetValue (file_name, out value)) + return -1; + return value; + } + } + + public AnonymousScopeEntry GetAnonymousScope (int id) + { + if (reader == null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope; + lock (this) { + if (anonymous_scopes != null) { + anonymous_scopes.TryGetValue (id, out scope); + return scope; + } + + anonymous_scopes = new Dictionary (); + reader.BaseStream.Position = ot.AnonymousScopeTableOffset; + for (int i = 0; i < ot.AnonymousScopeCount; i++) { + scope = new AnonymousScopeEntry (reader); + anonymous_scopes.Add (scope.ID, scope); + } + + return anonymous_scopes [id]; + } + } + + internal MyBinaryReader BinaryReader { + get { + if (reader == null) + throw new InvalidOperationException (); + + return reader; + } + } + + public void Dispose () + { + Dispose (true); + } + + protected virtual void Dispose (bool disposing) + { + if (disposing) { + if (reader != null) { + reader.Close (); + reader = null; + } + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs new file mode 100644 index 0000000000..5f30818ff6 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs @@ -0,0 +1,1376 @@ +// +// Mono.CSharp.Debugger/MonoSymbolTable.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2002 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Security.Cryptography; +using System.Collections.Generic; +using System.Text; +using System.IO; + +// +// Parts which are actually written into the symbol file are marked with +// +// #region This is actually written to the symbol file +// #endregion +// +// Please do not modify these regions without previously talking to me. +// +// All changes to the file format must be synchronized in several places: +// +// a) The fields in these regions (and their order) must match the actual +// contents of the symbol file. +// +// This helps people to understand the symbol file format without reading +// too much source code, ie. you look at the appropriate region and then +// you know what's actually in the file. +// +// It is also required to help me enforce b). +// +// b) The regions must be kept in sync with the unmanaged code in +// mono/metadata/debug-mono-symfile.h +// +// When making changes to the file format, you must also increase two version +// numbers: +// +// i) OffsetTable.Version in this file. +// ii) MONO_SYMBOL_FILE_VERSION in mono/metadata/debug-mono-symfile.h +// +// After doing so, recompile everything, including the debugger. Symbol files +// with different versions are incompatible to each other and the debugger and +// the runtime enfore this, so you need to recompile all your assemblies after +// changing the file format. +// + +namespace Mono.CompilerServices.SymbolWriter +{ + public class OffsetTable + { + public const int MajorVersion = 50; + public const int MinorVersion = 0; + public const long Magic = 0x45e82623fd7fa614; + + #region This is actually written to the symbol file + public int TotalFileSize; + public int DataSectionOffset; + public int DataSectionSize; + public int CompileUnitCount; + public int CompileUnitTableOffset; + public int CompileUnitTableSize; + public int SourceCount; + public int SourceTableOffset; + public int SourceTableSize; + public int MethodCount; + public int MethodTableOffset; + public int MethodTableSize; + public int TypeCount; + public int AnonymousScopeCount; + public int AnonymousScopeTableOffset; + public int AnonymousScopeTableSize; + + [Flags] + public enum Flags + { + IsAspxSource = 1, + WindowsFileNames = 2 + } + + public Flags FileFlags; + + public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase; + public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange; + public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase; + #endregion + + internal OffsetTable () + { + int platform = (int) Environment.OSVersion.Platform; + if ((platform != 4) && (platform != 128)) + FileFlags |= Flags.WindowsFileNames; + } + + internal OffsetTable (BinaryReader reader, int major_version, int minor_version) + { + TotalFileSize = reader.ReadInt32 (); + DataSectionOffset = reader.ReadInt32 (); + DataSectionSize = reader.ReadInt32 (); + CompileUnitCount = reader.ReadInt32 (); + CompileUnitTableOffset = reader.ReadInt32 (); + CompileUnitTableSize = reader.ReadInt32 (); + SourceCount = reader.ReadInt32 (); + SourceTableOffset = reader.ReadInt32 (); + SourceTableSize = reader.ReadInt32 (); + MethodCount = reader.ReadInt32 (); + MethodTableOffset = reader.ReadInt32 (); + MethodTableSize = reader.ReadInt32 (); + TypeCount = reader.ReadInt32 (); + + AnonymousScopeCount = reader.ReadInt32 (); + AnonymousScopeTableOffset = reader.ReadInt32 (); + AnonymousScopeTableSize = reader.ReadInt32 (); + + LineNumberTable_LineBase = reader.ReadInt32 (); + LineNumberTable_LineRange = reader.ReadInt32 (); + LineNumberTable_OpcodeBase = reader.ReadInt32 (); + + FileFlags = (Flags) reader.ReadInt32 (); + } + + internal void Write (BinaryWriter bw, int major_version, int minor_version) + { + bw.Write (TotalFileSize); + bw.Write (DataSectionOffset); + bw.Write (DataSectionSize); + bw.Write (CompileUnitCount); + bw.Write (CompileUnitTableOffset); + bw.Write (CompileUnitTableSize); + bw.Write (SourceCount); + bw.Write (SourceTableOffset); + bw.Write (SourceTableSize); + bw.Write (MethodCount); + bw.Write (MethodTableOffset); + bw.Write (MethodTableSize); + bw.Write (TypeCount); + + bw.Write (AnonymousScopeCount); + bw.Write (AnonymousScopeTableOffset); + bw.Write (AnonymousScopeTableSize); + + bw.Write (LineNumberTable_LineBase); + bw.Write (LineNumberTable_LineRange); + bw.Write (LineNumberTable_OpcodeBase); + + bw.Write ((int) FileFlags); + } + + public override string ToString () + { + return String.Format ( + "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]", + TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount, + SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset, + MethodTableSize, TypeCount); + } + } + + public class LineNumberEntry + { + #region This is actually written to the symbol file + public readonly int Row; + public readonly int File; + public readonly int Offset; + public readonly bool IsHidden; + #endregion + + public LineNumberEntry (int file, int row, int offset) + : this (file, row, offset, false) + { } + + public LineNumberEntry (int file, int row, int offset, bool is_hidden) + { + this.File = file; + this.Row = row; + this.Offset = offset; + this.IsHidden = is_hidden; + } + + public static LineNumberEntry Null = new LineNumberEntry (0, 0, 0); + + private class OffsetComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Offset < l2.Offset) + return -1; + else if (l1.Offset > l2.Offset) + return 1; + else + return 0; + } + } + + private class RowComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Row < l2.Row) + return -1; + else if (l1.Row > l2.Row) + return 1; + else + return 0; + } + } + + public static readonly IComparer OffsetComparer = new OffsetComparerClass (); + public static readonly IComparer RowComparer = new RowComparerClass (); + + public override string ToString () + { + return String.Format ("[Line {0}:{1}:{2}]", File, Row, Offset); + } + } + + public class CodeBlockEntry + { + public int Index; + #region This is actually written to the symbol file + public int Parent; + public Type BlockType; + public int StartOffset; + public int EndOffset; + #endregion + + public enum Type { + Lexical = 1, + CompilerGenerated = 2, + IteratorBody = 3, + IteratorDispatcher = 4 + } + + public CodeBlockEntry (int index, int parent, Type type, int start_offset) + { + this.Index = index; + this.Parent = parent; + this.BlockType = type; + this.StartOffset = start_offset; + } + + internal CodeBlockEntry (int index, MyBinaryReader reader) + { + this.Index = index; + int type_flag = reader.ReadLeb128 (); + BlockType = (Type) (type_flag & 0x3f); + this.Parent = reader.ReadLeb128 (); + this.StartOffset = reader.ReadLeb128 (); + this.EndOffset = reader.ReadLeb128 (); + + /* Reserved for future extensions. */ + if ((type_flag & 0x40) != 0) { + int data_size = reader.ReadInt16 (); + reader.BaseStream.Position += data_size; + } + } + + public void Close (int end_offset) + { + this.EndOffset = end_offset; + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 ((int) BlockType); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (StartOffset); + bw.WriteLeb128 (EndOffset); + } + + public override string ToString () + { + return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]", + Index, Parent, BlockType, StartOffset, EndOffset); + } + } + + public struct LocalVariableEntry + { + #region This is actually written to the symbol file + public readonly int Index; + public readonly string Name; + public readonly int BlockIndex; + #endregion + + public LocalVariableEntry (int index, string name, int block) + { + this.Index = index; + this.Name = name; + this.BlockIndex = block; + } + + internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Index = reader.ReadLeb128 (); + Name = reader.ReadString (); + BlockIndex = reader.ReadLeb128 (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.WriteLeb128 (Index); + bw.Write (Name); + bw.WriteLeb128 (BlockIndex); + } + + public override string ToString () + { + return String.Format ("[LocalVariable {0}:{1}:{2}]", + Name, Index, BlockIndex - 1); + } + } + + public struct CapturedVariable + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly string CapturedName; + public readonly CapturedKind Kind; + #endregion + + public enum CapturedKind : byte + { + Local, + Parameter, + This + } + + public CapturedVariable (string name, string captured_name, + CapturedKind kind) + { + this.Name = name; + this.CapturedName = captured_name; + this.Kind = kind; + } + + internal CapturedVariable (MyBinaryReader reader) + { + Name = reader.ReadString (); + CapturedName = reader.ReadString (); + Kind = (CapturedKind) reader.ReadByte (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.Write (Name); + bw.Write (CapturedName); + bw.Write ((byte) Kind); + } + + public override string ToString () + { + return String.Format ("[CapturedVariable {0}:{1}:{2}]", + Name, CapturedName, Kind); + } + } + + public struct CapturedScope + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly string CapturedName; + #endregion + + public CapturedScope (int scope, string captured_name) + { + this.Scope = scope; + this.CapturedName = captured_name; + } + + internal CapturedScope (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + CapturedName = reader.ReadString (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.Write (CapturedName); + } + + public override string ToString () + { + return String.Format ("[CapturedScope {0}:{1}]", + Scope, CapturedName); + } + } + + public struct ScopeVariable + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly int Index; + #endregion + + public ScopeVariable (int scope, int index) + { + this.Scope = scope; + this.Index = index; + } + + internal ScopeVariable (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + Index = reader.ReadLeb128 (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.WriteLeb128 (Index); + } + + public override string ToString () + { + return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index); + } + } + + public class AnonymousScopeEntry + { + #region This is actually written to the symbol file + public readonly int ID; + #endregion + + List captured_vars = new List (); + List captured_scopes = new List (); + + public AnonymousScopeEntry (int id) + { + this.ID = id; + } + + internal AnonymousScopeEntry (MyBinaryReader reader) + { + ID = reader.ReadLeb128 (); + + int num_captured_vars = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_vars; i++) + captured_vars.Add (new CapturedVariable (reader)); + + int num_captured_scopes = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_scopes; i++) + captured_scopes.Add (new CapturedScope (reader)); + } + + internal void AddCapturedVariable (string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + captured_vars.Add (new CapturedVariable (name, captured_name, kind)); + } + + public CapturedVariable[] CapturedVariables { + get { + CapturedVariable[] retval = new CapturedVariable [captured_vars.Count]; + captured_vars.CopyTo (retval, 0); + return retval; + } + } + + internal void AddCapturedScope (int scope, string captured_name) + { + captured_scopes.Add (new CapturedScope (scope, captured_name)); + } + + public CapturedScope[] CapturedScopes { + get { + CapturedScope[] retval = new CapturedScope [captured_scopes.Count]; + captured_scopes.CopyTo (retval, 0); + return retval; + } + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (ID); + + bw.WriteLeb128 (captured_vars.Count); + foreach (CapturedVariable cv in captured_vars) + cv.Write (bw); + + bw.WriteLeb128 (captured_scopes.Count); + foreach (CapturedScope cs in captured_scopes) + cs.Write (bw); + } + + public override string ToString () + { + return String.Format ("[AnonymousScope {0}]", ID); + } + } + + public class CompileUnitEntry : ICompileUnit + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + SourceFileEntry source; + List include_files; + List namespaces; + + bool creating; + + public static int Size { + get { return 8; } + } + + CompileUnitEntry ICompileUnit.Entry { + get { return this; } + } + + public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source) + { + this.file = file; + this.source = source; + + this.Index = file.AddCompileUnit (this); + + creating = true; + namespaces = new List (); + } + + public void AddFile (SourceFileEntry file) + { + if (!creating) + throw new InvalidOperationException (); + + if (include_files == null) + include_files = new List (); + + include_files.Add (file); + } + + public SourceFileEntry SourceFile { + get { + if (creating) + return source; + + ReadData (); + return source; + } + } + + public int DefineNamespace (string name, string[] using_clauses, int parent) + { + if (!creating) + throw new InvalidOperationException (); + + int index = file.GetNextNamespaceIndex (); + NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent); + namespaces.Add (ns); + return index; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.WriteLeb128 (source.Index); + + int count_includes = include_files != null ? include_files.Count : 0; + bw.WriteLeb128 (count_includes); + if (include_files != null) { + foreach (SourceFileEntry entry in include_files) + bw.WriteLeb128 (entry.Index); + } + + bw.WriteLeb128 (namespaces.Count); + foreach (NamespaceEntry ns in namespaces) + ns.Write (file, bw); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + } + + void ReadData () + { + if (creating) + throw new InvalidOperationException (); + + lock (file) { + if (namespaces != null) + return; + + MyBinaryReader reader = file.BinaryReader; + int old_pos = (int) reader.BaseStream.Position; + + reader.BaseStream.Position = DataOffset; + + int source_idx = reader.ReadLeb128 (); + source = file.GetSourceFile (source_idx); + + int count_includes = reader.ReadLeb128 (); + if (count_includes > 0) { + include_files = new List (); + for (int i = 0; i < count_includes; i++) + include_files.Add (file.GetSourceFile (reader.ReadLeb128 ())); + } + + int count_ns = reader.ReadLeb128 (); + namespaces = new List (); + for (int i = 0; i < count_ns; i ++) + namespaces.Add (new NamespaceEntry (file, reader)); + + reader.BaseStream.Position = old_pos; + } + } + + public NamespaceEntry[] Namespaces { + get { + ReadData (); + NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count]; + namespaces.CopyTo (retval, 0); + return retval; + } + } + + public SourceFileEntry[] IncludeFiles { + get { + ReadData (); + if (include_files == null) + return new SourceFileEntry [0]; + + SourceFileEntry[] retval = new SourceFileEntry [include_files.Count]; + include_files.CopyTo (retval, 0); + return retval; + } + } + } + + public class SourceFileEntry + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + string file_name; + byte[] guid; + byte[] hash; + bool creating; + bool auto_generated; + + public static int Size { + get { return 8; } + } + + public SourceFileEntry (MonoSymbolFile file, string file_name) + { + this.file = file; + this.file_name = file_name; + this.Index = file.AddSource (this); + + creating = true; + } + + public SourceFileEntry (MonoSymbolFile file, string file_name, + byte[] guid, byte[] checksum) + : this (file, file_name) + { + this.guid = guid; + this.hash = checksum; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.Write (file_name); + + if (guid == null) { + guid = Guid.NewGuid ().ToByteArray (); + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) { + MD5 md5 = MD5.Create (); + hash = md5.ComputeHash (fs); + } + } catch { + hash = new byte [16]; + } + } + + bw.Write (guid); + bw.Write (hash); + bw.Write ((byte) (auto_generated ? 1 : 0)); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + + int old_pos = (int) reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + file_name = reader.ReadString (); + guid = reader.ReadBytes (16); + hash = reader.ReadBytes (16); + auto_generated = reader.ReadByte () == 1; + + reader.BaseStream.Position = old_pos; + } + + public string FileName { + get { return file_name; } + } + + public bool AutoGenerated { + get { return auto_generated; } + } + + public void SetAutoGenerated () + { + if (!creating) + throw new InvalidOperationException (); + + auto_generated = true; + file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource; + } + + public bool CheckChecksum () + { + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open)) { + MD5 md5 = MD5.Create (); + byte[] data = md5.ComputeHash (fs); + for (int i = 0; i < 16; i++) + if (data [i] != hash [i]) + return false; + return true; + } + } catch { + return false; + } + } + + public override string ToString () + { + return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset); + } + } + + public class LineNumberTable + { + protected LineNumberEntry[] _line_numbers; + public LineNumberEntry[] LineNumbers { + get { return _line_numbers; } + } + + public readonly int LineBase; + public readonly int LineRange; + public readonly byte OpcodeBase; + public readonly int MaxAddressIncrement; + +#region Configurable constants + public const int Default_LineBase = -1; + public const int Default_LineRange = 8; + public const byte Default_OpcodeBase = 9; + + public const bool SuppressDuplicates = true; +#endregion + + public const byte DW_LNS_copy = 1; + public const byte DW_LNS_advance_pc = 2; + public const byte DW_LNS_advance_line = 3; + public const byte DW_LNS_set_file = 4; + public const byte DW_LNS_const_add_pc = 8; + + public const byte DW_LNE_end_sequence = 1; + + // MONO extensions. + public const byte DW_LNE_MONO_negate_is_hidden = 0x40; + + internal const byte DW_LNE_MONO__extensions_start = 0x40; + internal const byte DW_LNE_MONO__extensions_end = 0x7f; + + protected LineNumberTable (MonoSymbolFile file) + { + this.LineBase = file.OffsetTable.LineNumberTable_LineBase; + this.LineRange = file.OffsetTable.LineNumberTable_LineRange; + this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase; + this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange; + } + + internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines) + : this (file) + { + this._line_numbers = lines; + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + int start = (int) bw.BaseStream.Position; + + bool last_is_hidden = false; + int last_line = 1, last_offset = 0, last_file = 1; + for (int i = 0; i < LineNumbers.Length; i++) { + int line_inc = LineNumbers [i].Row - last_line; + int offset_inc = LineNumbers [i].Offset - last_offset; + + if (SuppressDuplicates && (i+1 < LineNumbers.Length)) { + if (LineNumbers [i+1].Equals (LineNumbers [i])) + continue; + } + + if (LineNumbers [i].File != last_file) { + bw.Write (DW_LNS_set_file); + bw.WriteLeb128 (LineNumbers [i].File); + last_file = LineNumbers [i].File; + } + + if (LineNumbers [i].IsHidden != last_is_hidden) { + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_MONO_negate_is_hidden); + last_is_hidden = LineNumbers [i].IsHidden; + } + + if (offset_inc >= MaxAddressIncrement) { + if (offset_inc < 2 * MaxAddressIncrement) { + bw.Write (DW_LNS_const_add_pc); + offset_inc -= MaxAddressIncrement; + } else { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + offset_inc = 0; + } + } + + if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) { + bw.Write (DW_LNS_advance_line); + bw.WriteLeb128 (line_inc); + if (offset_inc != 0) { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + } + bw.Write (DW_LNS_copy); + } else { + byte opcode; + opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) + + OpcodeBase); + bw.Write (opcode); + } + + last_line = LineNumbers [i].Row; + last_offset = LineNumbers [i].Offset; + } + + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_end_sequence); + + file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start; + } + + internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br) + { + LineNumberTable lnt = new LineNumberTable (file); + lnt.DoRead (file, br); + return lnt; + } + + void DoRead (MonoSymbolFile file, MyBinaryReader br) + { + var lines = new List (); + + bool is_hidden = false, modified = false; + int stm_line = 1, stm_offset = 0, stm_file = 1; + while (true) { + byte opcode = br.ReadByte (); + + if (opcode == 0) { + byte size = br.ReadByte (); + long end_pos = br.BaseStream.Position + size; + opcode = br.ReadByte (); + + if (opcode == DW_LNE_end_sequence) { + if (modified) + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + break; + } else if (opcode == DW_LNE_MONO_negate_is_hidden) { + is_hidden = !is_hidden; + modified = true; + } else if ((opcode >= DW_LNE_MONO__extensions_start) && + (opcode <= DW_LNE_MONO__extensions_end)) { + ; // reserved for future extensions + } else { + throw new MonoSymbolFileException ( + "Unknown extended opcode {0:x} in LNT ({1})", + opcode, file.FileName); + } + + br.BaseStream.Position = end_pos; + continue; + } else if (opcode < OpcodeBase) { + switch (opcode) { + case DW_LNS_copy: + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + break; + case DW_LNS_advance_pc: + stm_offset += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_advance_line: + stm_line += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_set_file: + stm_file = br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_const_add_pc: + stm_offset += MaxAddressIncrement; + modified = true; + break; + default: + throw new MonoSymbolFileException ( + "Unknown standard opcode {0:x} in LNT", + opcode); + } + } else { + opcode -= OpcodeBase; + + stm_offset += opcode / LineRange; + stm_line += LineBase + (opcode % LineRange); + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + } + } + + _line_numbers = new LineNumberEntry [lines.Count]; + lines.CopyTo (_line_numbers, 0); + } + + public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end) + { + if (_line_numbers.Length > 1) { + start = _line_numbers [0]; + end = _line_numbers [_line_numbers.Length - 1]; + return true; + } + + start = LineNumberEntry.Null; + end = LineNumberEntry.Null; + return false; + } + } + + public class MethodEntry : IComparable + { + #region This is actually written to the symbol file + public readonly int CompileUnitIndex; + public readonly int Token; + public readonly int NamespaceID; + + int DataOffset; + int LocalVariableTableOffset; + int LineNumberTableOffset; + int CodeBlockTableOffset; + int ScopeVariableTableOffset; + int RealNameOffset; + Flags flags; + #endregion + + int index; + + public Flags MethodFlags { + get { return flags; } + } + + public readonly CompileUnitEntry CompileUnit; + + LocalVariableEntry[] locals; + CodeBlockEntry[] code_blocks; + ScopeVariable[] scope_vars; + LineNumberTable lnt; + string real_name; + + public readonly MonoSymbolFile SymbolFile; + + public int Index { + get { return index; } + set { index = value; } + } + + [Flags] + public enum Flags + { + LocalNamesAmbiguous = 1 + } + + public const int Size = 12; + + internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index) + { + this.SymbolFile = file; + this.index = index; + + Token = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + LineNumberTableOffset = reader.ReadInt32 (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + CompileUnitIndex = reader.ReadLeb128 (); + LocalVariableTableOffset = reader.ReadLeb128 (); + NamespaceID = reader.ReadLeb128 (); + + CodeBlockTableOffset = reader.ReadLeb128 (); + ScopeVariableTableOffset = reader.ReadLeb128 (); + + RealNameOffset = reader.ReadLeb128 (); + + flags = (Flags) reader.ReadLeb128 (); + + reader.BaseStream.Position = old_pos; + + CompileUnit = file.GetCompileUnit (CompileUnitIndex); + } + + internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit, + int token, ScopeVariable[] scope_vars, + LocalVariableEntry[] locals, LineNumberEntry[] lines, + CodeBlockEntry[] code_blocks, string real_name, + Flags flags, int namespace_id) + { + this.SymbolFile = file; + this.real_name = real_name; + this.locals = locals; + this.code_blocks = code_blocks; + this.scope_vars = scope_vars; + this.flags = flags; + + index = -1; + + Token = token; + CompileUnitIndex = comp_unit.Index; + CompileUnit = comp_unit; + NamespaceID = namespace_id; + + CheckLineNumberTable (lines); + lnt = new LineNumberTable (file, lines); + file.NumLineNumbers += lines.Length; + + int num_locals = locals != null ? locals.Length : 0; + + if (num_locals <= 32) { + // Most of the time, the O(n^2) factor is actually + // less than the cost of allocating the hash table, + // 32 is a rough number obtained through some testing. + + for (int i = 0; i < num_locals; i ++) { + string nm = locals [i].Name; + + for (int j = i + 1; j < num_locals; j ++) { + if (locals [j].Name == nm) { + flags |= Flags.LocalNamesAmbiguous; + goto locals_check_done; + } + } + } + locals_check_done : + ; + } else { + var local_names = new Dictionary (); + foreach (LocalVariableEntry local in locals) { + if (local_names.ContainsKey (local.Name)) { + flags |= Flags.LocalNamesAmbiguous; + break; + } + local_names.Add (local.Name, local); + } + } + } + + void CheckLineNumberTable (LineNumberEntry[] line_numbers) + { + int last_offset = -1; + int last_row = -1; + + if (line_numbers == null) + return; + + for (int i = 0; i < line_numbers.Length; i++) { + LineNumberEntry line = line_numbers [i]; + + if (line.Equals (LineNumberEntry.Null)) + throw new MonoSymbolFileException (); + + if (line.Offset < last_offset) + throw new MonoSymbolFileException (); + + if (line.Offset > last_offset) { + last_row = line.Row; + last_offset = line.Offset; + } else if (line.Row > last_row) { + last_row = line.Row; + } + } + } + + internal void Write (MyBinaryWriter bw) + { + if ((index <= 0) || (DataOffset == 0)) + throw new InvalidOperationException (); + + bw.Write (Token); + bw.Write (DataOffset); + bw.Write (LineNumberTableOffset); + } + + internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw) + { + if (index <= 0) + throw new InvalidOperationException (); + + LocalVariableTableOffset = (int) bw.BaseStream.Position; + int num_locals = locals != null ? locals.Length : 0; + bw.WriteLeb128 (num_locals); + for (int i = 0; i < num_locals; i++) + locals [i].Write (file, bw); + file.LocalCount += num_locals; + + CodeBlockTableOffset = (int) bw.BaseStream.Position; + int num_code_blocks = code_blocks != null ? code_blocks.Length : 0; + bw.WriteLeb128 (num_code_blocks); + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i].Write (bw); + + ScopeVariableTableOffset = (int) bw.BaseStream.Position; + int num_scope_vars = scope_vars != null ? scope_vars.Length : 0; + bw.WriteLeb128 (num_scope_vars); + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i].Write (bw); + + if (real_name != null) { + RealNameOffset = (int) bw.BaseStream.Position; + bw.Write (real_name); + } + + LineNumberTableOffset = (int) bw.BaseStream.Position; + lnt.Write (file, bw); + + DataOffset = (int) bw.BaseStream.Position; + + bw.WriteLeb128 (CompileUnitIndex); + bw.WriteLeb128 (LocalVariableTableOffset); + bw.WriteLeb128 (NamespaceID); + + bw.WriteLeb128 (CodeBlockTableOffset); + bw.WriteLeb128 (ScopeVariableTableOffset); + + bw.WriteLeb128 (RealNameOffset); + bw.WriteLeb128 ((int) flags); + } + + public LineNumberTable GetLineNumberTable () + { + lock (SymbolFile) { + if (lnt != null) + return lnt; + + if (LineNumberTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LineNumberTableOffset; + + lnt = LineNumberTable.Read (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return lnt; + } + } + + public LocalVariableEntry[] GetLocals () + { + lock (SymbolFile) { + if (locals != null) + return locals; + + if (LocalVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LocalVariableTableOffset; + + int num_locals = reader.ReadLeb128 (); + locals = new LocalVariableEntry [num_locals]; + + for (int i = 0; i < num_locals; i++) + locals [i] = new LocalVariableEntry (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return locals; + } + } + + public CodeBlockEntry[] GetCodeBlocks () + { + lock (SymbolFile) { + if (code_blocks != null) + return code_blocks; + + if (CodeBlockTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = CodeBlockTableOffset; + + int num_code_blocks = reader.ReadLeb128 (); + code_blocks = new CodeBlockEntry [num_code_blocks]; + + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i] = new CodeBlockEntry (i, reader); + + reader.BaseStream.Position = old_pos; + return code_blocks; + } + } + + public ScopeVariable[] GetScopeVariables () + { + lock (SymbolFile) { + if (scope_vars != null) + return scope_vars; + + if (ScopeVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ScopeVariableTableOffset; + + int num_scope_vars = reader.ReadLeb128 (); + scope_vars = new ScopeVariable [num_scope_vars]; + + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i] = new ScopeVariable (reader); + + reader.BaseStream.Position = old_pos; + return scope_vars; + } + } + + public string GetRealName () + { + lock (SymbolFile) { + if (real_name != null) + return real_name; + + if (RealNameOffset == 0) + return null; + + real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset); + return real_name; + } + } + + public int CompareTo (object obj) + { + MethodEntry method = (MethodEntry) obj; + + if (method.Token < Token) + return 1; + else if (method.Token > Token) + return -1; + else + return 0; + } + + public override string ToString () + { + return String.Format ("[Method {0}:{1:x}:{2}:{3}]", + index, Token, CompileUnitIndex, CompileUnit); + } + } + + public struct NamespaceEntry + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly int Index; + public readonly int Parent; + public readonly string[] UsingClauses; + #endregion + + public NamespaceEntry (string name, int index, string[] using_clauses, int parent) + { + this.Name = name; + this.Index = index; + this.Parent = parent; + this.UsingClauses = using_clauses != null ? using_clauses : new string [0]; + } + + internal NamespaceEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Name = reader.ReadString (); + Index = reader.ReadLeb128 (); + Parent = reader.ReadLeb128 (); + + int count = reader.ReadLeb128 (); + UsingClauses = new string [count]; + for (int i = 0; i < count; i++) + UsingClauses [i] = reader.ReadString (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.Write (Name); + bw.WriteLeb128 (Index); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (UsingClauses.Length); + foreach (string uc in UsingClauses) + bw.Write (uc); + } + + public override string ToString () + { + return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs new file mode 100644 index 0000000000..4d6d1f3d2d --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs @@ -0,0 +1,403 @@ +// +// Mono.CSharp.Debugger/MonoSymbolWriter.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter +// interface. +// +// (C) 2002 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolWriter + { + List methods; + List sources; + List comp_units; + protected readonly MonoSymbolFile file; + string filename; + + private SourceMethodBuilder current_method; +#if NET_2_1 + System.Collections.Stack current_method_stack = new System.Collections.Stack (); +#else + Stack current_method_stack = new Stack (); +#endif + + public MonoSymbolWriter (string filename) + { + this.methods = new List (); + this.sources = new List (); + this.comp_units = new List (); + this.file = new MonoSymbolFile (); + + this.filename = filename + ".mdb"; + } + + public MonoSymbolFile SymbolFile { + get { return file; } + } + + public void CloseNamespace () + { } + + public void DefineLocalVariable (int index, string name) + { + if (current_method == null) + return; + + current_method.AddLocal (index, name); + } + + public void DefineCapturedLocal (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Local); + } + + public void DefineCapturedParameter (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Parameter); + } + + public void DefineCapturedThis (int scope_id, string captured_name) + { + file.DefineCapturedVariable (scope_id, "this", captured_name, + CapturedVariable.CapturedKind.This); + } + + public void DefineCapturedScope (int scope_id, int id, string captured_name) + { + file.DefineCapturedScope (scope_id, id, captured_name); + } + + public void DefineScopeVariable (int scope, int index) + { + if (current_method == null) + return; + + current_method.AddScopeVariable (scope, index); + } + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (current_method == null) + return; + + current_method.MarkSequencePoint (offset, file, line, column, is_hidden); + } + + public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method) + { + SourceMethodBuilder builder = new SourceMethodBuilder (file, ns_id, method); + current_method_stack.Push (current_method); + current_method = builder; + methods.Add (current_method); + return builder; + } + + public void CloseMethod () + { + current_method = (SourceMethodBuilder) current_method_stack.Pop (); + } + + public SourceFileEntry DefineDocument (string url) + { + SourceFileEntry entry = new SourceFileEntry (file, url); + sources.Add (entry); + return entry; + } + + public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum) + { + SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum); + sources.Add (entry); + return entry; + } + + public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source) + { + CompileUnitEntry entry = new CompileUnitEntry (file, source); + comp_units.Add (entry); + return entry; + } + + public int DefineNamespace (string name, CompileUnitEntry unit, + string[] using_clauses, int parent) + { + if ((unit == null) || (using_clauses == null)) + throw new NullReferenceException (); + + return unit.DefineNamespace (name, using_clauses, parent); + } + + public int OpenScope (int start_offset) + { + if (current_method == null) + return 0; + + current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset); + return 0; + } + + public void CloseScope (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void OpenCompilerGeneratedBlock (int start_offset) + { + if (current_method == null) + return; + + current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated, + start_offset); + } + + public void CloseCompilerGeneratedBlock (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void StartIteratorBody (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorBody, + start_offset); + } + + public void EndIteratorBody (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void StartIteratorDispatcher (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher, + start_offset); + } + + public void EndIteratorDispatcher (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void DefineAnonymousScope (int id) + { + file.DefineAnonymousScope (id); + } + + public void WriteSymbolFile (Guid guid) + { + foreach (SourceMethodBuilder method in methods) + method.DefineMethod (file); + + try { + // We mmap the file, so unlink the previous version since it may be in use + File.Delete (filename); + } catch { + // We can safely ignore + } + using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) { + file.CreateSymbolFile (guid, fs); + } + } + } + + public class SourceMethodBuilder + { + List _locals; + List _blocks; + List _scope_vars; +#if NET_2_1 + System.Collections.Stack _block_stack; +#else + Stack _block_stack; +#endif + string _real_name; + IMethodDef _method; + ICompileUnit _comp_unit; +// MethodEntry.Flags _method_flags; + int _ns_id; + + public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method) + { + this._comp_unit = comp_unit; + this._method = method; + this._ns_id = ns_id; + + method_lines = new LineNumberEntry [32]; + } + + private LineNumberEntry [] method_lines; + private int method_lines_pos = 0; + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (method_lines_pos == method_lines.Length) { + LineNumberEntry [] tmp = method_lines; + method_lines = new LineNumberEntry [method_lines.Length * 2]; + Array.Copy (tmp, method_lines, method_lines_pos); + } + + int file_idx = file != null ? file.Index : 0; + method_lines [method_lines_pos++] = new LineNumberEntry ( + file_idx, line, offset, is_hidden); + } + + public void StartBlock (CodeBlockEntry.Type type, int start_offset) + { + if (_block_stack == null) { +#if NET_2_1 + _block_stack = new System.Collections.Stack (); +#else + _block_stack = new Stack (); +#endif + } + + if (_blocks == null) + _blocks = new List (); + + int parent = CurrentBlock != null ? CurrentBlock.Index : -1; + + CodeBlockEntry block = new CodeBlockEntry ( + _blocks.Count + 1, parent, type, start_offset); + + _block_stack.Push (block); + _blocks.Add (block); + } + + public void EndBlock (int end_offset) + { + CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop (); + block.Close (end_offset); + } + + public CodeBlockEntry[] Blocks { + get { + if (_blocks == null) + return new CodeBlockEntry [0]; + + CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count]; + _blocks.CopyTo (retval, 0); + return retval; + } + } + + public CodeBlockEntry CurrentBlock { + get { + if ((_block_stack != null) && (_block_stack.Count > 0)) + return (CodeBlockEntry) _block_stack.Peek (); + else + return null; + } + } + + public LocalVariableEntry[] Locals { + get { + if (_locals == null) + return new LocalVariableEntry [0]; + else { + LocalVariableEntry[] retval = + new LocalVariableEntry [_locals.Count]; + _locals.CopyTo (retval, 0); + return retval; + } + } + } + + public void AddLocal (int index, string name) + { + if (_locals == null) + _locals = new List (); + int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0; + _locals.Add (new LocalVariableEntry (index, name, block_idx)); + } + + public ScopeVariable[] ScopeVariables { + get { + if (_scope_vars == null) + return new ScopeVariable [0]; + + ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count]; + _scope_vars.CopyTo (retval); + return retval; + } + } + + public void AddScopeVariable (int scope, int index) + { + if (_scope_vars == null) + _scope_vars = new List (); + _scope_vars.Add ( + new ScopeVariable (scope, index)); + } + + public string RealMethodName { + get { return _real_name; } + } + + public void SetRealMethodName (string name) + { + _real_name = name; + } + + public ICompileUnit SourceFile { + get { return _comp_unit; } + } + + public IMethodDef Method { + get { return _method; } + } + + public void DefineMethod (MonoSymbolFile file) + { + LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos]; + Array.Copy (method_lines, lines, method_lines_pos); + + MethodEntry entry = new MethodEntry ( + file, _comp_unit.Entry, _method.Token, ScopeVariables, + Locals, lines, Blocks, RealMethodName, 0, //_method_flags, + _ns_id); + + file.AddMethod (entry); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES new file mode 100644 index 0000000000..ccae274939 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES @@ -0,0 +1,38 @@ +* Notes on improving error handling in MCS + (from Axel Schreiner ) + + +I included the 'recover' example with C# as well. Currently the package +is at . I did change some +names and the embedding that the user does somewhat, i.e., it is not +directly compatible with what you did. + +Here is the important part about error recovery. To make the typical +iterations bullet-proof, code them as follows: + +opt : // null + | opt WORD { yyErrorFlag = 0; } + | opt error + +seq : WORD + | seq WORD { yyErrorFlag = 0; } + | error + | seq error + +list : WORD + | list ',' WORD { yyErrorFlag = 0; } + | error + | list error + | list error WORD { yyErrorFlag = 0; } + | list ',' error + +i.e., throw in 'error' wherever a token can be. 'yyErrorFlag' need not +be set to zero, but if it is done this way, second errors are caught +earlier. This may introduce s/r conflicts, but they tend to be harmless. + +In your case -- the comment concerning error recovery at the beginning +of your compiler jay file -- just adding 'error' to the different +global things won't work. Your example will already have started to +advance in one of the rules and 'error' is then not in the lookahead of +wherever the parse then is. You need to put 'error' into the iteration +above those global things. \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE new file mode 100644 index 0000000000..6fa1e31e94 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE @@ -0,0 +1,26 @@ +This document describes all code optimalizations performed by Mono C# compiler +when optimalizations are enabled via /optimize+ option. + +Optimalizations: + +* Instance field initializer to default value +--------------------------------------------- + +Code to optimize: + +class C +{ + enum E + { + Test + } + + int i = 0; // Field will not be redundantly assigned + int i2 = new int (); // This will be also completely optimized out + + E e = E.Test; // Even this will go out. + +} + + + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO new file mode 100644 index 0000000000..ee2cc56f83 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO @@ -0,0 +1,239 @@ +---- This is a list of old tasks, just here for historical value ---- + +Open question: + Create a toplevel block for anonymous methods? + +Anonymous Methods +----------------- + + Plan: + + * Resolve anonymous methods before. + * Each time a Local matches, if the mode is `InAnonymous', flag + the VariableInfo for `proxying'. + * During Resolve track the depth required for local variables. + * Before Emit, create proxy classes with proper depth. + * Emit. + +Notes on memory allocation +-------------------------- + + Outdated: + + A run of the AllocationProfile shows that the compiler allocates roughly + 30 megabytes of strings. From those, 20 megabytes come from + LookupType. + + See the notes on current_container problems below on memory usage. + +LookupTypeReflection: +--------------------- + + With something like `System.Object', LookupTypeReflection will be called + twice: once to find out that `System' is not a type and once + for System.Object. + + This is required because System.Reflection requires that the type/nested types are + not separated by a dot but by a plus sign. + + A nested class would be My+Class (My being the toplevel, Class the nested one). + + It is interesting to look at the most called lookups when bootstrapping MCS: + + 647 LTR: ArrayList + 713 LTR: System.Globalization + 822 LTR: System.Object+Expression + 904 LTR: Mono.CSharp.ArrayList + 976 LTR: System.Runtime.CompilerServices + 999 LTR: Type + 1118 LTR: System.Runtime + 1208 LTR: Mono.CSharp.Type + 1373 LTR: Mono.Languages + 1599 LTR: System.Diagnostics + 2036 LTR: System.Text + 2302 LTR: System.Reflection.Emit + 2515 LTR: System.Collections + 4527 LTR: System.Reflection + 22273 LTR: Mono.CSharp + 24245 LTR: System + 27005 LTR: Mono + + Analysis: + The top 9 lookups are done for things which are not types. + + Mono.CSharp.Type happens to be a common lookup: the class Type + used heavily in the compiler in the default namespace. + + RED FLAG: + + Then `Type' is looked up alone a lot of the time, this happens + in parameter declarations and am not entirely sure that this is + correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName, + which for some reason is null!). This seems to be a problem with a lost + piece of context during FindType. + + System.Object is also used a lot as a toplevel class, and we assume it will + have children, we should just shortcut this. + + A cache: + + Adding a cache and adding a catch for `System.Object' to flag that it wont be the + root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds. + + This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs. Memory consumption + went down from 74 megs to 65 megs with this change. + +Major tasks: +------------ + + Pinned and volatile require type modifiers that can not be encoded + with Reflection.Emit. + +* Revisit + + Primary-expression, as it has now been split into + non-array-creation-expression and array-creation-expression. + +* Emit `pinned' for pinned local variables. + + Both `modreq' and pinned will require special hacks in the compiler. + +* Make sure that we are pinning the right variable + +* local_variable_declaration + + Not sure that this grammar is correct, we might have to + resolve this during semantic analysis. + +* Optimizations + + In Indexers and Properties, probably support an EmitWithDup + That emits the code to call Get and then leaves a this pointer + in the stack, so that later a Store can be emitted using that + this pointer (consider Property++ or Indexer++) + +* Use of local temporary in UnaryMutator + + We should get rid of the Localtemporary there for some cases + + This turns out to be very complex, at least for the post-version, + because this case: + + a = i++ + + To produce optimal code, it is necessary for UnaryMutator to know + that it is being assigned to a variable (the way the stack is laid + out using dup requires the store to happen inside UnaryMutator). + +* Interface indexers + + I have not figured out why the Microsoft version puts an + `instance' attribute, and I am not generating this `instance' attribute. + + Explanation: The reason for the `instance' attribute on + indexers is that indexers only apply to instances + +* Check for Final when overriding, if the parent is Final, then we cant + allow an override. + + Implement base indexer access. + +current_container/current_namespace and the DeclSpace +----------------------------------------------------- + + We are storing fully qualified names in the DeclSpace instead of the node, + this is because `current_namespace' (Namepsace) is not a DeclSpace like + `current_container'. + + The reason for storing the full names today is this: + + namespace X { + class Y { + } + } + + namespace A { + class Y { + } + } + + The problem is that we only use the namespace stack to track the "prefix" + for typecontainers, but they are not typecontainers themselves, so we have + to use fully qualified names, because both A.X and A.Y would be entered + in the toplevel type container. If we use the short names, there would be + a name clash. + + To fix this problem, we have to make namespaces DeclSpaces. + + The full size, contrasted with the size that could be stored is: + corlib: + Size of strings held: 368901 + Size of strings short: 147863 + + System: + Size of strings held: 212677 + Size of strings short: 97521 + + System.XML: + Size of strings held: 128055 + Size of strings short: 35782 + + System.Data: + Size of strings held: 117896 + Size of strings short: 36153 + + System.Web: + Size of strings held: 194527 + Size of strings short: 58064 + + System.Windows.Forms: + Size of strings held: 220495 + Size of strings short: 64923 + + +The use of DottedName +--------------------- + + We could probably use a different system to represent names, like this: + + class Name { + string simplename; + Name parent; + } + + So `System.ComponentModel' becomes: + + x: (System, null) + y: (ComponentModel, x) + + The problem is that we would still need to construct the name to pass to + GetType. + + This has been now implemented, its called "QualifiedIdentifier" + +TODO: + + 1. Create a "partial" emit context for each TypeContainer.. + + 2. EmitContext should be partially constructed. No IL Generator. + + interface_type review. + + parameter_array, line 952: `note: must be a single dimension array type'. Validate this + +Instance idea +------------- + + It would be nice to have things that can be "instances" to have an + EmitInstance method (this would default to nothing). + + The idea is to be able to use efficiently the instance data on stack + manipulations, as opposed to the current scheme, where we basically have + a few special cases. + + * `yield' is no longer a keyword, it only has special + meaning before a return or break keywords. + + * Study side effects with assign + * Study TemporaryStorage/LocalStorage -> Merge/rename + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN new file mode 100644 index 0000000000..dc8324c3d5 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN @@ -0,0 +1,66 @@ +Clean Up +-------- + + Move MapVariable from CodeGen into Block? + +Improve test: + + Necesitamos que a-capture8.cs pruebe si la asignacion funciona o no. + +Audit: + + Al emitir instancias de variables + (EmitCaptureVariableInstance) parece ser que el loop de iteracion: + + while (si.ScopeBlock.ID != li.Block.ID) + + está mas actulizado que el codigo similar para parámetros, es posible + que sea bitrot de parámetros o que en los parámetros usamos otra estrategia + (lo segundo es más razonable). + +Iteradores: + + En algún lugar no pongo el `FieldBuilder' a un valor con los + iteradores, ver expression.cs: 3616, local_info.FieldBuilder es nulo. + +Parameters: + + a-parameter4.cs falla por que no se liga el método anónimo + anidado con el padre. + +Cleanup: + + CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); + if (cc != this){ + cc.EmitParameter (ec, name); + return; + } + + That should be a static method, and call the instance method + in the right CaptureContext, instead of having the CaptureContext + compute that itself. + +MakePinned is gone: + + Need to audit the code now that use DeclareLocal, and that this uses + a differnent code path than the main mcs. + +Need to fix the order in which types are closed: currently we are not +compatible with the MS requirement that the parent has to be created +before the children are. + +Tests and pending features: + + Switch statement is broken (because it uses ILGenerator during + the Resolve phase, which with the `anonymous' branch is no longer + the case: so we have to delay the creation of labels until they + are needed, during the Emit phase). + +Validation: + + For testing, set ec.IG == null during resolve, restore value + for emit. + + Currently it is commented out: there is a bug in the + statement.cs changes (see the old-statement.cs, the compiler + fails during bootstrap) diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README new file mode 100644 index 0000000000..f7023e675c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README @@ -0,0 +1,72 @@ +Completion support +================== + + Supported: + + a. to complete members of type `a' + a for types and namespaces + a.W + a for local variables + + Unsupported: + + delegate { FOO. + using statement autocompletion + +These are the sources to the Mono C# compiler +--------------------------------------------- + + Read the mcs/docs/compiler.txt for an overview of the compiler. + +Testing the Compiler +-------------------- + + You might want to use the `make btest' in this directory to + have the compiler bootstrap itself, this is the basic regression + test. + + Before commiting changes to MCS, make sure that all the tests + in `mcs/tests' pass, and all the tests in 'mcs/errors' have the + expected result, type: + + cd mcs # The top-level 'mcs' directory + make compiler-tests + + If you want to test the installed compiler, you can run: + + cd mcs # The top-level 'mcs' directory + make test-installed-compiler + +Full Bootstrap +============== + + To finally ensure the state of the compiler, it is ideal to do + a full bootstrap, to do this, do: + + cd mcs + make clean; + make + make install + + That installs the compiler and assemblies compiled by the new compiler. + + Then, repeat that step again: + + make clean + make + + If things work, the compiler has not added a new regression + while building the mscorlib and the compiler itself. + +Tests +===== + + When bugs are fixed, new tests must be added to the + `mcs/tests' directory to excercise the problem and to guarantee + that we keep the compiler in a good state. + + When an error is reported, it should be added to mcs/errors. + + We try to make the errors numbers be the same as the ones in + Microsoft C#, if this is not possible, allocate a negative error + number, and list it in mcs/errors/errors.txt diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO new file mode 100644 index 0000000000..1abb0382b7 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO @@ -0,0 +1,223 @@ +=========================================== + +* Value Parameter + + I believe that `Value Parameter' might have been introduced + after C# 1.0, also notice than in the treatment of Value Parameter + the parameters are defined in four categories: + + Section 9.3 in the latest spec. + + +Large project: +-------------- + +New +--- + + It would be nice to optimize the case of: + + Method (new ValueType ()) + + So that no temporary is created, and we only use a newobj call + that remains on the stack, as opposed to ldloca, initobj, ldloc + call. + +NEW NOTES: +---------- + + ImplicitStandardConversionExists and ImplicitStandardConversion + should always be the same, but there are a few diverging lines that + must be studied: + + if (expr_type == target_type && !(expr is NullLiteral)) + return expr; + + vs: + + if (expr_type == target_type) + return true; + +**************************************************************************************** +* +* The information on the rest of this file is mostly outdated, and its kept here for +* historical reasons +* +**************************************************************************************** + +Error Reporting: +---------------- + + * Make yyerror show a nice syntax error, instead of the current mess. + +Optimization ideas +------------------ + + Currently when we build a type cache, it contains private members, + internal members, and internal protected members; We should trim + these out, as it shows up on the profile. + + We create too many Arraylists; When we know the size, we should create + an array; + + During parsing we use arraylists to accumulate data, like this: + + thing: + + thing_list + : thing { $$ =new ArrayList (); $$.Add ($1); } + | thing_list thing { ArrayList a = $1; a.Add ($2); $$ = a; } + + We probably could start using "Pairs" there: + + thing_list + : thing { $$ = new Pair ($1, null); } + | thing_list thing { Pair p = $1; $$ = new Pair ($2, $1); } + + +EmitContext.ResolveTypeTree +--------------------------- + + We should investigate its usage. The problem is that by default + this will be set when calling FindType, that triggers a more expensive + lookup. + + I believe we should pass the current EmitContext (which has this turned off + by default) to ResolveType/REsolveTypeExpr and then have the routines that + need ResolveType to pass null as the emit context. + +DeclareLocal audit +------------------ + + DeclareLocal is used in various statements. The audit should be done + in two steps: + + * Identify all the declare locals. + + * Identify its uses. + + * Find if we can make wrapper functions for all of them. + + Then we can move DeclareLocal into a helper class. + + This is required to fix foreach in iterators. + +Ideas: +------ + + Instead of the hack that *knows* about System.Object not having any children classes, + we should just make it simple for a probe to know that there is no need for it. + +Dead Code Elimination bugs: +--------------------------- + + I should also resolve all the children expressions in Switch, Fixed, Using. + +Major tasks: +------------ + Properties and 17.6.3: Finish it. + +readonly variables and ref/out + +BUGS +---- + +* Break/Continue statements + + A finally block should reset the InLoop/LoopBegin/LoopEnd, as + they are logically outside the scope of the loop. + +* Break/continue part 2. + + They should transfer control to the finally block if inside a try/catch + block. + +* +> // CSC sets beforefieldinit +> class X { +> // .cctor will be generated by compiler +> public static readonly object O = new System.Object (); +> public static void Main () {} +> } +> + +PENDING TASKS +------------- + +* Merge test 89 and test-34 + +* Code cleanup + + The information when registering a method in InternalParameters + is duplicated, you can always get the types from the InternalParameters + +* Emit modreq for volatiles + + Handle modreq from public apis. + +* Merge tree.cs, rootcontext.cs + +OPTIMIZATIONS +------------- + +* User Defined Conversions is doing way too many calls to do union sets that are not needed + +* Add test case for destructors + +* Places that use `Ldelema' are basically places where I will be + initializing a value type. I could apply an optimization to + disable the implicit local temporary from being created (by using + the method in New). + +* Dropping TypeContainer as an argument to EmitContext + + My theory is that I can get rid of the TypeBuilder completely from + the EmitContext, and have typecasts where it is used (from + DeclSpace to where it matters). + + The only pending problem is that the code that implements Aliases + is on TypeContainer, and probably should go in DeclSpace. + +* Tests + + Write tests for the various reference conversions. We have + test for all the numeric conversions. + +* Optimizations: variable allocation. + + When local variables of a type are required, we should request + the variable and later release it when we are done, so that + the same local variable slot can be reused later on. + +* Add a cache for the various GetArrayMethod operations. + +* MakeUnionSet Callers + + If the types are the same, there is no need to compute the unionset, + we can just use the list from one of the types. + +* Factor the lookup code for class declarations an interfaces + (interface.cs:GetInterfaceByName) + +RECOMMENDATIONS +--------------- + +* Use of lexer.Location in the parser + + Currently we do: + + TOKEN nt TERMINAL nt TERMINAL nt3 { + $$ = new Blah ($2, $4, $6, lexer.Location); + } + + This is bad, because the lexer.Location is for the last item in `nt3' + + We need to change that to use this pattern: + + TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 { + $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ()); + } + + Notice how numbering of the arguments changes as the + { oob_stack.Push (lexer.Location) } takes a "slot" in the productions. + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs new file mode 100644 index 0000000000..5576bcc5f6 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs @@ -0,0 +1,2038 @@ +// +// anonymous.cs: Support for anonymous methods and types +// +// Author: +// Miguel de Icaza (miguel@ximain.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + public abstract class CompilerGeneratedClass : Class + { + protected CompilerGeneratedClass (TypeContainer parent, MemberName name, Modifiers mod) + : base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED, null) + { + } + + protected void CheckMembersDefined () + { + if (HasMembersDefined) + throw new InternalErrorException ("Helper class already defined!"); + } + + protected static MemberName MakeMemberName (MemberBase host, string name, int unique_id, TypeParameter[] tparams, Location loc) + { + string host_name = host == null ? null : host.Name; + string tname = MakeName (host_name, "c", name, unique_id); + TypeArguments args = null; + if (tparams != null) { + args = new TypeArguments (); + foreach (TypeParameter tparam in tparams) + args.Add (new TypeParameterName (tparam.Name, null, loc)); + } + + return new MemberName (tname, args, loc); + } + + public static string MakeName (string host, string typePrefix, string name, int id) + { + return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X"); + } + } + + public class HoistedStoreyClass : CompilerGeneratedClass + { + public sealed class HoistedField : Field + { + public HoistedField (HoistedStoreyClass parent, FullNamedExpression type, Modifiers mod, string name, + Attributes attrs, Location loc) + : base (parent, type, mod, new MemberName (name, loc), attrs) + { + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + HoistedStoreyClass parent = ((HoistedStoreyClass) Parent).GetGenericStorey (); + if (parent != null && parent.Mutator != null) + member_type = parent.Mutator.Mutate (MemberType); + + return true; + } + } + + protected TypeParameterMutator mutator; + + public HoistedStoreyClass (TypeContainer parent, MemberName name, TypeParameter[] tparams, Modifiers mod) + : base (parent, name, mod | Modifiers.PRIVATE) + { + if (tparams != null) { + type_params = new TypeParameter[tparams.Length]; + var src = new TypeParameterSpec[tparams.Length]; + var dst = new TypeParameterSpec[tparams.Length]; + + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = tparams[i].CreateHoistedCopy (this, spec); + + src[i] = tparams[i].Type; + dst[i] = type_params[i].Type; + } + + // A copy is not enough, inflate any type parameter constraints + // using a new type parameters + var inflator = new TypeParameterInflator (this, null, src, dst); + for (int i = 0; i < type_params.Length; ++i) { + src[i].InflateConstraints (inflator, dst[i]); + } + + mutator = new TypeParameterMutator (tparams, type_params); + } + } + + #region Properties + + public TypeParameterMutator Mutator { + get { + return mutator; + } + set { + mutator = value; + } + } + + #endregion + + public HoistedStoreyClass GetGenericStorey () + { + DeclSpace storey = this; + while (storey != null && storey.CurrentTypeParameters == null) + storey = storey.Parent; + + return storey as HoistedStoreyClass; + } + } + + + // + // Anonymous method storey is created when an anonymous method uses + // variable or parameter from outer scope. They are then hoisted to + // anonymous method storey (captured) + // + public class AnonymousMethodStorey : HoistedStoreyClass + { + struct StoreyFieldPair + { + public readonly AnonymousMethodStorey Storey; + public readonly Field Field; + + public StoreyFieldPair (AnonymousMethodStorey storey, Field field) + { + this.Storey = storey; + this.Field = field; + } + } + + // + // Needed to delay hoisted _this_ initialization. When an anonymous + // method is used inside ctor and _this_ is hoisted, base ctor has to + // be called first, otherwise _this_ will be initialized with + // uninitialized value. + // + sealed class ThisInitializer : Statement + { + readonly HoistedThis hoisted_this; + + public ThisInitializer (HoistedThis hoisted_this) + { + this.hoisted_this = hoisted_this; + } + + protected override void DoEmit (EmitContext ec) + { + hoisted_this.EmitHoistingAssignment (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing to clone + } + } + + // Unique storey ID + public readonly int ID; + static int unique_id; + + public readonly Block OriginalSourceBlock; + + // A list of StoreyFieldPair with local field keeping parent storey instance + List used_parent_storeys; + List children_references; + + // A list of hoisted parameters + protected List hoisted_params; + protected List hoisted_locals; + + // Hoisted this + protected HoistedThis hoisted_this; + + // Local variable which holds this storey instance + public LocalTemporary Instance; + + public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) + : base (parent, MakeMemberName (host, name, unique_id, tparams, block.StartLocation), + tparams, Modifiers.SEALED) + { + OriginalSourceBlock = block; + ID = unique_id++; + } + + public void AddCapturedThisField (EmitContext ec) + { + TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); + Field f = AddCompilerGeneratedField ("<>f__this", type_expr); + f.Define (); + hoisted_this = new HoistedThis (this, f); + + // Inflated type instance has to be updated manually + if (Instance.Type is InflatedTypeSpec) { + var inflator = new TypeParameterInflator (this, Instance.Type, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + Instance.Type.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + + inflator = new TypeParameterInflator (this, f.Parent.CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + f.Parent.CurrentType.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + } + } + + public Field AddCapturedVariable (string name, TypeSpec type) + { + CheckMembersDefined (); + + FullNamedExpression field_type = new TypeExpression (type, Location); + if (!IsGeneric) + return AddCompilerGeneratedField (name, field_type); + + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + Field f = new HoistedField (this, field_type, mod, name, null, Location); + AddField (f); + return f; + } + + protected Field AddCompilerGeneratedField (string name, FullNamedExpression type) + { + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + Field f = new Field (this, type, mod, new MemberName (name, Location), null); + AddField (f); + return f; + } + + // + // Creates a link between hoisted variable block and the anonymous method storey + // + // An anonymous method can reference variables from any outer block, but they are + // hoisted in their own ExplicitBlock. When more than one block is referenced we + // need to create another link between those variable storeys + // + public void AddReferenceFromChildrenBlock (ExplicitBlock block) + { + if (children_references == null) + children_references = new List (); + + if (!children_references.Contains (block)) + children_references.Add (block); + } + + public void AddParentStoreyReference (EmitContext ec, AnonymousMethodStorey storey) + { + CheckMembersDefined (); + + if (used_parent_storeys == null) + used_parent_storeys = new List (); + else if (used_parent_storeys.Exists (i => i.Storey == storey)) + return; + + TypeExpr type_expr = storey.CreateStoreyTypeExpression (ec); + Field f = AddCompilerGeneratedField ("<>f__ref$" + storey.ID, type_expr); + used_parent_storeys.Add (new StoreyFieldPair (storey, f)); + } + + public void CaptureLocalVariable (ResolveContext ec, LocalVariable local_info) + { + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + if (ec.CurrentBlock.Explicit != local_info.Block.Explicit) + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + + if (local_info.HoistedVariant != null) + return; + + HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info)); + local_info.HoistedVariant = var; + + if (hoisted_locals == null) + hoisted_locals = new List (); + + hoisted_locals.Add (var); + } + + public void CaptureParameter (ResolveContext ec, ParameterReference param_ref) + { + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + + if (param_ref.GetHoistedVariable (ec) != null) + return; + + if (hoisted_params == null) + hoisted_params = new List (2); + + var expr = new HoistedParameter (this, param_ref); + param_ref.Parameter.HoistedVariant = expr; + hoisted_params.Add (expr); + } + + TypeExpr CreateStoreyTypeExpression (EmitContext ec) + { + // + // Create an instance of storey type + // + TypeExpr storey_type_expr; + if (CurrentTypeParameters != null) { + // + // Use current method type parameter (MVAR) for top level storey only. All + // nested storeys use class type parameter (VAR) + // + TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ? + ec.CurrentAnonymousMethod.Storey.TypeParameters : + ec.CurrentTypeParameters; + + TypeArguments targs = new TypeArguments (); + + // + // Use type parameter name instead of resolved type parameter + // specification to resolve to correctly nested type parameters + // + for (int i = 0; i < tparams.Length; ++i) + targs.Add (new SimpleName (tparams [i].Name, Location)); // new TypeParameterExpr (tparams[i], Location)); + + storey_type_expr = new GenericTypeExpr (Definition, targs, Location); + } else { + storey_type_expr = new TypeExpression (CurrentType, Location); + } + + return storey_type_expr; + } + + public void SetNestedStoryParent (AnonymousMethodStorey parentStorey) + { + Parent = parentStorey; + type_params = null; + spec.IsGeneric = false; + spec.DeclaringType = parentStorey.CurrentType; + MemberName.TypeArguments = null; + } + + protected override bool DoResolveTypeParameters () + { + // Although any storey can have type parameters they are all clones of method type + // parameters therefore have to mutate MVAR references in any of cloned constraints + if (type_params != null) { + for (int i = 0; i < type_params.Length; ++i) { + var spec = type_params[i].Type; + spec.BaseType = mutator.Mutate (spec.BaseType); + if (spec.InterfacesDefined != null) { + var mutated = new TypeSpec[spec.InterfacesDefined.Length]; + for (int ii = 0; ii < mutated.Length; ++ii) { + mutated[ii] = mutator.Mutate (spec.InterfacesDefined[ii]); + } + + spec.InterfacesDefined = mutated; + } + + if (spec.TypeArguments != null) { + spec.TypeArguments = mutator.Mutate (spec.TypeArguments); + } + } + } + + // + // Update parent cache as we most likely passed the point + // where the cache was constructed + // + Parent.CurrentType.MemberCache.AddMember (this.spec); + + return true; + } + + // + // Initializes all hoisted variables + // + public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block) + { + // There can be only one instance variable for each storey type + if (Instance != null) + throw new InternalErrorException (); + + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + // + // Create an instance of a storey + // + var storey_type_expr = CreateStoreyTypeExpression (ec); + + ResolveContext rc = new ResolveContext (ec.MemberContext); + rc.CurrentBlock = block; + Expression e = new New (storey_type_expr, null, Location).Resolve (rc); + e.Emit (ec); + + Instance = new LocalTemporary (storey_type_expr.Type); + Instance.Store (ec); + + EmitHoistedFieldsInitialization (rc, ec); + + SymbolWriter.DefineScopeVariable (ID, Instance.Builder); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + void EmitHoistedFieldsInitialization (ResolveContext rc, EmitContext ec) + { + // + // Initialize all storey reference fields by using local or hoisted variables + // + if (used_parent_storeys != null) { + foreach (StoreyFieldPair sf in used_parent_storeys) { + // + // Get instance expression of storey field + // + Expression instace_expr = GetStoreyInstanceExpression (ec); + var fs = sf.Field.Spec; + if (TypeManager.IsGenericType (instace_expr.Type)) + fs = MemberCache.GetMember (instace_expr.Type, fs); + + FieldExpr f_set_expr = new FieldExpr (fs, Location); + f_set_expr.InstanceExpression = instace_expr; + + SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec)); + if (a.Resolve (rc) != null) + a.EmitStatement (ec); + } + } + + // + // Define hoisted `this' in top-level storey only + // + if (OriginalSourceBlock.Explicit.HasCapturedThis && !(Parent is AnonymousMethodStorey)) { + AddCapturedThisField (ec); + rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); + } + + // + // Setting currect anonymous method to null blocks any further variable hoisting + // + AnonymousExpression ae = ec.CurrentAnonymousMethod; + ec.CurrentAnonymousMethod = null; + + if (hoisted_params != null) { + EmitHoistedParameters (ec, hoisted_params); + } + + ec.CurrentAnonymousMethod = ae; + } + + protected virtual void EmitHoistedParameters (EmitContext ec, IList hoisted) + { + foreach (HoistedParameter hp in hoisted) { + hp.EmitHoistingAssignment (ec); + } + } + + public override void EmitType () + { + SymbolWriter.DefineAnonymousScope (ID); + + if (hoisted_this != null) + hoisted_this.EmitSymbolInfo (); + + if (hoisted_locals != null) { + foreach (HoistedVariable local in hoisted_locals) + local.EmitSymbolInfo (); + } + + if (hoisted_params != null) { + foreach (HoistedParameter param in hoisted_params) + param.EmitSymbolInfo (); + } + + if (used_parent_storeys != null) { + foreach (StoreyFieldPair sf in used_parent_storeys) { + SymbolWriter.DefineCapturedScope (ID, sf.Storey.ID, sf.Field.Name); + } + } + + base.EmitType (); + } + + // + // Returns a field which holds referenced storey instance + // + Field GetReferencedStoreyField (AnonymousMethodStorey storey) + { + if (used_parent_storeys == null) + return null; + + foreach (StoreyFieldPair sf in used_parent_storeys) { + if (sf.Storey == storey) + return sf.Field; + } + + return null; + } + + // + // Creates storey instance expression regardless of currect IP + // + public Expression GetStoreyInstanceExpression (EmitContext ec) + { + AnonymousExpression am = ec.CurrentAnonymousMethod; + + // + // Access from original block -> storey + // + if (am == null) + return Instance; + + // + // Access from anonymous method implemented as a static -> storey + // + if (am.Storey == null) + return Instance; + + Field f = am.Storey.GetReferencedStoreyField (this); + if (f == null) { + if (am.Storey == this) { + // + // Access inside of same storey (S -> S) + // + return new CompilerGeneratedThis (CurrentType, Location); + } + // + // External field access + // + return Instance; + } + + // + // Storey was cached to local field + // + FieldExpr f_ind = new FieldExpr (f, Location); + f_ind.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location); + return f_ind; + } + + protected virtual string GetVariableMangledName (LocalVariable local_info) + { + // + // No need to mangle anonymous method hoisted variables cause they + // are hoisted in their own scopes + // + return local_info.Name; + } + + public HoistedThis HoistedThis { + get { return hoisted_this; } + } + + public IList ReferencesFromChildrenBlock { + get { return children_references; } + } + + public static void Reset () + { + unique_id = 0; + } + } + + public abstract class HoistedVariable + { + // + // Hoisted version of variable references used in expression + // tree has to be delayed until we know its location. The variable + // doesn't know its location until all stories are calculated + // + class ExpressionTreeVariableReference : Expression + { + readonly HoistedVariable hv; + + public ExpressionTreeVariableReference (HoistedVariable hv) + { + this.hv = hv; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return hv.CreateExpressionTree (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + type = ec.Module.PredefinedTypes.Expression.Resolve (); + return this; + } + + public override void Emit (EmitContext ec) + { + ResolveContext rc = new ResolveContext (ec.MemberContext); + Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc); + // This should never fail + e = e.Resolve (rc); + if (e != null) + e.Emit (ec); + } + } + + protected readonly AnonymousMethodStorey storey; + protected Field field; + Dictionary cached_inner_access; // TODO: Hashtable is too heavyweight + FieldExpr cached_outer_access; + + protected HoistedVariable (AnonymousMethodStorey storey, string name, TypeSpec type) + : this (storey, storey.AddCapturedVariable (name, type)) + { + } + + protected HoistedVariable (AnonymousMethodStorey storey, Field field) + { + this.storey = storey; + this.field = field; + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + GetFieldExpression (ec).AddressOf (ec, mode); + } + + public Expression CreateExpressionTree () + { + return new ExpressionTreeVariableReference (this); + } + + public void Emit (EmitContext ec) + { + GetFieldExpression (ec).Emit (ec); + } + + // + // Creates field access expression for hoisted variable + // + protected virtual FieldExpr GetFieldExpression (EmitContext ec) + { + if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) { + if (cached_outer_access != null) + return cached_outer_access; + + // + // When setting top-level hoisted variable in generic storey + // change storey generic types to method generic types (VAR -> MVAR) + // + if (storey.Instance.Type.IsGenericOrParentIsGeneric) { + var fs = MemberCache.GetMember (storey.Instance.Type, field.Spec); + cached_outer_access = new FieldExpr (fs, field.Location); + } else { + cached_outer_access = new FieldExpr (field, field.Location); + } + + cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); + return cached_outer_access; + } + + FieldExpr inner_access; + if (cached_inner_access != null) { + if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access)) + inner_access = null; + } else { + inner_access = null; + cached_inner_access = new Dictionary (4); + } + + if (inner_access == null) { + if (field.Parent.IsGeneric) { + var fs = MemberCache.GetMember (field.Parent.CurrentType, field.Spec); + inner_access = new FieldExpr (fs, field.Location); + } else { + inner_access = new FieldExpr (field, field.Location); + } + + inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); + cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access); + } + + return inner_access; + } + + public abstract void EmitSymbolInfo (); + + public void Emit (EmitContext ec, bool leave_copy) + { + GetFieldExpression (ec).Emit (ec, leave_copy); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false); + } + } + + public class HoistedParameter : HoistedVariable + { + sealed class HoistedFieldAssign : Assign + { + public HoistedFieldAssign (Expression target, Expression source) + : base (target, source, source.Location) + { + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + // + // Implicit conversion check fails for hoisted type arguments + // as they are of different types (!!0 x !0) + // + return this; + } + } + + readonly ParameterReference parameter; + + public HoistedParameter (AnonymousMethodStorey scope, ParameterReference par) + : base (scope, par.Name, par.Type) + { + this.parameter = par; + } + + public HoistedParameter (HoistedParameter hp, string name) + : base (hp.storey, name, hp.parameter.Type) + { + this.parameter = hp.parameter; + } + + public void EmitHoistingAssignment (EmitContext ec) + { + // + // Remove hoisted redirection to emit assignment from original parameter + // + HoistedVariable temp = parameter.Parameter.HoistedVariant; + parameter.Parameter.HoistedVariant = null; + + Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter); + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) + a.EmitStatement (ec); + + parameter.Parameter.HoistedVariant = temp; + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedParameter (storey.ID, field.Name, field.Name); + } + + public Field Field { + get { return field; } + } + } + + class HoistedLocalVariable : HoistedVariable + { + readonly string name; + + public HoistedLocalVariable (AnonymousMethodStorey scope, LocalVariable local, string name) + : base (scope, name, local.Type) + { + this.name = local.Name; + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name); + } + } + + public class HoistedThis : HoistedVariable + { + public HoistedThis (AnonymousMethodStorey storey, Field field) + : base (storey, field) + { + } + + public void EmitHoistingAssignment (EmitContext ec) + { + SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location)); + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) + a.EmitStatement (ec); + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedThis (storey.ID, field.Name); + } + + public Field Field { + get { return field; } + } + } + + // + // Anonymous method expression as created by parser + // + public class AnonymousMethodExpression : Expression + { + // + // Special conversion for nested expression tree lambdas + // + class Quote : ShimExpression + { + public Quote (Expression expr) + : base (expr) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + var args = new Arguments (1); + args.Add (new Argument (expr.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "Quote", args); + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr == null) + return null; + + eclass = expr.eclass; + type = expr.Type; + return this; + } + } + + readonly Dictionary compatibles; + readonly bool is_async; + + public ParametersBlock Block; + + public AnonymousMethodExpression (bool isAsync, Location loc) + { + this.is_async = isAsync; + this.loc = loc; + this.compatibles = new Dictionary (); + } + + #region Properties + + public override string ExprClassName { + get { + return "anonymous method"; + } + } + + public virtual bool HasExplicitParameters { + get { + return Parameters != ParametersCompiled.Undefined; + } + } + + public bool IsAsync { + get { + return is_async; + } + } + + public ParametersCompiled Parameters { + get { + return Block.Parameters; + } + } + + #endregion + + // + // Returns true if the body of lambda expression can be implicitly + // converted to the delegate of type `delegate_type' + // + public bool ImplicitStandardConversionExists (ResolveContext ec, TypeSpec delegate_type) + { + using (ec.With (ResolveContext.Options.InferReturnType, false)) { + using (ec.Set (ResolveContext.Options.ProbingMode)) { + return Compatible (ec, delegate_type) != null; + } + } + } + + TypeSpec CompatibleChecks (ResolveContext ec, TypeSpec delegate_type) + { + if (delegate_type.IsDelegate) + return delegate_type; + + if (delegate_type.IsExpressionTreeType) { + delegate_type = delegate_type.TypeArguments [0]; + if (delegate_type.IsDelegate) + return delegate_type; + + ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + return null; + } + + ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + return null; + } + + protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters) + { + if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode)) + return true; + + if (!ec.IsInProbingMode) + ec.Report.Error (1661, loc, + "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + + return false; + } + + protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) + { + if (Parameters.Count != invoke_pd.Count) { + if (ignore_errors) + return false; + + ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ()); + return false; + } + + bool has_implicit_parameters = !HasExplicitParameters; + bool error = false; + + for (int i = 0; i < Parameters.Count; ++i) { + Parameter.Modifier p_mod = invoke_pd.FixedParameters [i].ModFlags; + if (Parameters.FixedParameters [i].ModFlags != p_mod && p_mod != Parameter.Modifier.PARAMS) { + if (ignore_errors) + return false; + + if (p_mod == Parameter.Modifier.NONE) + ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", + (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags)); + else + ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", + (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); + error = true; + } + + if (has_implicit_parameters) + continue; + + TypeSpec type = invoke_pd.Types [i]; + + // We assume that generic parameters are always inflated + if (TypeManager.IsGenericParameter (type)) + continue; + + if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type))) + continue; + + if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) { + if (ignore_errors) + return false; + + ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", + (i+1).ToString (), + TypeManager.CSharpName (Parameters.Types [i]), + TypeManager.CSharpName (invoke_pd.Types [i])); + error = true; + } + } + + return !error; + } + + // + // Infers type arguments based on explicit arguments + // + public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type) + { + if (!HasExplicitParameters) + return false; + + if (!delegate_type.IsDelegate) { + if (!delegate_type.IsExpressionTreeType) + return false; + + delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; + if (!delegate_type.IsDelegate) + return false; + } + + AParametersCollection d_params = Delegate.GetParameters (delegate_type); + if (d_params.Count != Parameters.Count) + return false; + + for (int i = 0; i < Parameters.Count; ++i) { + TypeSpec itype = d_params.Types [i]; + if (!TypeManager.IsGenericParameter (itype)) { + if (!TypeManager.HasElementType (itype)) + continue; + + if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype))) + continue; + } + type_inference.ExactInference (Parameters.Types [i], itype); + } + return true; + } + + public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) + { + Expression expr; + AnonymousExpression am; + + if (compatibles.TryGetValue (delegate_type, out expr)) { + am = expr as AnonymousExpression; + return am == null ? null : am.ReturnType; + } + + using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { + var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); + if (body != null) { + if (is_async) { + AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc); + } + + am = body.Compatible (ec, body, is_async); + } else { + am = null; + } + } + + if (am == null) + return null; + +// compatibles.Add (delegate_type, am); + return am.ReturnType; + } + + // + // Returns AnonymousMethod container if this anonymous method + // expression can be implicitly converted to the delegate type `delegate_type' + // + public Expression Compatible (ResolveContext ec, TypeSpec type) + { + Expression am; + if (compatibles.TryGetValue (type, out am)) + return am; + + TypeSpec delegate_type = CompatibleChecks (ec, type); + if (delegate_type == null) + return null; + + // + // At this point its the first time we know the return type that is + // needed for the anonymous method. We create the method here. + // + + var invoke_mb = Delegate.GetInvokeMethod (delegate_type); + TypeSpec return_type = invoke_mb.ReturnType; + + // + // Second: the return type of the delegate must be compatible with + // the anonymous type. Instead of doing a pass to examine the block + // we satisfy the rule by setting the return type on the EmitContext + // to be the delegate type return type. + // + + var body = CompatibleMethodBody (ec, null, return_type, delegate_type); + if (body == null) + return null; + + bool etree_conversion = delegate_type != type; + + try { + if (etree_conversion) { + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { + // + // Nested expression tree lambda use same scope as parent + // lambda, this also means no variable capturing between this + // and parent scope + // + am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async); + + // + // Quote nested expression tree + // + if (am != null) + am = new Quote (am); + } else { + int errors = ec.Report.Errors; + + using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) { + am = body.Compatible (ec); + } + + // + // Rewrite expressions into expression tree when targeting Expression + // + if (am != null && errors == ec.Report.Errors) + am = CreateExpressionTree (ec, delegate_type); + } + } else { + if (is_async) { + AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc); + } + + am = body.Compatible (ec); + } + } catch (CompletionResult) { + throw; + } catch (Exception e) { + throw new InternalErrorException (e, loc); + } + + if (!ec.IsInProbingMode) { + compatibles.Add (type, am ?? EmptyExpression.Null); + } + + return am; + } + + protected virtual Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) + { + return CreateExpressionTree (ec); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree"); + return null; + } + + protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) + { + var delegate_parameters = Delegate.GetParameters (delegate_type); + + if (Parameters == ParametersCompiled.Undefined) { + // + // We provide a set of inaccessible parameters + // + Parameter[] fixedpars = new Parameter[delegate_parameters.Count]; + + for (int i = 0; i < delegate_parameters.Count; i++) { + Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags; + if (i_mod == Parameter.Modifier.OUT) { + if (!ec.IsInProbingMode) { + ec.Report.Error (1688, loc, + "Cannot convert anonymous method block without a parameter list to delegate type `{0}' because it has one or more `out' parameters", + delegate_type.GetSignatureForError ()); + } + + return null; + } + fixedpars[i] = new Parameter ( + new TypeExpression (delegate_parameters.Types [i], loc), null, + delegate_parameters.FixedParameters [i].ModFlags, null, loc); + } + + return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); + } + + if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { + return null; + } + + return Parameters; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context"); + return null; + } + + // + // Set class type, set type + // + + eclass = ExprClass.Value; + + // + // This hack means `The type is not accessible + // anywhere', we depend on special conversion + // rules. + // + type = InternalType.AnonymousMethod; + + if (!DoResolveParameters (ec)) + return null; + + // FIXME: The emitted code isn't very careful about reachability + // so, ensure we have a 'ret' at the end + BlockContext bc = ec as BlockContext; + if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable) + bc.NeedReturnLabel (); + + return this; + } + + protected virtual bool DoResolveParameters (ResolveContext rc) + { + return Parameters.Resolve (rc); + } + + public override void Emit (EmitContext ec) + { + // nothing, as we only exist to not do anything. + } + + public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc) + { + ec.Report.Error (1686, loc, + "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method, lambda expression or query expression", + var.Name); + } + + public override string GetSignatureForError () + { + return ExprClassName; + } + + AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type) + { + ParametersCompiled p = ResolveParameters (ec, tic, delegate_type); + if (p == null) + return null; + + ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block; + + return CompatibleMethodFactory (return_type, delegate_type, p, b); + } + + protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b) + { + return new AnonymousMethodBody (p, b, return_type, delegate_type, loc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + AnonymousMethodExpression target = (AnonymousMethodExpression) t; + + target.Block = (ParametersBlock) clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Abstract expression for any block which requires variables hoisting + // + public abstract class AnonymousExpression : ExpressionStatement + { + protected class AnonymousMethodMethod : Method + { + public readonly AnonymousExpression AnonymousMethod; + public readonly AnonymousMethodStorey Storey; + readonly string RealName; + + public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey, + GenericMethod generic, TypeExpr return_type, + Modifiers mod, string real_name, MemberName name, + ParametersCompiled parameters) + : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED, + name, parameters, null) + { + this.AnonymousMethod = am; + this.Storey = storey; + this.RealName = real_name; + + Parent.PartialContainer.AddMethod (this); + Block = new ToplevelBlock (am.block, parameters); + } + + public override EmitContext CreateEmitContext (ILGenerator ig) + { + EmitContext ec = new EmitContext (this, ig, ReturnType); + ec.CurrentAnonymousMethod = AnonymousMethod; + if (AnonymousMethod.return_label != null) { + ec.HasReturnLabel = true; + ec.ReturnLabel = (Label) AnonymousMethod.return_label; + } + + return ec; + } + + protected override void DefineTypeParameters () + { + // Type parameters were cloned + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + if (Storey != null && Storey.Mutator != null) { + if (!parameters.IsEmpty) { + var mutated = Storey.Mutator.Mutate (parameters.Types); + if (mutated != parameters.Types) + parameters = ParametersCompiled.CreateFullyResolved ((Parameter[]) parameters.FixedParameters, mutated); + } + + member_type = Storey.Mutator.Mutate (member_type); + } + + return true; + } + + public override void Emit () + { + if (MethodBuilder == null) { + Define (); + } + + base.Emit (); + } + + public override void EmitExtraSymbolInfo (SourceMethod source) + { + source.SetRealMethodName (RealName); + } + } + + protected ParametersBlock block; + + public TypeSpec ReturnType; + + object return_label; + + protected AnonymousExpression (ParametersBlock block, TypeSpec return_type, Location loc) + { + this.ReturnType = return_type; + this.block = block; + this.loc = loc; + } + + public abstract string ContainerType { get; } + public abstract bool IsIterator { get; } + public abstract AnonymousMethodStorey Storey { get; } + + public AnonymousExpression Compatible (ResolveContext ec) + { + return Compatible (ec, this, false); + } + + public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync) + { + if (block.Resolved) + return this; + + // TODO: Implement clone + BlockContext aec = new BlockContext (ec, block, ReturnType); + aec.CurrentAnonymousMethod = ae; + + ResolveContext.Options flags = 0; + + var am = this as AnonymousMethodBody; + + if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { + am.ReturnTypeInference = new TypeInferenceContext (); + } + + if (ec.IsInProbingMode) + flags |= ResolveContext.Options.ProbingMode; + + if (ec.HasSet (ResolveContext.Options.FieldInitializerScope)) + flags |= ResolveContext.Options.FieldInitializerScope; + + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) + flags |= ResolveContext.Options.ExpressionTreeConversion; + + aec.Set (flags); + + var errors = ec.Report.Errors; + + bool res = Block.Resolve (ec.CurrentBranching, aec, null); + + if (aec.HasReturnLabel) + return_label = aec.ReturnLabel; + + if (am != null && am.ReturnTypeInference != null) { + am.ReturnTypeInference.FixAllTypes (ec); + ReturnType = am.ReturnTypeInference.InferredTypeArguments [0]; + am.ReturnTypeInference = null; + + // + // If e is synchronous the inferred return type is T + // If e is asynchronous the inferred return type is Task + // + if (isAsync && ReturnType != null) { + ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); + } + } + + if (res && errors != ec.Report.Errors) + return null; + + return res ? this : null; + } + + public void SetHasThisAccess () + { + ExplicitBlock b = block; + do { + if (b.HasCapturedThis) + return; + + b.HasCapturedThis = true; + b = b.Parent == null ? null : b.Parent.Explicit; + } while (b != null); + } + + // + // The block that makes up the body for the anonymous method + // + public ParametersBlock Block { + get { + return block; + } + } + + } + + public class AnonymousMethodBody : AnonymousExpression + { + protected readonly ParametersCompiled parameters; + AnonymousMethodStorey storey; + + AnonymousMethodMethod method; + Field am_cache; + string block_name; + TypeInferenceContext return_inference; + + static int unique_id; + + public AnonymousMethodBody (ParametersCompiled parameters, + ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, + Location loc) + : base (block, return_type, loc) + { + this.type = delegate_type; + this.parameters = parameters; + } + + #region Properties + + public override string ContainerType { + get { return "anonymous method"; } + } + + public override bool IsIterator { + get { + return false; + } + } + + public ParametersCompiled Parameters { + get { + return parameters; + } + } + + public TypeInferenceContext ReturnTypeInference { + get { + return return_inference; + } + set { + return_inference = value; + } + } + + public override AnonymousMethodStorey Storey { + get { return storey; } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression"); + return null; + } + + bool Define (ResolveContext ec) + { + if (!Block.Resolved && Compatible (ec) == null) + return false; + + if (block_name == null) { + MemberCore mc = (MemberCore) ec.MemberContext; + block_name = mc.MemberName.Basename; + } + + return true; + } + + // + // Creates a host for the anonymous method + // + AnonymousMethodMethod DoCreateMethodHost (EmitContext ec) + { + // + // Anonymous method body can be converted to + // + // 1, an instance method in current scope when only `this' is hoisted + // 2, a static method in current scope when neither `this' nor any variable is hoisted + // 3, an instance method in compiler generated storey when any hoisted variable exists + // + + Modifiers modifiers; + if (Block.HasCapturedVariable || Block.HasCapturedThis) { + storey = FindBestMethodStorey (); + modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + } else { + if (ec.CurrentAnonymousMethod != null) + storey = ec.CurrentAnonymousMethod.Storey; + + modifiers = Modifiers.STATIC | Modifiers.PRIVATE; + } + + TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition.Parent.PartialContainer; + + MemberCore mc = ec.MemberContext as MemberCore; + string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null, + "m", null, unique_id++); + + MemberName member_name; + GenericMethod generic_method; + if (storey == null && mc.MemberName.TypeArguments != null) { + member_name = new MemberName (name, mc.MemberName.TypeArguments.Clone (), Location); + + var hoisted_tparams = ec.CurrentTypeParameters; + var type_params = new TypeParameter[hoisted_tparams.Length]; + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = hoisted_tparams[i].CreateHoistedCopy (parent, null); + } + + generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name, type_params, + new TypeExpression (ReturnType, Location), parameters); + } else { + member_name = new MemberName (name, Location); + generic_method = null; + } + + string real_name = String.Format ( + "{0}~{1}{2}", mc.GetSignatureForError (), GetSignatureForError (), + parameters.GetSignatureForError ()); + + return new AnonymousMethodMethod (parent, + this, storey, generic_method, new TypeExpression (ReturnType, Location), modifiers, + real_name, member_name, parameters); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (!Define (ec)) + return null; + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + // + // Use same anonymous method implementation for scenarios where same + // code is used from multiple blocks, e.g. field initializers + // + if (method == null) { + // + // Delay an anonymous method definition to avoid emitting unused code + // for unreachable blocks or expression trees + // + method = DoCreateMethodHost (ec); + method.Define (); + } + + bool is_static = (method.ModFlags & Modifiers.STATIC) != 0; + if (is_static && am_cache == null) { + // + // Creates a field cache to store delegate instance if it's not generic + // + if (!method.MemberName.IsGeneric) { + TypeContainer parent = method.Parent.PartialContainer; + int id = parent.Fields == null ? 0 : parent.Fields.Count; + var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type; + + am_cache = new Field (parent, new TypeExpression (cache_type, loc), + Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, + new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null); + am_cache.Define (); + parent.AddField (am_cache); + } else { + // TODO: Implement caching of generated generic static methods + // + // Idea: + // + // Some extra class is needed to capture variable generic type + // arguments. Maybe we could re-use anonymous types, with a unique + // anonymous method id, but they are quite heavy. + // + // Consider : "() => typeof(T);" + // + // We need something like + // static class Wrap { + // public static DelegateType cache; + // } + // + // We then specialize local variable to capture all generic parameters + // and delegate type, e.g. "Wrap cache;" + // + } + } + + Label l_initialized = ec.DefineLabel (); + + if (am_cache != null) { + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); + ec.Emit (OpCodes.Brtrue_S, l_initialized); + } + + // + // Load method delegate implementation + // + + if (is_static) { + ec.Emit (OpCodes.Ldnull); + } else if (storey != null) { + Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); + if (e != null) + e.Emit (ec); + } else { + ec.Emit (OpCodes.Ldarg_0); + } + + var delegate_method = method.Spec; + if (storey != null && storey.MemberName.IsGeneric) { + TypeSpec t = storey.Instance.Type; + + // + // Mutate anonymous method instance type if we are in nested + // hoisted generic anonymous method storey + // + if (ec.CurrentAnonymousMethod != null && + ec.CurrentAnonymousMethod.Storey != null && + ec.CurrentAnonymousMethod.Storey.Mutator != null) { + t = storey.Mutator.Mutate (t); + } + + ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ())); + } else { + if (delegate_method.IsGeneric) + delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters); + + ec.Emit (OpCodes.Ldftn, delegate_method); + } + + var constructor_method = Delegate.GetConstructor (type); + ec.Emit (OpCodes.Newobj, constructor_method); + + if (am_cache != null) { + ec.Emit (OpCodes.Stsfld, am_cache.Spec); + ec.MarkLabel (l_initialized); + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); + } + } + + public override void EmitStatement (EmitContext ec) + { + throw new NotImplementedException (); + } + + // + // Look for the best storey for this anonymous method + // + AnonymousMethodStorey FindBestMethodStorey () + { + // + // Use the nearest parent block which has a storey + // + for (Block b = Block.Parent; b != null; b = b.Parent) { + AnonymousMethodStorey s = b.Explicit.AnonymousMethodStorey; + if (s != null) + return s; + } + + return null; + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpName (type); + } + + public static void Reset () + { + unique_id = 0; + } + } + + // + // Anonymous type container + // + public class AnonymousTypeClass : CompilerGeneratedClass + { + static int types_counter; + public const string ClassNamePrefix = "<>__AnonType"; + public const string SignatureForError = "anonymous type"; + + readonly IList parameters; + + private AnonymousTypeClass (TypeContainer parent, MemberName name, IList parameters, Location loc) + : base (parent, name, (parent.Module.Evaluator != null ? Modifiers.PUBLIC : 0) | Modifiers.SEALED) + { + this.parameters = parameters; + } + + public static AnonymousTypeClass Create (TypeContainer parent, IList parameters, Location loc) + { + string name = ClassNamePrefix + types_counter++; + + ParametersCompiled all_parameters; + TypeParameterName[] t_params; + SimpleName[] t_args; + + if (parameters.Count == 0) { + all_parameters = ParametersCompiled.EmptyReadOnlyParameters; + t_params = new TypeParameterName[0]; + t_args = null; + } else { + t_args = new SimpleName[parameters.Count]; + t_params = new TypeParameterName[parameters.Count]; + Parameter[] ctor_params = new Parameter[parameters.Count]; + for (int i = 0; i < parameters.Count; ++i) { + AnonymousTypeParameter p = parameters[i]; + for (int ii = 0; ii < i; ++ii) { + if (parameters[ii].Name == p.Name) { + parent.Compiler.Report.Error (833, parameters[ii].Location, + "`{0}': An anonymous type cannot have multiple properties with the same name", + p.Name); + + p = new AnonymousTypeParameter (null, "$" + i.ToString (), p.Location); + parameters[i] = p; + break; + } + } + + t_args[i] = new SimpleName ("<" + p.Name + ">__T", p.Location); + t_params[i] = new TypeParameterName (t_args[i].Name, null, p.Location); + ctor_params[i] = new Parameter (t_args[i], p.Name, Parameter.Modifier.NONE, null, p.Location); + } + + all_parameters = new ParametersCompiled (ctor_params); + } + + // + // Create generic anonymous type host with generic arguments + // named upon properties names + // + AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace, + new MemberName (name, new TypeArguments (t_params), loc), parameters, loc); + + if (parameters.Count > 0) + a_type.SetParameterInfo (null); + + Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + null, all_parameters, null, loc); + c.Block = new ToplevelBlock (parent.Module.Compiler, c.ParameterInfo, loc); + + // + // Create fields and contructor body with field initialization + // + bool error = false; + for (int i = 0; i < parameters.Count; ++i) { + AnonymousTypeParameter p = parameters [i]; + + Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY, + new MemberName ("<" + p.Name + ">", p.Location), null); + + if (!a_type.AddField (f)) { + error = true; + continue; + } + + c.Block.AddStatement (new StatementExpression ( + new SimpleAssign (new MemberAccess (new This (p.Location), f.Name), + c.Block.GetParameterReference (i, p.Location)))); + + ToplevelBlock get_block = new ToplevelBlock (parent.Module.Compiler, p.Location); + get_block.AddStatement (new Return ( + new MemberAccess (new This (p.Location), f.Name), p.Location)); + + Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC, + new MemberName (p.Name, p.Location), null); + prop.Get = new Property.GetMethod (prop, 0, null, p.Location); + prop.Get.Block = get_block; + a_type.AddProperty (prop); + } + + if (error) + return null; + + a_type.AddConstructor (c); + return a_type; + } + + public static void Reset () + { + types_counter = 0; + } + + protected override bool AddToContainer (MemberCore symbol, string name) + { + MemberCore mc = GetDefinition (name); + + if (mc == null) { + defined_names.Add (name, symbol); + return true; + } + + // A conflict between anonymous type members will be reported + if (symbol is TypeParameter) { + Report.SymbolRelatedToPreviousError (symbol); + return false; + } + + // Ignore other conflicts + return true; + } + + protected override bool DoDefineMembers () + { + if (!base.DoDefineMembers ()) + return false; + + Location loc = Location; + + var equals_parameters = ParametersCompiled.CreateFullyResolved ( + new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object); + + Method equals = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), + equals_parameters, null); + + equals_parameters[0].Resolve (equals, 0); + + Method tostring = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.String, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + + ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); + + TypeExpr current_type; + if (type_params != null) { + var targs = new TypeArguments (); + foreach (var type_param in type_params) + targs.Add (new TypeParameterExpr (type_param, type_param.Location)); + + current_type = new GenericTypeExpr (Definition, targs, loc); + } else { + current_type = new TypeExpression (Definition, loc); + } + + var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc); + equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other)); + var other_variable = new LocalVariableReference (li_other, loc); + + MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); + + Expression rs_equals = null; + Expression string_concat = new StringConstant (Compiler.BuiltinTypes, "{", loc); + Expression rs_hashcode = new IntConstant (Compiler.BuiltinTypes, -2128831035, loc); + for (int i = 0; i < parameters.Count; ++i) { + var p = parameters [i]; + var f = Fields [i]; + + MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( + system_collections_generic, "EqualityComparer", + new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc), + "Default", loc); + + Arguments arguments_equal = new Arguments (2); + arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); + arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); + + Expression field_equal = new Invocation (new MemberAccess (equality_comparer, + "Equals", loc), arguments_equal); + + Arguments arguments_hashcode = new Arguments (1); + arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); + Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, + "GetHashCode", loc), arguments_hashcode); + + IntConstant FNV_prime = new IntConstant (Compiler.BuiltinTypes, 16777619, loc); + rs_hashcode = new Binary (Binary.Operator.Multiply, + new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode, loc), + FNV_prime, loc); + + Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality, + new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc), loc)), + new Invocation (new MemberAccess ( + new MemberAccess (new This (f.Location), f.Name), "ToString"), null), + new StringConstant (Compiler.BuiltinTypes, string.Empty, loc), loc); + + if (rs_equals == null) { + rs_equals = field_equal; + string_concat = new Binary (Binary.Operator.Addition, + string_concat, + new Binary (Binary.Operator.Addition, + new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc), + field_to_string, + loc), + loc); + continue; + } + + // + // Implementation of ToString () body using string concatenation + // + string_concat = new Binary (Binary.Operator.Addition, + new Binary (Binary.Operator.Addition, + string_concat, + new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc), + loc), + field_to_string, + loc); + + rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal, loc); + } + + string_concat = new Binary (Binary.Operator.Addition, + string_concat, + new StringConstant (Compiler.BuiltinTypes, " }", loc), + loc); + + // + // Equals (object obj) override + // + var other_variable_assign = new TemporaryVariableReference (li_other, loc); + equals_block.AddStatement (new StatementExpression ( + new SimpleAssign (other_variable_assign, + new As (equals_block.GetParameterReference (0, loc), + current_type, loc), loc))); + + Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc), loc); + if (rs_equals != null) + equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals, loc); + equals_block.AddStatement (new Return (equals_test, loc)); + + equals.Block = equals_block; + equals.Define (); + AddMethod (equals); + + // + // GetHashCode () override + // + Method hashcode = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.Int, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("GetHashCode", loc), + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + + // + // Modified FNV with good avalanche behavior and uniform + // distribution with larger hash sizes. + // + // const int FNV_prime = 16777619; + // int hash = (int) 2166136261; + // foreach (int d in data) + // hash = (hash ^ d) * FNV_prime; + // hash += hash << 13; + // hash ^= hash >> 7; + // hash += hash << 3; + // hash ^= hash >> 17; + // hash += hash << 5; + + ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc); + Block hashcode_block = new Block (hashcode_top, loc, loc); + hashcode_top.AddStatement (new Unchecked (hashcode_block, loc)); + + var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc); + hashcode_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_hash.Type, loc), li_hash)); + LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc); + hashcode_block.AddStatement (new StatementExpression ( + new SimpleAssign (hash_variable_assign, rs_hashcode))); + + var hash_variable = new LocalVariableReference (li_hash, loc); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc), loc), loc))); + + hashcode_block.AddStatement (new Return (hash_variable, loc)); + hashcode.Block = hashcode_top; + hashcode.Define (); + AddMethod (hashcode); + + // + // ToString () override + // + + ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); + tostring_block.AddStatement (new Return (string_concat, loc)); + tostring.Block = tostring_block; + tostring.Define (); + AddMethod (tostring); + + return true; + } + + public override string GetSignatureForError () + { + return SignatureForError; + } + + public IList Parameters { + get { + return parameters; + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs new file mode 100644 index 0000000000..a246066896 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs @@ -0,0 +1,551 @@ +// +// argument.cs: Argument expressions +// +// Author: +// Miguel de Icaza (miguel@ximain.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // Argument expression used for invocation + // + public class Argument + { + public enum AType : byte + { + None = 0, + Ref = 1, // ref modifier used + Out = 2, // out modifier used + Default = 3, // argument created from default parameter value + DynamicTypeName = 4, // System.Type argument for dynamic binding + ExtensionType = 5, // Instance expression inserted as the first argument + } + + public readonly AType ArgType; + public Expression Expr; + + public Argument (Expression expr, AType type) + { + this.Expr = expr; + this.ArgType = type; + } + + public Argument (Expression expr) + { + if (expr == null) + throw new ArgumentNullException (); + + this.Expr = expr; + } + + #region Properties + + public bool IsByRef { + get { return ArgType == AType.Ref || ArgType == AType.Out; } + } + + public bool IsDefaultArgument { + get { return ArgType == AType.Default; } + } + + public Parameter.Modifier Modifier { + get { + switch (ArgType) { + case AType.Out: + return Parameter.Modifier.OUT; + + case AType.Ref: + return Parameter.Modifier.REF; + + default: + return Parameter.Modifier.NONE; + } + } + } + + public TypeSpec Type { + get { return Expr.Type; } + } + + #endregion + + public Argument Clone (Expression expr) + { + Argument a = (Argument) MemberwiseClone (); + a.Expr = expr; + return a; + } + + public Argument Clone (CloneContext clonectx) + { + return Clone (Expr.Clone (clonectx)); + } + + public virtual Expression CreateExpressionTree (ResolveContext ec) + { + if (ArgType == AType.Default) + ec.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter"); + + return Expr.CreateExpressionTree (ec); + } + + public string GetSignatureForError () + { + if (Expr.eclass == ExprClass.MethodGroup) + return Expr.ExprClassName; + + return TypeManager.CSharpName (Expr.Type); + } + + public bool ResolveMethodGroup (ResolveContext ec) + { + SimpleName sn = Expr as SimpleName; + if (sn != null) + Expr = sn.GetMethodGroup (); + + // FIXME: csc doesn't report any error if you try to use `ref' or + // `out' in a delegate creation expression. + Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + if (Expr == null) + return false; + + return true; + } + + public void Resolve (ResolveContext ec) + { +// using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) { + // Verify that the argument is readable + if (ArgType != AType.Out) + Expr = Expr.Resolve (ec); + + // Verify that the argument is writeable + if (Expr != null && IsByRef) + Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess); + + if (Expr == null) + Expr = ErrorExpression.Instance; +// } + } + + public virtual void Emit (EmitContext ec) + { + if (!IsByRef) { + Expr.Emit (ec); + return; + } + + AddressOp mode = AddressOp.Store; + if (ArgType == AType.Ref) + mode |= AddressOp.Load; + + IMemoryLocation ml = (IMemoryLocation) Expr; + ml.AddressOf (ec, mode); + } + } + + public class MovableArgument : Argument + { + LocalTemporary variable; + + public MovableArgument (Argument arg) + : this (arg.Expr, arg.ArgType) + { + } + + protected MovableArgument (Expression expr, AType modifier) + : base (expr, modifier) + { + } + + public override void Emit (EmitContext ec) + { + // TODO: Should guard against multiple emits + base.Emit (ec); + + // Release temporary variable when used + if (variable != null) + variable.Release (ec); + } + + public void EmitAssign (EmitContext ec) + { + var type = Expr.Type; + if (IsByRef) { + var ml = (IMemoryLocation) Expr; + ml.AddressOf (ec, AddressOp.Load); + type = ReferenceContainer.MakeType (ec.Module, type); + } else { + Expr.Emit (ec); + } + + variable = new LocalTemporary (type); + variable.Store (ec); + + Expr = variable; + } + } + + public class NamedArgument : MovableArgument + { + public readonly string Name; + readonly Location loc; + + public NamedArgument (string name, Location loc, Expression expr) + : this (name, loc, expr, AType.None) + { + } + + public NamedArgument (string name, Location loc, Expression expr, AType modifier) + : base (expr, modifier) + { + this.Name = name; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (853, loc, "An expression tree cannot contain named argument"); + return base.CreateExpressionTree (ec); + } + + public Location Location { + get { return loc; } + } + } + + public class Arguments + { + sealed class ArgumentsOrdered : Arguments + { + readonly List ordered; + + public ArgumentsOrdered (Arguments args) + : base (args.Count) + { + AddRange (args); + ordered = new List (); + } + + public void AddOrdered (MovableArgument arg) + { + ordered.Add (arg); + } + + public override Expression[] Emit (EmitContext ec, bool dup_args) + { + foreach (var a in ordered) { + a.EmitAssign (ec); + } + + return base.Emit (ec, dup_args); + } + } + + // Try not to add any more instances to this class, it's allocated a lot + List args; + + public Arguments (int capacity) + { + args = new List (capacity); + } + + public void Add (Argument arg) + { + args.Add (arg); + } + + public void AddRange (Arguments args) + { + this.args.AddRange (args.args); + } + + public ArrayInitializer CreateDynamicBinderArguments (ResolveContext rc) + { + Location loc = Location.Null; + var all = new ArrayInitializer (args.Count, loc); + + MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc); + + foreach (Argument a in args) { + Arguments dargs = new Arguments (2); + + // CSharpArgumentInfoFlags.None = 0 + const string info_flags_enum = "CSharpArgumentInfoFlags"; + Expression info_flags = new IntLiteral (rc.BuiltinTypes, 0, loc); + + if (a.Expr is Constant) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "Constant", loc), loc); + } else if (a.ArgType == Argument.AType.Ref) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsRef", loc), loc); + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } else if (a.ArgType == Argument.AType.Out) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsOut", loc), loc); + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } else if (a.ArgType == Argument.AType.DynamicTypeName) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsStaticType", loc), loc); + } + + var arg_type = a.Expr.Type; + + if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { + MethodGroupExpr mg = a.Expr as MethodGroupExpr; + if (mg != null) { + rc.Report.Error (1976, a.Expr.Location, + "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", + mg.Name); + } else if (arg_type == InternalType.AnonymousMethod) { + rc.Report.Error (1977, a.Expr.Location, + "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); + } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { + rc.Report.Error (1978, a.Expr.Location, + "An expression of type `{0}' cannot be used as an argument of dynamic operation", + TypeManager.CSharpName (arg_type)); + } + + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } + + string named_value; + NamedArgument na = a as NamedArgument; + if (na != null) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "NamedArgument", loc), loc); + + named_value = na.Name; + } else { + named_value = null; + } + + dargs.Add (new Argument (info_flags)); + dargs.Add (new Argument (new StringLiteral (rc.BuiltinTypes, named_value, loc))); + all.Add (new Invocation (new MemberAccess (new MemberAccess (binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); + } + + return all; + } + + public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e) + { + Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length); + for (int i = 0; i < e.Length; ++i) { + if (e [i] != null) + all.Add (new Argument (e[i])); + } + + if (args != null) { + foreach (Argument a in args.args) { + Expression tree_arg = a.CreateExpressionTree (ec); + if (tree_arg != null) + all.Add (new Argument (tree_arg)); + } + } + + return all; + } + + public void CheckArrayAsAttribute (CompilerContext ctx) + { + foreach (Argument arg in args) { + // Type is undefined (was error 246) + if (arg.Type == null) + continue; + + if (arg.Type.IsArray) + ctx.Report.Warning (3016, 1, arg.Expr.Location, "Arrays as attribute arguments are not CLS-compliant"); + } + } + + public Arguments Clone (CloneContext ctx) + { + Arguments cloned = new Arguments (args.Count); + foreach (Argument a in args) + cloned.Add (a.Clone (ctx)); + + return cloned; + } + + public int Count { + get { return args.Count; } + } + + // + // Emits a list of resolved Arguments + // + public void Emit (EmitContext ec) + { + Emit (ec, false); + } + + // + // if `dup_args' is true, a copy of the arguments will be left + // on the stack and return value will contain an array of access + // expressions + // NOTE: It's caller responsibility is to release temporary variables + // + public virtual Expression[] Emit (EmitContext ec, bool dup_args) + { + Expression[] temps; + + if (dup_args && Count != 0) + temps = new Expression [Count]; + else + temps = null; + + int i = 0; + LocalTemporary lt; + foreach (Argument a in args) { + a.Emit (ec); + if (!dup_args) + continue; + + if (a.Expr is Constant || a.Expr is This) { + // + // No need to create a temporary variable for constants + // + temps[i] = a.Expr; + } else { + ec.Emit (OpCodes.Dup); + temps[i] = lt = new LocalTemporary (a.Type); + lt.Store (ec); + } + + ++i; + } + + return temps; + } + + public List.Enumerator GetEnumerator () + { + return args.GetEnumerator (); + } + + // + // At least one argument is of dynamic type + // + public bool HasDynamic { + get { + foreach (Argument a in args) { + if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) + return true; + } + + return false; + } + } + + // + // At least one argument is named argument + // + public bool HasNamed { + get { + foreach (Argument a in args) { + if (a is NamedArgument) + return true; + } + + return false; + } + } + + + public void Insert (int index, Argument arg) + { + args.Insert (index, arg); + } + + public static System.Linq.Expressions.Expression[] MakeExpression (Arguments args, BuilderContext ctx) + { + if (args == null || args.Count == 0) + return null; + + var exprs = new System.Linq.Expressions.Expression [args.Count]; + for (int i = 0; i < exprs.Length; ++i) { + Argument a = args.args [i]; + exprs[i] = a.Expr.MakeExpression (ctx); + } + + return exprs; + } + + // + // For named arguments when the order of execution is different + // to order of invocation + // + public Arguments MarkOrderedArgument (NamedArgument a) + { + // + // Constant expression have no effect on left-to-right execution + // + if (a.Expr is Constant) + return this; + + ArgumentsOrdered ra = this as ArgumentsOrdered; + if (ra == null) { + ra = new ArgumentsOrdered (this); + + for (int i = 0; i < args.Count; ++i) { + var la = args [i]; + if (la == a) + break; + + var ma = la as MovableArgument; + if (ma == null) { + ma = new MovableArgument (la); + ra.args[i] = ma; + } + + ra.AddOrdered (ma); + } + } + + ra.AddOrdered (a); + return ra; + } + + // + // Returns dynamic when at least one argument is of dynamic type + // + public void Resolve (ResolveContext ec, out bool dynamic) + { + dynamic = false; + foreach (Argument a in args) { + a.Resolve (ec); + if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) + dynamic = true; + } + } + + public void RemoveAt (int index) + { + args.RemoveAt (index); + } + + public Argument this [int index] { + get { return args [index]; } + set { args [index] = value; } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs new file mode 100644 index 0000000000..afae0c57af --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs @@ -0,0 +1,1183 @@ +// +// assembly.cs: Assembly declaration and specifications +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004 Novell, Inc. +// + + +using System; +using System.IO; +using System.Collections.Generic; +using System.Globalization; +using System.Security; +using System.Security.Cryptography; +using System.Security.Permissions; +using Mono.Security.Cryptography; +using Mono.CompilerServices.SymbolWriter; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using SecurityType = System.Collections.Generic.List; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public interface IAssemblyDefinition + { + string FullName { get; } + bool HasExtensionMethod { get; } + bool IsCLSCompliant { get; } + bool IsMissing { get; } + string Name { get; } + + byte[] GetPublicKeyToken (); + bool IsFriendAssemblyTo (IAssemblyDefinition assembly); + } + + public abstract class AssemblyDefinition : IAssemblyDefinition + { + // TODO: make it private and move all builder based methods here + public AssemblyBuilder Builder; + protected AssemblyBuilderExtension builder_extra; + MonoSymbolWriter symbol_writer; + + bool is_cls_compliant; + bool wrap_non_exception_throws; + bool wrap_non_exception_throws_custom; + + protected ModuleContainer module; + readonly string name; + protected readonly string file_name; + + byte[] public_key, public_key_token; + bool delay_sign; + + // Holds private/public key pair when private key + // was available + StrongNameKeyPair private_key; + + Attribute cls_attribute; + Method entry_point; + + protected List added_modules; + SecurityType declarative_security; + Dictionary emitted_forwarders; + AssemblyAttributesPlaceholder module_target_attrs; + + protected AssemblyDefinition (ModuleContainer module, string name) + { + this.module = module; + this.name = Path.GetFileNameWithoutExtension (name); + + wrap_non_exception_throws = true; + + delay_sign = Compiler.Settings.StrongNameDelaySign; + + // + // Load strong name key early enough for assembly importer to be able to + // use the keys for InternalsVisibleTo + // This should go somewhere close to ReferencesLoading but don't have the place yet + // + if (Compiler.Settings.HasKeyFileOrContainer) { + LoadPublicKey (Compiler.Settings.StrongNameKeyFile, Compiler.Settings.StrongNameKeyContainer); + } + } + + protected AssemblyDefinition (ModuleContainer module, string name, string fileName) + : this (module, name) + { + this.file_name = fileName; + } + + #region Properties + + public Attribute CLSCompliantAttribute { + get { + return cls_attribute; + } + } + + public CompilerContext Compiler { + get { + return module.Compiler; + } + } + + // + // Assembly entry point, aka Main method + // + public Method EntryPoint { + get { + return entry_point; + } + set { + entry_point = value; + } + } + + public string FullName { + get { + return Builder.FullName; + } + } + + public bool HasExtensionMethod { + get { + return module.HasExtensionMethod; + } + } + + public bool HasCLSCompliantAttribute { + get { + return cls_attribute != null; + } + } + + // TODO: This should not exist here but will require more changes + public MetadataImporter Importer { + get; set; + } + + public bool IsCLSCompliant { + get { + return is_cls_compliant; + } + } + + bool IAssemblyDefinition.IsMissing { + get { + return false; + } + } + + public string Name { + get { + return name; + } + } + + public bool WrapNonExceptionThrows { + get { + return wrap_non_exception_throws; + } + } + + protected Report Report { + get { + return Compiler.Report; + } + } + + #endregion + + public void AddModule (ImportedModuleDefinition module) + { + if (added_modules == null) { + added_modules = new List (); + added_modules.Add (module); + } + } + + public void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.AssemblyCulture) { + string value = a.GetString (); + if (value == null || value.Length == 0) + return; + + if (Compiler.Settings.Target == Target.Exe) { + a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty"); + return; + } + + if (value == "neutral") + value = ""; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetCulture (value, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyVersion) { + string value = a.GetString (); + if (value == null || value.Length == 0) + return; + + var vinfo = IsValidAssemblyVersion (value, true); + if (vinfo == null) { + a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value)); + return; + } + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetVersion (vinfo, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyAlgorithmId) { + const int pos = 2; // skip CA header + uint alg = (uint) cdata [pos]; + alg |= ((uint) cdata [pos + 1]) << 8; + alg |= ((uint) cdata [pos + 2]) << 16; + alg |= ((uint) cdata [pos + 3]) << 24; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetAlgorithmId (alg, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyFlags) { + const int pos = 2; // skip CA header + uint flags = (uint) cdata[pos]; + flags |= ((uint) cdata [pos + 1]) << 8; + flags |= ((uint) cdata [pos + 2]) << 16; + flags |= ((uint) cdata [pos + 3]) << 24; + + // Ignore set PublicKey flag if assembly is not strongnamed + if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && public_key == null) + flags &= ~(uint) AssemblyNameFlags.PublicKey; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetFlags (flags, a.Location); + } + + return; + } + + if (a.Type == pa.TypeForwarder) { + TypeSpec t = a.GetArgumentType (); + if (t == null || TypeManager.HasElementType (t)) { + Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute"); + return; + } + + if (emitted_forwarders == null) { + emitted_forwarders = new Dictionary (); + } else if (emitted_forwarders.ContainsKey (t.MemberDefinition)) { + Report.SymbolRelatedToPreviousError (emitted_forwarders[t.MemberDefinition].Location, null); + Report.Error (739, a.Location, "A duplicate type forward of type `{0}'", + TypeManager.CSharpName (t)); + return; + } + + emitted_forwarders.Add (t.MemberDefinition, a); + + if (t.MemberDefinition.DeclaringAssembly == this) { + Report.SymbolRelatedToPreviousError (t); + Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly", + TypeManager.CSharpName (t)); + return; + } + + if (t.IsNested) { + Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type", + TypeManager.CSharpName (t)); + return; + } + + builder_extra.AddTypeForwarder (t.GetDefinition (), a.Location); + return; + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + if (a.Type == pa.InternalsVisibleTo) { + string assembly_name = a.GetString (); + if (assembly_name.Length == 0) + return; + + AssemblyName aname = null; + try { + aname = new AssemblyName (assembly_name); + } catch (Exception) { + Report.Warning (1700, 3, a.Location, "Assembly reference `{0}' is invalid and cannot be resolved", + assembly_name); + return; + } + + if (aname.Version != null || aname.CultureInfo != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) { + Report.Error (1725, a.Location, + "Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified", + assembly_name); + + return; + } + + // TODO: GetPublicKey () does not work on .NET when AssemblyName is constructed from a string + if (public_key != null && aname.GetPublicKey () == null) { + Report.Error (1726, a.Location, + "Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations", + assembly_name); + return; + } + } else if (a.Type == pa.RuntimeCompatibility) { + wrap_non_exception_throws_custom = true; + } else if (a.Type == pa.AssemblyFileVersion) { + string value = a.GetString (); + if (string.IsNullOrEmpty (value) || IsValidAssemblyVersion (value, false) == null) { + Report.Warning (1607, 1, a.Location, "The version number `{0}' specified for `{1}' is invalid", + value, a.Name); + return; + } + } + + + SetCustomAttribute (ctor, cdata); + } + + // + // When using assembly public key attributes InternalsVisibleTo key + // was not checked, we have to do it later when we actually know what + // our public key token is + // + void CheckReferencesPublicToken () + { + // TODO: It should check only references assemblies but there is + // no working SRE API + foreach (var entry in Importer.Assemblies) { + var a = entry as ImportedAssemblyDefinition; + if (a == null) + continue; + + if (public_key != null && !a.HasStrongName) { + Report.Error (1577, "Referenced assembly `{0}' does not have a strong name", + a.FullName); + } + + var ci = a.Assembly.GetName ().CultureInfo; + if (!ci.Equals (System.Globalization.CultureInfo.InvariantCulture)) { + Report.Warning (1607, 1, "Referenced assembly `{0}' has different culture setting of `{1}'", + a.Name, ci.Name); + } + + if (!a.IsFriendAssemblyTo (this)) + continue; + + var attr = a.GetAssemblyVisibleToName (this); + var atoken = attr.GetPublicKeyToken (); + + if (ArrayComparer.IsEqual (GetPublicKeyToken (), atoken)) + continue; + + Report.SymbolRelatedToPreviousError (a.Location); + Report.Error (281, + "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it", + attr.FullName, FullName); + } + } + + protected AssemblyName CreateAssemblyName () + { + var an = new AssemblyName (name); + + if (public_key != null && Compiler.Settings.Target != Target.Module) { + if (delay_sign) { + an.SetPublicKey (public_key); + } else { + if (public_key.Length == 16) { + Report.Error (1606, "Could not sign the assembly. ECMA key can only be used to delay-sign assemblies"); + } else if (private_key == null) { + Error_AssemblySigning ("The specified key file does not have a private key"); + } else { + an.KeyPair = private_key; + } + } + } + + return an; + } + + public virtual ModuleBuilder CreateModuleBuilder () + { + if (file_name == null) + throw new NotSupportedException ("transient module in static assembly"); + + var module_name = Path.GetFileName (file_name); + + // Always initialize module without symbolInfo. We could be framework dependent + // but returned ISymbolWriter does not have all what we need therefore some + // adaptor will be needed for now we alwayas emit MDB format when generating + // debug info + return Builder.DefineDynamicModule (module_name, module_name, false); + } + + public virtual void Emit () + { + if (Compiler.Settings.Target == Target.Module) { + module_target_attrs = new AssemblyAttributesPlaceholder (module, name); + module_target_attrs.CreateType (); + module_target_attrs.DefineType (); + module_target_attrs.Define (); + module.AddCompilerGeneratedClass (module_target_attrs); + } else if (added_modules != null) { + ReadModulesAssemblyAttributes (); + } + + if (Compiler.Settings.GenerateDebugInfo) { + symbol_writer = new MonoSymbolWriter (file_name); + + // Register all source files with symbol writer + foreach (var source in Compiler.SourceFiles) { + source.DefineSymbolInfo (symbol_writer); + } + + // TODO: global variables + SymbolWriter.symwriter = symbol_writer; + } + + module.Emit (); + + if (module.HasExtensionMethod) { + var pa = module.PredefinedAttributes.Extension; + if (pa.IsDefined) { + SetCustomAttribute (pa.Constructor, AttributeEncoder.Empty); + } + } + + if (!wrap_non_exception_throws_custom) { + PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility; + if (pa.IsDefined && pa.ResolveBuilder ()) { + var prop = module.PredefinedMembers.RuntimeCompatibilityWrapNonExceptionThrows.Get (); + if (prop != null) { + AttributeEncoder encoder = new AttributeEncoder (); + encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null)); + SetCustomAttribute (pa.Constructor, encoder.ToArray ()); + } + } + } + + if (declarative_security != null) { +#if STATIC + foreach (var entry in declarative_security) { + Builder.__AddDeclarativeSecurity (entry); + } +#else + var args = new PermissionSet[3]; + declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args[0]); + declarative_security.TryGetValue (SecurityAction.RequestOptional, out args[1]); + declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args[2]); + builder_extra.AddPermissionRequests (args); +#endif + } + + CheckReferencesPublicToken (); + + SetEntryPoint (); + } + + public byte[] GetPublicKeyToken () + { + if (public_key == null || public_key_token != null) + return public_key_token; + + HashAlgorithm ha = SHA1.Create (); + byte[] hash = ha.ComputeHash (public_key); + // we need the last 8 bytes in reverse order + public_key_token = new byte[8]; + Buffer.BlockCopy (hash, hash.Length - 8, public_key_token, 0, 8); + Array.Reverse (public_key_token, 0, 8); + return public_key_token; + } + + // + // Either keyFile or keyContainer has to be non-null + // + void LoadPublicKey (string keyFile, string keyContainer) + { + if (keyContainer != null) { + try { + private_key = new StrongNameKeyPair (keyContainer); + public_key = private_key.PublicKey; + } catch { + Error_AssemblySigning ("The specified key container `" + keyContainer + "' does not exist"); + } + + return; + } + + bool key_file_exists = File.Exists (keyFile); + + // + // For attribute based KeyFile do additional lookup + // in output assembly path + // + if (!key_file_exists && Compiler.Settings.StrongNameKeyFile == null) { + // + // The key file can be relative to output assembly + // + string test_path = Path.Combine (Path.GetDirectoryName (file_name), keyFile); + key_file_exists = File.Exists (test_path); + if (key_file_exists) + keyFile = test_path; + } + + if (!key_file_exists) { + Error_AssemblySigning ("The specified key file `" + keyFile + "' does not exist"); + return; + } + + using (FileStream fs = new FileStream (keyFile, FileMode.Open, FileAccess.Read)) { + byte[] snkeypair = new byte[fs.Length]; + fs.Read (snkeypair, 0, snkeypair.Length); + + // check for ECMA key + if (snkeypair.Length == 16) { + public_key = snkeypair; + return; + } + + try { + // take it, with or without, a private key + RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair); + // and make sure we only feed the public part to Sys.Ref + byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); + + // AssemblyName.SetPublicKey requires an additional header + byte[] publicKeyHeader = new byte[8] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00 }; + + // Encode public key + public_key = new byte[12 + publickey.Length]; + Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, publicKeyHeader.Length); + + // Length of Public Key (in bytes) + int lastPart = public_key.Length - 12; + public_key[8] = (byte) (lastPart & 0xFF); + public_key[9] = (byte) ((lastPart >> 8) & 0xFF); + public_key[10] = (byte) ((lastPart >> 16) & 0xFF); + public_key[11] = (byte) ((lastPart >> 24) & 0xFF); + + Buffer.BlockCopy (publickey, 0, public_key, 12, publickey.Length); + } catch { + Error_AssemblySigning ("The specified key file `" + keyFile + "' has incorrect format"); + return; + } + + if (delay_sign) + return; + + try { + // TODO: Is there better way to test for a private key presence ? + CryptoConvert.FromCapiPrivateKeyBlob (snkeypair); + private_key = new StrongNameKeyPair (snkeypair); + } catch { } + } + } + + void ReadModulesAssemblyAttributes () + { + foreach (var m in added_modules) { + var cattrs = m.ReadAssemblyAttributes (); + if (cattrs == null) + continue; + + module.OptAttributes.AddAttributes (cattrs); + } + } + + public void Resolve () + { + if (Compiler.Settings.Unsafe && module.PredefinedTypes.SecurityAction.Define ()) { + // + // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] + // when -unsafe option was specified + // + Location loc = Location.Null; + + MemberAccess system_security_permissions = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); + + var req_min = module.PredefinedMembers.SecurityActionRequestMinimum.Resolve (loc); + + Arguments pos = new Arguments (1); + pos.Add (new Argument (req_min.GetConstant (null))); + + Arguments named = new Arguments (1); + named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (Compiler.BuiltinTypes, true, loc))); + + Attribute g = new Attribute ("assembly", + new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"), + new Arguments[] { pos, named }, loc, false); + g.AttachTo (module, module); + var ctor = g.Resolve (); + if (ctor != null) { + g.ExtractSecurityPermissionSet (ctor, ref declarative_security); + } + } + + if (module.OptAttributes == null) + return; + + // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types. + if (!module.OptAttributes.CheckTargets()) + return; + + cls_attribute = module.ResolveAssemblyAttribute (module.PredefinedAttributes.CLSCompliant); + + if (cls_attribute != null) { + is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue (); + } + + if (added_modules != null && Compiler.Settings.VerifyClsCompliance && is_cls_compliant) { + foreach (var m in added_modules) { + if (!m.IsCLSCompliant) { + Report.Error (3013, + "Added modules must be marked with the CLSCompliant attribute to match the assembly", + m.Name); + } + } + } + + Attribute a = module.ResolveAssemblyAttribute (module.PredefinedAttributes.RuntimeCompatibility); + if (a != null) { + var val = a.GetNamedValue ("WrapNonExceptionThrows") as BoolConstant; + if (val != null) + wrap_non_exception_throws = val.Value; + } + } + + protected void ResolveAssemblySecurityAttributes () + { + string key_file = null; + string key_container = null; + + if (module.OptAttributes != null) { + foreach (Attribute a in module.OptAttributes.Attrs) { + // cannot rely on any resolve-based members before you call Resolve + if (a.ExplicitTarget != "assembly") + continue; + + // TODO: This code is buggy: comparing Attribute name without resolving is wrong. + // However, this is invoked by CodeGen.Init, when none of the namespaces + // are loaded yet. + // TODO: Does not handle quoted attributes properly + switch (a.Name) { + case "AssemblyKeyFile": + case "AssemblyKeyFileAttribute": + case "System.Reflection.AssemblyKeyFileAttribute": + if (Compiler.Settings.StrongNameKeyFile != null) { + Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); + Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", + "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); + } else { + string value = a.GetString (); + if (!string.IsNullOrEmpty (value)) { + Error_ObsoleteSecurityAttribute (a, "keyfile"); + key_file = value; + } + } + break; + case "AssemblyKeyName": + case "AssemblyKeyNameAttribute": + case "System.Reflection.AssemblyKeyNameAttribute": + if (Compiler.Settings.StrongNameKeyContainer != null) { + Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); + Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", + "keycontainer", "System.Reflection.AssemblyKeyNameAttribute"); + } else { + string value = a.GetString (); + if (!string.IsNullOrEmpty (value)) { + Error_ObsoleteSecurityAttribute (a, "keycontainer"); + key_container = value; + } + } + break; + case "AssemblyDelaySign": + case "AssemblyDelaySignAttribute": + case "System.Reflection.AssemblyDelaySignAttribute": + bool b = a.GetBoolean (); + if (b) { + Error_ObsoleteSecurityAttribute (a, "delaysign"); + } + + delay_sign = b; + break; + } + } + } + + // We came here only to report assembly attributes warnings + if (public_key != null) + return; + + // + // Load the strong key file found in attributes when no + // command line key was given + // + if (key_file != null || key_container != null) { + LoadPublicKey (key_file, key_container); + } else if (delay_sign) { + Report.Warning (1607, 1, "Delay signing was requested but no key file was given"); + } + } + + public void EmbedResources () + { + // + // Add Win32 resources + // + if (Compiler.Settings.Win32ResourceFile != null) { + Builder.DefineUnmanagedResource (Compiler.Settings.Win32ResourceFile); + } else { + Builder.DefineVersionInfoResource (); + } + + if (Compiler.Settings.Win32IconFile != null) { + builder_extra.DefineWin32IconResource (Compiler.Settings.Win32IconFile); + } + + if (Compiler.Settings.Resources != null) { + if (Compiler.Settings.Target == Target.Module) { + Report.Error (1507, "Cannot link resource file when building a module"); + } else { + int counter = 0; + foreach (var res in Compiler.Settings.Resources) { + if (!File.Exists (res.FileName)) { + Report.Error (1566, "Error reading resource file `{0}'", res.FileName); + continue; + } + + if (res.IsEmbeded) { + Stream stream; + if (counter++ < 10) { + stream = File.OpenRead (res.FileName); + } else { + // TODO: SRE API requires resource stream to be available during AssemblyBuilder::Save + // we workaround it by reading everything into memory to compile projects with + // many embedded resource (over 3500) references + stream = new MemoryStream (File.ReadAllBytes (res.FileName)); + } + + module.Builder.DefineManifestResource (res.Name, stream, res.Attributes); + } else { + Builder.AddResourceFile (res.Name, Path.GetFileName (res.FileName), res.Attributes); + } + } + } + } + } + + public void Save () + { + PortableExecutableKinds pekind; + ImageFileMachine machine; + + switch (Compiler.Settings.Platform) { + case Platform.X86: + pekind = PortableExecutableKinds.Required32Bit | PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.I386; + break; + case Platform.X64: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.AMD64; + break; + case Platform.IA64: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.IA64; + break; + case Platform.AnyCPU: + default: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.I386; + break; + } + + Compiler.TimeReporter.Start (TimeReporter.TimerType.OutputSave); + try { + if (Compiler.Settings.Target == Target.Module) { + SaveModule (pekind, machine); + } else { + Builder.Save (module.Builder.ScopeName, pekind, machine); + } + } catch (Exception e) { + Report.Error (16, "Could not write to file `" + name + "', cause: " + e.Message); + } + Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave); + + // Save debug symbols file + if (symbol_writer != null) { + // TODO: it should run in parallel + Compiler.TimeReporter.Start (TimeReporter.TimerType.DebugSave); + symbol_writer.WriteSymbolFile (SymbolWriter.GetGuid (module.Builder)); + Compiler.TimeReporter.Stop (TimeReporter.TimerType.DebugSave); + } + } + + protected virtual void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine) + { + Report.RuntimeMissingSupport (Location.Null, "-target:module"); + } + + void SetCustomAttribute (MethodSpec ctor, byte[] data) + { + if (module_target_attrs != null) + module_target_attrs.AddAssemblyAttribute (ctor, data); + else + Builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data); + } + + void SetEntryPoint () + { + if (!Compiler.Settings.NeedsEntryPoint) { + if (Compiler.Settings.MainClass != null) + Report.Error (2017, "Cannot specify -main if building a module or library"); + + return; + } + + PEFileKinds file_kind; + + switch (Compiler.Settings.Target) { + case Target.Library: + case Target.Module: + file_kind = PEFileKinds.Dll; + break; + case Target.WinExe: + file_kind = PEFileKinds.WindowApplication; + break; + default: + file_kind = PEFileKinds.ConsoleApplication; + break; + } + + if (entry_point == null) { + string main_class = Compiler.Settings.MainClass; + if (main_class != null) { + // TODO: Handle dotted names + var texpr = module.GlobalRootNamespace.LookupType (module, main_class, 0, LookupMode.Probing, Location.Null); + if (texpr == null) { + Report.Error (1555, "Could not find `{0}' specified for Main method", main_class); + return; + } + + var mtype = texpr.Type.MemberDefinition as ClassOrStruct; + if (mtype == null) { + Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", main_class); + return; + } + + Report.Error (1558, mtype.Location, "`{0}' does not have a suitable static Main method", mtype.GetSignatureForError ()); + } else { + string pname = file_name == null ? name : Path.GetFileName (file_name); + Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point", + pname); + } + + return; + } + + Builder.SetEntryPoint (entry_point.MethodBuilder, file_kind); + } + + void Error_ObsoleteSecurityAttribute (Attribute a, string option) + { + Report.Warning (1699, 1, a.Location, + "Use compiler option `{0}' or appropriate project settings instead of `{1}' attribute", + option, a.Name); + } + + void Error_AssemblySigning (string text) + { + Report.Error (1548, "Error during assembly signing. " + text); + } + + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) + { + return false; + } + + static Version IsValidAssemblyVersion (string version, bool allowGenerated) + { + string[] parts = version.Split ('.'); + if (parts.Length < 1 || parts.Length > 4) + return null; + + var values = new int[4]; + for (int i = 0; i < parts.Length; ++i) { + if (!int.TryParse (parts[i], out values[i])) { + if (parts[i].Length == 1 && parts[i][0] == '*' && allowGenerated) { + if (i == 2) { + // Nothing can follow * + if (parts.Length > 3) + return null; + + // Generate Build value based on days since 1/1/2000 + TimeSpan days = DateTime.Today - new DateTime (2000, 1, 1); + values[i] = System.Math.Max (days.Days, 0); + i = 3; + } + + if (i == 3) { + // Generate Revision value based on every other second today + var seconds = DateTime.Now - DateTime.Today; + values[i] = (int) seconds.TotalSeconds / 2; + continue; + } + } + + return null; + } + + if (values[i] > ushort.MaxValue) + return null; + } + + return new Version (values[0], values[1], values[2], values[3]); + } + } + + public class AssemblyResource : IEquatable + { + public AssemblyResource (string fileName, string name) + : this (fileName, name, false) + { + } + + public AssemblyResource (string fileName, string name, bool isPrivate) + { + FileName = fileName; + Name = name; + Attributes = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public; + } + + public ResourceAttributes Attributes { get; private set; } + public string Name { get; private set; } + public string FileName { get; private set; } + public bool IsEmbeded { get; set; } + + #region IEquatable Members + + public bool Equals (AssemblyResource other) + { + return Name == other.Name; + } + + #endregion + } + + // + // A placeholder class for assembly attributes when emitting module + // + class AssemblyAttributesPlaceholder : CompilerGeneratedClass + { + static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>"; + public static readonly string AssemblyFieldName = "attributes"; + + Field assembly; + + public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName) + : base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC) + { + assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC, + new MemberName (AssemblyFieldName), null); + + AddField (assembly); + } + + public void AddAssemblyAttribute (MethodSpec ctor, byte[] data) + { + assembly.SetCustomAttribute (ctor, data); + } + + public static string GetGeneratedName (string outputName) + { + return string.Format (TypeNamePrefix, outputName); + } + } + + // + // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible + // compiler. This is a default implementation for framework System.Reflection.Emit + // which does not implement any of the methods + // + public class AssemblyBuilderExtension + { + readonly CompilerContext ctx; + + public AssemblyBuilderExtension (CompilerContext ctx) + { + this.ctx = ctx; + } + + public virtual System.Reflection.Module AddModule (string module) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "-addmodule"); + return null; + } + + public virtual void AddPermissionRequests (PermissionSet[] permissions) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "assembly declarative security"); + } + + public virtual void AddTypeForwarder (TypeSpec type, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "TypeForwardedToAttribute"); + } + + public virtual void DefineWin32IconResource (string fileName) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "-win32icon"); + } + + public virtual void SetAlgorithmId (uint value, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyAlgorithmIdAttribute"); + } + + public virtual void SetCulture (string culture, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyCultureAttribute"); + } + + public virtual void SetFlags (uint flags, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyFlagsAttribute"); + } + + public virtual void SetVersion (Version version, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyVersionAttribute"); + } + } + + abstract class AssemblyReferencesLoader + { + protected readonly CompilerContext compiler; + + protected readonly List paths; + + public AssemblyReferencesLoader (CompilerContext compiler) + { + this.compiler = compiler; + + paths = new List (); + paths.AddRange (compiler.Settings.ReferencesLookupPaths); + paths.Add (Directory.GetCurrentDirectory ()); + } + + public abstract bool HasObjectType (T assembly); + protected abstract string[] GetDefaultReferences (); + public abstract T LoadAssemblyFile (string fileName); + public abstract T LoadAssemblyDefault (string assembly); + public abstract void LoadReferences (ModuleContainer module); + + protected void Error_FileNotFound (string fileName) + { + compiler.Report.Error (6, "Metadata file `{0}' could not be found", fileName); + } + + protected void Error_FileCorrupted (string fileName) + { + compiler.Report.Error (9, "Metadata file `{0}' does not contain valid metadata", fileName); + } + + protected void Error_AssemblyIsModule (string fileName) + { + compiler.Report.Error (1509, + "Referenced assembly file `{0}' is a module. Consider using `-addmodule' option to add the module", + fileName); + } + + protected void Error_ModuleIsAssembly (string fileName) + { + compiler.Report.Error (1542, + "Added module file `{0}' is an assembly. Consider using `-r' option to reference the file", + fileName); + } + + protected void LoadReferencesCore (ModuleContainer module, out T corlib_assembly, out List> loaded) + { + compiler.TimeReporter.Start (TimeReporter.TimerType.ReferencesLoading); + + loaded = new List> (); + + // + // Load mscorlib.dll as the first + // + if (module.Compiler.Settings.StdLib) { + corlib_assembly = LoadAssemblyDefault ("mscorlib.dll"); + } else { + corlib_assembly = default (T); + } + + T a; + foreach (string r in module.Compiler.Settings.AssemblyReferences) { + a = LoadAssemblyFile (r); + if (a == null || EqualityComparer.Default.Equals (a, corlib_assembly)) + continue; + + var key = Tuple.Create (module.GlobalRootNamespace, a); + if (loaded.Contains (key)) + continue; + + // A corlib assembly is the first assembly which contains System.Object + if (corlib_assembly == null && HasObjectType (a)) { + corlib_assembly = a; + continue; + } + + loaded.Add (key); + } + + foreach (var entry in module.Compiler.Settings.AssemblyReferencesAliases) { + a = LoadAssemblyFile (entry.Item2); + if (a == null) + continue; + + var key = Tuple.Create (module.CreateRootNamespace (entry.Item1), a); + if (loaded.Contains (key)) + continue; + + loaded.Add (key); + } + + if (compiler.Settings.LoadDefaultReferences) { + foreach (string r in GetDefaultReferences ()) { + a = LoadAssemblyDefault (r); + if (a == null) + continue; + + var key = Tuple.Create (module.GlobalRootNamespace, a); + if (loaded.Contains (key)) + continue; + + loaded.Add (key); + } + } + + compiler.TimeReporter.Stop (TimeReporter.TimerType.ReferencesLoading); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs new file mode 100644 index 0000000000..6fd2a7a03a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs @@ -0,0 +1,786 @@ +// +// assign.cs: Assignments. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004-2008 Novell, Inc +// +using System; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// This interface is implemented by expressions that can be assigned to. + /// + /// + /// This interface is implemented by Expressions whose values can not + /// store the result on the top of the stack. + /// + /// Expressions implementing this (Properties, Indexers and Arrays) would + /// perform an assignment of the Expression "source" into its final + /// location. + /// + /// No values on the top of the stack are expected to be left by + /// invoking this method. + /// + public interface IAssignMethod { + // + // This is an extra version of Emit. If leave_copy is `true' + // A copy of the expression will be left on the stack at the + // end of the code generated for EmitAssign + // + void Emit (EmitContext ec, bool leave_copy); + + // + // This method does the assignment + // `source' will be stored into the location specified by `this' + // if `leave_copy' is true, a copy of `source' will be left on the stack + // if `prepare_for_load' is true, when `source' is emitted, there will + // be data on the stack that it can use to compuatate its value. This is + // for expressions like a [f ()] ++, where you can't call `f ()' twice. + // + void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + + /* + For simple assignments, this interface is very simple, EmitAssign is called with source + as the source expression and leave_copy and prepare_for_load false. + + For compound assignments it gets complicated. + + EmitAssign will be called as before, however, prepare_for_load will be + true. The @source expression will contain an expression + which calls Emit. So, the calls look like: + + this.EmitAssign (ec, source, false, true) -> + source.Emit (ec); -> + [...] -> + this.Emit (ec, false); -> + end this.Emit (ec, false); -> + end [...] + end source.Emit (ec); + end this.EmitAssign (ec, source, false, true) + + + When prepare_for_load is true, EmitAssign emits a `token' on the stack that + Emit will use for its state. + + Let's take FieldExpr as an example. assume we are emitting f ().y += 1; + + Here is the call tree again. This time, each call is annotated with the IL + it produces: + + this.EmitAssign (ec, source, false, true) + call f + dup + + Binary.Emit () + this.Emit (ec, false); + ldfld y + end this.Emit (ec, false); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + stfld + end this.EmitAssign (ec, source, false, true) + + Observe two things: + 1) EmitAssign left a token on the stack. It was the result of f (). + 2) This token was used by Emit + + leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy + of the expression at that point in evaluation. This is used for pre/post inc/dec + and for a = x += y. Let's do the above example with leave_copy true in EmitAssign + + this.EmitAssign (ec, source, true, true) + call f + dup + + Binary.Emit () + this.Emit (ec, false); + ldfld y + end this.Emit (ec, false); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + dup + stloc temp + stfld + ldloc temp + end this.EmitAssign (ec, source, true, true) + + And with it true in Emit + + this.EmitAssign (ec, source, false, true) + call f + dup + + Binary.Emit () + this.Emit (ec, true); + ldfld y + dup + stloc temp + end this.Emit (ec, true); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + stfld + ldloc temp + end this.EmitAssign (ec, source, false, true) + + Note that these two examples are what happens for ++x and x++, respectively. + */ + } + + /// + /// An Expression to hold a temporary value. + /// + /// + /// The LocalTemporary class is used to hold temporary values of a given + /// type to "simulate" the expression semantics. The local variable is + /// never captured. + /// + /// The local temporary is used to alter the normal flow of code generation + /// basically it creates a local variable, and its emit instruction generates + /// code to access this value, return its address or save its value. + /// + /// If `is_address' is true, then the value that we store is the address to the + /// real value, and not the value itself. + /// + /// This is needed for a value type, because otherwise you just end up making a + /// copy of the value on the stack and modifying it. You really need a pointer + /// to the origional value so that you can modify it in that location. This + /// Does not happen with a class because a class is a pointer -- so you always + /// get the indirection. + /// + /// + public class LocalTemporary : Expression, IMemoryLocation, IAssignMethod { + LocalBuilder builder; + + public LocalTemporary (TypeSpec t) + { + type = t; + eclass = ExprClass.Value; + } + + public LocalTemporary (LocalBuilder b, TypeSpec t) + : this (t) + { + builder = b; + } + + public void Release (EmitContext ec) + { + ec.FreeTemporaryLocal (builder, type); + builder = null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + if (builder == null) + throw new InternalErrorException ("Emit without Store, or after Release"); + + ec.Emit (OpCodes.Ldloc, builder); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + Emit (ec); + + if (leave_copy) + Emit (ec); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + if (prepare_for_load) + throw new NotImplementedException (); + + source.Emit (ec); + + Store (ec); + + if (leave_copy) + Emit (ec); + } + + #endregion + + public LocalBuilder Builder { + get { return builder; } + } + + public void Store (EmitContext ec) + { + if (builder == null) + builder = ec.GetTemporaryLocal (type); + + ec.Emit (OpCodes.Stloc, builder); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + if (builder == null) + builder = ec.GetTemporaryLocal (type); + + if (builder.LocalType.IsByRef) { + // + // if is_address, than this is just the address anyways, + // so we just return this. + // + ec.Emit (OpCodes.Ldloc, builder); + } else { + ec.Emit (OpCodes.Ldloca, builder); + } + } + } + + /// + /// The Assign node takes care of assigning the value of source into + /// the expression represented by target. + /// + public abstract class Assign : ExpressionStatement { + protected Expression target, source; + + protected Assign (Expression target, Expression source, Location loc) + { + this.target = target; + this.source = source; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator"); + return null; + } + + public Expression Target { + get { return target; } + } + + public Expression Source { + get { + return source; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + bool ok = true; + source = source.Resolve (ec); + + if (source == null) { + ok = false; + source = EmptyExpression.Null; + } + + target = target.ResolveLValue (ec, source); + + if (target == null || !ok) + return null; + + TypeSpec target_type = target.Type; + TypeSpec source_type = source.Type; + + eclass = ExprClass.Value; + type = target_type; + + if (!(target is IAssignMethod)) { + Error_ValueAssignment (ec, loc); + return null; + } + + if (target_type != source_type) { + Expression resolved = ResolveConversions (ec); + + if (resolved != this) + return resolved; + } + + return this; + } + +#if NET_4_0 + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + var tassign = target as IDynamicAssign; + if (tassign == null) + throw new InternalErrorException (target.GetType () + " does not support dynamic assignment"); + + var target_object = tassign.MakeAssignExpression (ctx, source); + + // + // Some hacking is needed as DLR does not support void type and requires + // always have object convertible return type to support caching and chaining + // + // We do this by introducing an explicit block which returns RHS value when + // available or null + // + if (target_object.NodeType == System.Linq.Expressions.ExpressionType.Block) + return target_object; + + System.Linq.Expressions.UnaryExpression source_object; + if (ctx.HasSet (BuilderContext.Options.CheckedScope)) { + source_object = System.Linq.Expressions.Expression.ConvertChecked (source.MakeExpression (ctx), target_object.Type); + } else { + source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type); + } + + return System.Linq.Expressions.Expression.Assign (target_object, source_object); + } +#endif + protected virtual Expression ResolveConversions (ResolveContext ec) + { + source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location); + if (source == null) + return null; + + return this; + } + + void Emit (EmitContext ec, bool is_statement) + { + IAssignMethod t = (IAssignMethod) target; + t.EmitAssign (ec, source, !is_statement, this is CompoundAssign); + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec, true); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Assign _target = (Assign) t; + + _target.target = target.Clone (clonectx); + _target.source = source.Clone (clonectx); + } + } + + public class SimpleAssign : Assign + { + public SimpleAssign (Expression target, Expression source) + : this (target, source, target.Location) + { + } + + public SimpleAssign (Expression target, Expression source, Location loc) + : base (target, source, loc) + { + } + + bool CheckEqualAssign (Expression t) + { + if (source is Assign) { + Assign a = (Assign) source; + if (t.Equals (a.Target)) + return true; + return a is SimpleAssign && ((SimpleAssign) a).CheckEqualAssign (t); + } + return t.Equals (source); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = base.DoResolve (ec); + if (e == null || e != this) + return e; + + if (CheckEqualAssign (target)) + ec.Report.Warning (1717, 3, loc, "Assignment made to same variable; did you mean to assign something else?"); + + return this; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RuntimeExplicitAssign : Assign + { + public RuntimeExplicitAssign (Expression target, Expression source) + : base (target, source, target.Location) + { + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + source = EmptyCast.Create (source, target.Type); + return this; + } + } + + // + // Compiler generated assign + // + class CompilerAssign : Assign + { + public CompilerAssign (Expression target, Expression source, Location loc) + : base (target, source, loc) + { + } + + public void UpdateSource (Expression source) + { + base.source = source; + } + } + + // + // Implements fields and events class initializers + // + public class FieldInitializer : Assign + { + // + // Field initializers are tricky for partial classes. They have to + // share same constructor (block) for expression trees resolve but + // they have they own resolve scope + // + sealed class FieldInitializerContext : ResolveContext + { + ExplicitBlock ctor_block; + + public FieldInitializerContext (IMemberContext mc, ResolveContext constructorContext) + : base (mc, Options.FieldInitializerScope | Options.ConstructorScope) + { + this.ctor_block = constructorContext.CurrentBlock.Explicit; + } + + public override ExplicitBlock ConstructorBlock { + get { + return ctor_block; + } + } + } + + // + // Keep resolved value because field initializers have their own rules + // + ExpressionStatement resolved; + IMemberContext mc; + + public FieldInitializer (FieldSpec spec, Expression expression, IMemberContext mc) + : base (new FieldExpr (spec, expression.Location), expression, expression.Location) + { + this.mc = mc; + if (!spec.IsStatic) + ((FieldExpr)target).InstanceExpression = new CompilerGeneratedThis (mc.CurrentType, expression.Location); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // Field initializer can be resolved (fail) many times + if (source == null) + return null; + + if (resolved == null) { + var ctx = new FieldInitializerContext (mc, ec); + resolved = base.DoResolve (ctx) as ExpressionStatement; + } + + return resolved; + } + + public override void EmitStatement (EmitContext ec) + { + if (resolved == null) + return; + + if (resolved != this) + resolved.EmitStatement (ec); + else + base.EmitStatement (ec); + } + + public bool IsComplexInitializer { + get { return !(source is Constant); } + } + + public bool IsDefaultInitializer { + get { + Constant c = source as Constant; + if (c == null) + return false; + + FieldExpr fe = (FieldExpr)target; + return c.IsDefaultInitializer (fe.Type); + } + } + } + + // + // This class is used for compound assignments. + // + public class CompoundAssign : Assign + { + // This is just a hack implemented for arrays only + public sealed class TargetExpression : Expression + { + Expression child; + public TargetExpression (Expression child) + { + this.child = child; + this.loc = child.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = child.Type; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + } + + // Used for underlying binary operator + readonly Binary.Operator op; + Expression right; + Expression left; + + public Binary.Operator Op { + get { + return op; + } + } + + public CompoundAssign (Binary.Operator op, Expression target, Expression source, Location loc) + : base (target, source, loc) + { + right = source; + this.op = op; + } + + public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left, Location loc) + : this (op, target, source, loc) + { + this.left = left; + } + + protected override Expression DoResolve (ResolveContext ec) + { + right = right.Resolve (ec); + if (right == null) + return null; + + MemberAccess ma = target as MemberAccess; + using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) { + target = target.Resolve (ec); + } + + if (target == null) + return null; + + if (target is MethodGroupExpr){ + ec.Report.Error (1656, loc, + "Cannot assign to `{0}' because it is a `{1}'", + ((MethodGroupExpr)target).Name, target.ExprClassName); + return null; + } + + var event_expr = target as EventExpr; + if (event_expr != null) { + source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc); + if (source == null) + return null; + + Expression rside; + if (op == Binary.Operator.Addition) + rside = EmptyExpression.EventAddition; + else if (op == Binary.Operator.Subtraction) + rside = EmptyExpression.EventSubtraction; + else + rside = null; + + target = target.ResolveLValue (ec, rside); + if (target == null) + return null; + + eclass = ExprClass.Value; + type = event_expr.Operator.ReturnType; + return this; + } + + // + // Only now we can decouple the original source/target + // into a tree, to guarantee that we do not have side + // effects. + // + if (left == null) + left = new TargetExpression (target); + + source = new Binary (op, left, right, true, loc); + + if (target is DynamicMemberAssignable) { + Arguments targs = ((DynamicMemberAssignable) target).Arguments; + source = source.Resolve (ec); + + Arguments args = new Arguments (targs.Count + 1); + args.AddRange (targs); + args.Add (new Argument (source)); + + var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; + + // + // Compound assignment does target conversion using additional method + // call, set checked context as the binary operation can overflow + // + if (ec.HasSet (ResolveContext.Options.CheckedScope)) + binder_flags |= CSharpBinderFlags.CheckedContext; + + if (target is DynamicMemberBinder) { + source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec); + + // Handles possible event addition/subtraction + if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { + args = new Arguments (targs.Count + 1); + args.AddRange (targs); + args.Add (new Argument (right)); + string method_prefix = op == Binary.Operator.Addition ? + Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; + + var invoke = DynamicInvocation.CreateSpecialNameInvoke ( + new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec); + + args = new Arguments (targs.Count); + args.AddRange (targs); + source = new DynamicEventCompoundAssign (ma.Name, args, + (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); + } + } else { + source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec); + } + + return source; + } + + return base.DoResolve (ec); + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + // + // LAMESPEC: Under dynamic context no target conversion is happening + // This allows more natual dynamic behaviour but breaks compatibility + // with static binding + // + if (target is RuntimeValueExpression) + return this; + + TypeSpec target_type = target.Type; + + // + // 1. the return type is implicitly convertible to the type of target + // + if (Convert.ImplicitConversionExists (ec, source, target_type)) { + source = Convert.ImplicitConversion (ec, source, target_type, loc); + return this; + } + + // + // Otherwise, if the selected operator is a predefined operator + // + Binary b = source as Binary; + if (b == null && source is ReducedExpression) + b = ((ReducedExpression) source).OriginalExpression as Binary; + + if (b != null) { + // + // 2a. the operator is a shift operator + // + // 2b. the return type is explicitly convertible to the type of x, and + // y is implicitly convertible to the type of x + // + if ((b.Oper & Binary.Operator.ShiftMask) != 0 || + Convert.ImplicitConversionExists (ec, right, target_type)) { + source = Convert.ExplicitConversion (ec, source, target_type, loc); + return this; + } + } + + if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments arg = new Arguments (1); + arg.Add (new Argument (source)); + return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec); + } + + right.Error_ValueCannotBeConverted (ec, loc, target_type, false); + return null; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CompoundAssign ctarget = (CompoundAssign) t; + + ctarget.right = ctarget.source = source.Clone (clonectx); + ctarget.target = target.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs new file mode 100644 index 0000000000..1a1345013f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs @@ -0,0 +1,614 @@ +// +// async.cs: Asynchronous functions +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2011 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + class Await : ExpressionStatement + { + Expression expr; + AwaitStatement stmt; + + public Await (Expression expr, Location loc) + { + this.expr = expr; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + var t = (Await) target; + + t.expr = expr.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + if (rc.HasSet (ResolveContext.Options.FinallyScope)) { + rc.Report.Error (1984, loc, + "The `await' operator cannot be used in the body of a finally clause"); + } + + if (rc.HasSet (ResolveContext.Options.CatchScope)) { + rc.Report.Error (1985, loc, + "The `await' operator cannot be used in the body of a catch clause"); + } + + if (rc.HasSet (ResolveContext.Options.LockScope)) { + rc.Report.Error (1996, loc, + "The `await' operator cannot be used in the body of a lock statement"); + } + + if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { + rc.Report.Error (1989, loc, "An expression tree cannot contain an await operator"); + return null; + } + + if (rc.IsUnsafe) { + // TODO: New error code + rc.Report.Error (-1900, loc, + "The `await' operator cannot be used in an unsafe context"); + } + + var bc = (BlockContext) rc; + + if (!bc.CurrentBlock.ParametersBlock.IsAsync) { + // TODO: Should check for existence of await type but + // what to do with it + } + + stmt = new AwaitStatement (expr, loc); + if (!stmt.Resolve (bc)) + return null; + + type = stmt.ResultType; + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + stmt.EmitPrologue (ec); + stmt.Emit (ec); + } + + public void EmitAssign (EmitContext ec, FieldExpr field) + { + stmt.EmitPrologue (ec); + field.InstanceExpression.Emit (ec); + stmt.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + stmt.EmitStatement (ec); + } + } + + class AwaitStatement : YieldStatement + { + sealed class AwaitableMemberAccess : MemberAccess + { + public AwaitableMemberAccess (Expression expr) + : base (expr, "GetAwaiter") + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name) + { + Error_WrongGetAwaiter (rc, loc, type); + } + + protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + rc.Report.Error (1991, loc, "Cannot await `{0}' expression", type.GetSignatureForError ()); + } + } + + Field awaiter; + PropertyExpr is_completed; + MethodSpec on_completed; + MethodSpec get_result; + TypeSpec type; + + public AwaitStatement (Expression expr, Location loc) + : base (expr, loc) + { + } + + #region Properties + + public TypeSpec Type { + get { + return type; + } + } + + public TypeSpec ResultType { + get { + return get_result.ReturnType; + } + } + + #endregion + + protected override void DoEmit (EmitContext ec) + { + var fe_awaiter = new FieldExpr (awaiter, loc); + fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + + // + // result = awaiter.GetResult (); + // + var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc); + mg_result.InstanceExpression = fe_awaiter; + + mg_result.EmitCall (ec, new Arguments (0)); + } + + public void EmitPrologue (EmitContext ec) + { + var fe_awaiter = new FieldExpr (awaiter, loc); + fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + + // + // awaiter = expr.GetAwaiter (); + // + fe_awaiter.EmitAssign (ec, expr, false, false); + + is_completed.InstanceExpression = fe_awaiter; + is_completed.EmitBranchable (ec, resume_point, true); + + var mg_completed = MethodGroupExpr.CreatePredefined (on_completed, fe_awaiter.Type, loc); + mg_completed.InstanceExpression = fe_awaiter; + + var args = new Arguments (1); + var storey = (AsyncTaskStorey) machine_initializer.Storey; + var fe_cont = new FieldExpr (storey.Continuation, loc); + fe_cont.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + + args.Add (new Argument (fe_cont)); + + // + // awaiter.OnCompleted (continuation); + // + mg_completed.EmitCall (ec, args); + + base.DoEmit (ec); + } + + public void EmitStatement (EmitContext ec) + { + EmitPrologue (ec); + Emit (ec); + + if (ResultType.Kind != MemberKind.Void) { + var storey = (AsyncTaskStorey) machine_initializer.Storey; + + if (storey.HoistedReturn != null) + storey.HoistedReturn.EmitAssign (ec); + else + ec.Emit (OpCodes.Pop); + } + } + + static void Error_WrongGetAwaiter (ResolveContext rc, Location loc, TypeSpec type) + { + rc.Report.Error (1986, loc, + "The `await' operand type `{0}' must have suitable GetAwaiter method", + type.GetSignatureForError ()); + } + + void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter) + { + rc.Report.Error (1999, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members", + awaiter.GetSignatureForError ()); + } + + public override bool Resolve (BlockContext bc) + { + if (!base.Resolve (bc)) + return false; + + type = expr.Type; + + // + // The task result is of dynamic type + // + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + throw new NotImplementedException ("dynamic await"); + + // + // Check whether the expression is awaitable + // + Expression ama = new AwaitableMemberAccess (expr).Resolve (bc); + if (ama == null) + return false; + + Arguments args = new Arguments (0); + + var errors_printer = new SessionReportPrinter (); + var old = bc.Report.SetPrinter (errors_printer); + ama = new Invocation (ama, args).Resolve (bc); + + if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) { + bc.Report.SetPrinter (old); + Error_WrongGetAwaiter (bc, loc, expr.Type); + return false; + } + + var awaiter_type = ama.Type; + awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (awaiter_type, loc); + expr = ama; + + // + // Predefined: bool IsCompleted { get; } + // + var is_completed_ma = new MemberAccess (expr, "IsCompleted").Resolve (bc); + if (is_completed_ma != null) { + is_completed = is_completed_ma as PropertyExpr; + if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null) { + // valid + } else { + bc.Report.SetPrinter (old); + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + } + + bc.Report.SetPrinter (old); + + if (errors_printer.ErrorsCount > 0) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + + // + // Predefined: OnCompleted (Action) + // + if (bc.Module.PredefinedTypes.Action.Define ()) { + on_completed = MemberCache.FindMember (awaiter_type, MemberFilter.Method ("OnCompleted", 0, + ParametersCompiled.CreateFullyResolved (bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (on_completed == null) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + } + + // + // Predefined: GetResult () + // + // The method return type is also result type of await expression + // + get_result = MemberCache.FindMember (awaiter_type, MemberFilter.Method ("GetResult", 0, + ParametersCompiled.EmptyReadOnlyParameters, null), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (get_result == null) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + + return true; + } + } + + public class AsyncInitializer : StateMachineInitializer + { + TypeInferenceContext return_inference; + + public AsyncInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType) + : base (block, host, returnType) + { + } + + #region Properties + + public override string ContainerType { + get { + return "async state machine block"; + } + } + + public override bool IsIterator { + get { + return false; + } + } + + public Block OriginalBlock { + get { + return block.Parent; + } + } + + public TypeInferenceContext ReturnTypeInference { + get { + return return_inference; + } + } + + #endregion + + public static void Create (ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc) + { + if (returnType != null && returnType.Kind != MemberKind.Void && + returnType != host.Module.PredefinedTypes.Task.TypeSpec && + !returnType.IsGenericTask) { + host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task"); + } + + for (int i = 0; i < parameters.Count; i++) { + Parameter p = parameters[i]; + Parameter.Modifier mod = p.ModFlags; + if ((mod & Parameter.Modifier.ISBYREF) != 0) { + host.Compiler.Report.Error (1988, p.Location, + "Async methods cannot have ref or out parameters"); + return; + } + + // TODO: + if (p is ArglistParameter) { + host.Compiler.Report.Error (1636, p.Location, + "__arglist is not allowed in parameter list of iterators"); + return; + } + + // TODO: + if (parameters.Types[i].IsPointer) { + host.Compiler.Report.Error (1637, p.Location, + "Iterators cannot have unsafe parameters or yield types"); + return; + } + } + + // TODO: Warning + //if (!block.HasAwait) { + //} + + block.WrapIntoAsyncTask (host, returnType); + } + + protected override BlockContext CreateBlockContext (ResolveContext rc) + { + var ctx = base.CreateBlockContext (rc); + var lambda = rc.CurrentAnonymousMethod as LambdaMethod; + if (lambda != null) + return_inference = lambda.ReturnTypeInference; + + return ctx; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + + protected override void EmitMoveNextEpilogue (EmitContext ec) + { + var storey = (AsyncTaskStorey) Storey; + storey.EmitSetResult (ec); + } + + public override void EmitStatement (EmitContext ec) + { + var storey = (AsyncTaskStorey) Storey; + storey.Instance.Emit (ec); + ec.Emit (OpCodes.Call, storey.StateMachineMethod.Spec); + + if (storey.Task != null) { + // + // async.$builder.Task; + // + var pe_task = new PropertyExpr (storey.Task, loc) { + InstanceExpression = new FieldExpr (storey.Builder, loc) { + InstanceExpression = storey.Instance + }, + Getter = storey.Task.Get + }; + + pe_task.Emit (ec); + } + + ec.Emit (OpCodes.Ret); + } + + public override void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + } + + class AsyncTaskStorey : StateMachine + { + int awaiters; + Field builder, continuation; + readonly TypeSpec return_type; + MethodSpec set_result; + PropertySpec task; + LocalVariable hoisted_return; + + public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type) + : base (initializer.OriginalBlock, initializer.Host, null, null, "async") + { + return_type = type; + } + + public Field AddAwaiter (TypeSpec type, Location loc) + { + return AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, loc)); + } + + #region Properties + + public Field Builder { + get { + return builder; + } + } + + public Field Continuation { + get { + return continuation; + } + } + + public LocalVariable HoistedReturn { + get { + return hoisted_return; + } + } + + public TypeSpec ReturnType { + get { + return return_type; + } + } + + public PropertySpec Task { + get { + return task; + } + } + + #endregion + + protected override bool DoDefineMembers () + { + var action = Module.PredefinedTypes.Action.Resolve (); + if (action != null) { + continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location)); + continuation.ModFlags |= Modifiers.READONLY; + } + + PredefinedType builder_type; + PredefinedMember bf; + PredefinedMember sr; + bool has_task_return_type = false; + var pred_members = Module.PredefinedMembers; + + if (return_type.Kind == MemberKind.Void) { + builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; + bf = pred_members.AsyncVoidMethodBuilderCreate; + sr = pred_members.AsyncVoidMethodBuilderSetResult; + } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; + bf = pred_members.AsyncTaskMethodBuilderCreate; + sr = pred_members.AsyncTaskMethodBuilderSetResult; + task = pred_members.AsyncTaskMethodBuilderTask.Resolve (Location); + } else { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; + bf = pred_members.AsyncTaskMethodBuilderGenericCreate; + sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; + task = pred_members.AsyncTaskMethodBuilderGenericTask.Resolve (Location); + has_task_return_type = true; + } + + set_result = sr.Resolve (Location); + var builder_factory = bf.Resolve (Location); + var bt = builder_type.Resolve (); + if (bt == null || set_result == null || builder_factory == null) + return false; + + // + // Inflate generic Task types + // + if (has_task_return_type) { + bt = bt.MakeGenericType (Module, return_type.TypeArguments); + builder_factory = MemberCache.GetMember (bt, builder_factory); + set_result = MemberCache.GetMember (bt, set_result); + + if (task != null) + task = MemberCache.GetMember (bt, task); + } + + builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location)); + builder.ModFlags |= Modifiers.READONLY; + + if (!base.DoDefineMembers ()) + return false; + + MethodGroupExpr mg; + var block = instance_constructors[0].Block; + + // + // Initialize continuation with state machine method + // + if (continuation != null) { + var args = new Arguments (1); + mg = MethodGroupExpr.CreatePredefined (StateMachineMethod.Spec, spec, Location); + args.Add (new Argument (mg)); + + block.AddStatement ( + new StatementExpression (new SimpleAssign ( + new FieldExpr (continuation, Location), + new NewDelegate (action, args, Location), + Location + ))); + } + + mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location); + block.AddStatement ( + new StatementExpression (new SimpleAssign ( + new FieldExpr (builder, Location), + new Invocation (mg, new Arguments (0)), + Location))); + + if (has_task_return_type) { + hoisted_return = LocalVariable.CreateCompilerGenerated (bt.TypeArguments[0], block, Location); + } + + return true; + } + + public void EmitSetResult (EmitContext ec) + { + // + // $builder.SetResult (); + // $builder.SetResult (value); + // + var mg = MethodGroupExpr.CreatePredefined (set_result, set_result.DeclaringType, Location); + mg.InstanceExpression = new FieldExpr (Builder, Location) { + InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location) + }; + + Arguments args; + if (hoisted_return == null) { + args = new Arguments (0); + } else { + args = new Arguments (1); + args.Add (new Argument (new LocalVariableReference (hoisted_return, Location))); + } + + mg.EmitCall (ec, args); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs new file mode 100644 index 0000000000..b58a81351f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs @@ -0,0 +1,2008 @@ +// +// attribute.cs: Attribute Handler +// +// Author: Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security; +using System.Security.Permissions; +using System.Text; +using System.IO; + +#if STATIC +using SecurityType = System.Collections.Generic.List; +using BadImageFormat = IKVM.Reflection.BadImageFormatException; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using BadImageFormat = System.BadImageFormatException; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Base class for objects that can have Attributes applied to them. + /// + public abstract class Attributable { + // + // Holds all attributes attached to this element + // + protected Attributes attributes; + + public void AddAttributes (Attributes attrs, IMemberContext context) + { + if (attrs == null) + return; + + if (attributes == null) + attributes = attrs; + else + attributes.AddAttributes (attrs.Attrs); + attrs.AttachTo (this, context); + } + + public Attributes OptAttributes { + get { + return attributes; + } + set { + attributes = value; + } + } + + /// + /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder + /// + public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa); + + /// + /// Returns one AttributeTarget for this element. + /// + public abstract AttributeTargets AttributeTargets { get; } + + public abstract bool IsClsComplianceRequired (); + + /// + /// Gets list of valid attribute targets for explicit target declaration. + /// The first array item is default target. Don't break this rule. + /// + public abstract string[] ValidAttributeTargets { get; } + }; + + public class Attribute : Expression + { + public readonly string ExplicitTarget; + public AttributeTargets Target; + readonly ATypeNameExpression expression; + + public Arguments PosArguments; + public Arguments NamedArguments; + + bool resolve_error; + bool arg_resolved; + readonly bool nameEscaped; + + // + // An attribute can be attached to multiple targets (e.g. multiple fields) + // + Attributable[] targets; + + // + // A member context for the attribute, it's much easier to hold it here + // than trying to pull it during resolve + // + IMemberContext context; + + public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All); + public static readonly object[] EmptyObject = new object [0]; + + List> named_values; + + public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped) + { + this.expression = expr; + if (args != null) { + PosArguments = args[0]; + NamedArguments = args[1]; + } + this.loc = loc; + ExplicitTarget = target; + this.nameEscaped = nameEscaped; + } + + void AddModuleCharSet (ResolveContext rc) + { + const string dll_import_char_set = "CharSet"; + + // + // Only when not customized by user + // + if (HasField (dll_import_char_set)) + return; + + if (!rc.Module.PredefinedTypes.CharSet.Define ()) { + return; + } + + if (NamedArguments == null) + NamedArguments = new Arguments (1); + + var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location); + NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value)); + } + + public Attribute Clone () + { + Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped); + a.PosArguments = PosArguments; + a.NamedArguments = NamedArguments; + return a; + } + + // + // When the same attribute is attached to multiple fiels + // we use @target field as a list of targets. The attribute + // has to be resolved only once but emitted for each target. + // + public void AttachTo (Attributable target, IMemberContext context) + { + if (this.targets == null) { + this.targets = new Attributable[] { target }; + this.context = context; + return; + } + + // When re-attaching global attributes + if (context is NamespaceContainer) { + this.targets[0] = target; + this.context = context; + return; + } + + // Resize target array + Attributable[] new_array = new Attributable [this.targets.Length + 1]; + targets.CopyTo (new_array, 0); + new_array [targets.Length] = target; + this.targets = new_array; + + // No need to update context, different targets cannot have + // different contexts, it's enough to remove same attributes + // from secondary members. + + target.OptAttributes = null; + } + + public ResolveContext CreateResolveContext () + { + return new ResolveContext (context, ResolveContext.Options.ConstantScope); + } + + static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name) + { + rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " + + "must be fields which are not readonly, static, const or read-write properties which are " + + "public and not static", + name.Name); + } + + static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name) + { + rc.Report.Error (655, name.Location, + "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type", + name.Name); + } + + public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc) + { + context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression"); + } + + public void Error_MissingGuidAttribute () + { + Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute"); + } + + public void Error_MisusedExtensionAttribute () + { + Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ()); + } + + public void Error_MisusedDynamicAttribute () + { + Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ()); + } + + /// + /// This is rather hack. We report many emit attribute error with same error to be compatible with + /// csc. But because csc has to report them this way because error came from ilasm we needn't. + /// + public void Error_AttributeEmitError (string inner) + { + Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'", + TypeManager.CSharpName (Type), inner); + } + + public void Error_InvalidSecurityParent () + { + Error_AttributeEmitError ("it is attached to invalid parent"); + } + + Attributable Owner { + get { + return targets [0]; + } + } + + /// + /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true. + /// + void ResolveAttributeType () + { + SessionReportPrinter resolve_printer = new SessionReportPrinter (); + ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer); + + bool t1_is_attr = false; + bool t2_is_attr = false; + TypeSpec t1, t2; + ATypeNameExpression expanded = null; + + // TODO: Additional warnings such as CS0436 are swallowed because we don't + // print on success + + try { + t1 = expression.ResolveAsType (context); + if (t1 != null) + t1_is_attr = t1.IsAttribute; + + resolve_printer.EndSession (); + + if (nameEscaped) { + t2 = null; + } else { + expanded = (ATypeNameExpression) expression.Clone (null); + expanded.Name += "Attribute"; + + t2 = expanded.ResolveAsType (context); + if (t2 != null) + t2_is_attr = t2.IsAttribute; + } + } finally { + context.Module.Compiler.Report.SetPrinter (prev_recorder); + } + + if (t1_is_attr && t2_is_attr && t1 != t2) { + Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'", + GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ()); + resolve_error = true; + return; + } + + if (t1_is_attr) { + Type = t1; + return; + } + + if (t2_is_attr) { + Type = t2; + return; + } + + resolve_error = true; + + if (t1 != null) { + resolve_printer.Merge (prev_recorder); + + Report.SymbolRelatedToPreviousError (t1); + Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ()); + return; + } + + if (t2 != null) { + Report.SymbolRelatedToPreviousError (t2); + Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ()); + return; + } + + resolve_printer.Merge (prev_recorder); + } + + public TypeSpec ResolveType () + { + if (Type == null && !resolve_error) + ResolveAttributeType (); + return Type; + } + + public override string GetSignatureForError () + { + if (Type != null) + return TypeManager.CSharpName (Type); + + return expression.GetSignatureForError (); + } + + public bool HasSecurityAttribute { + get { + PredefinedAttribute pa = context.Module.PredefinedAttributes.Security; + return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false); + } + } + + public bool IsValidSecurityAttribute () + { + return HasSecurityAttribute && IsSecurityActionValid (); + } + + static bool IsValidArgumentType (TypeSpec t) + { + if (t.IsArray) { + var ac = (ArrayContainer) t; + if (ac.Rank > 1) + return false; + + t = ac.Element; + } + + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + case BuiltinTypeSpec.Type.Type: + return true; + } + + return t.IsEnum; + } + + // TODO: Don't use this ambiguous value + public string Name { + get { return expression.Name; } + } + + public ATypeNameExpression TypeNameExpression { + get { + return expression; + } + } + + public Report Report { + get { return context.Module.Compiler.Report; } + } + + public MethodSpec Resolve () + { + if (resolve_error) + return null; + + resolve_error = true; + arg_resolved = true; + + if (Type == null) { + ResolveAttributeType (); + if (Type == null) + return null; + } + + if (Type.IsAbstract) { + Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ()); + return null; + } + + ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete (); + if (obsolete_attr != null) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report); + } + + ResolveContext rc = null; + + MethodSpec ctor; + // Try if the attribute is simple and has been resolved before + if (PosArguments != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) { + rc = CreateResolveContext (); + ctor = ResolveConstructor (rc); + if (ctor == null) { + return null; + } + + if (PosArguments == null && ctor.Parameters.IsEmpty) + context.Module.AttributeConstructorCache.Add (Type, ctor); + } + + // + // Add [module: DefaultCharSet] to all DllImport import attributes + // + var module = context.Module; + if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) { + if (rc == null) + rc = CreateResolveContext (); + + AddModuleCharSet (rc); + } + + if (NamedArguments != null) { + if (rc == null) + rc = CreateResolveContext (); + + if (!ResolveNamedArguments (rc)) + return null; + } + + resolve_error = false; + return ctor; + } + + MethodSpec ResolveConstructor (ResolveContext ec) + { + if (PosArguments != null) { + bool dynamic; + PosArguments.Resolve (ec, out dynamic); + if (dynamic) { + Error_AttributeArgumentIsDynamic (ec.MemberContext, loc); + return null; + } + } + + return ConstructorLookup (ec, Type, ref PosArguments, loc); + } + + bool ResolveNamedArguments (ResolveContext ec) + { + int named_arg_count = NamedArguments.Count; + var seen_names = new List (named_arg_count); + + named_values = new List> (named_arg_count); + + foreach (NamedArgument a in NamedArguments) { + string name = a.Name; + if (seen_names.Contains (name)) { + ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name); + continue; + } + + seen_names.Add (name); + + a.Resolve (ec); + + Expression member = Expression.MemberLookup (ec, false, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member == null) { + member = Expression.MemberLookup (ec, true, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member != null) { + // TODO: ec.Report.SymbolRelatedToPreviousError (member); + Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + return false; + } + } + + if (member == null){ + Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name); + return false; + } + + if (!(member is PropertyExpr || member is FieldExpr)) { + Error_InvalidNamedArgument (ec, a); + return false; + } + + ObsoleteAttribute obsolete_attr; + + if (member is PropertyExpr) { + var pi = ((PropertyExpr) member).PropertyInfo; + + if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) { + ec.Report.SymbolRelatedToPreviousError (pi); + Error_InvalidNamedArgument (ec, a); + return false; + } + + if (!IsValidArgumentType (member.Type)) { + ec.Report.SymbolRelatedToPreviousError (pi); + Error_InvalidNamedArgumentType (ec, a); + return false; + } + + obsolete_attr = pi.GetAttributeObsolete (); + pi.MemberDefinition.SetIsAssigned (); + } else { + var fi = ((FieldExpr) member).Spec; + + if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) { + Error_InvalidNamedArgument (ec, a); + return false; + } + + if (!IsValidArgumentType (member.Type)) { + ec.Report.SymbolRelatedToPreviousError (fi); + Error_InvalidNamedArgumentType (ec, a); + return false; + } + + obsolete_attr = fi.GetAttributeObsolete (); + fi.MemberDefinition.SetIsAssigned (); + } + + if (obsolete_attr != null && !context.IsObsolete) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report); + + if (a.Type != member.Type) { + a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location); + } + + if (a.Expr != null) + named_values.Add (new KeyValuePair ((MemberExpr) member, a)); + } + + return true; + } + + /// + /// Get a string containing a list of valid targets for the attribute 'attr' + /// + public string GetValidTargets () + { + StringBuilder sb = new StringBuilder (); + AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn; + + if ((targets & AttributeTargets.Assembly) != 0) + sb.Append ("assembly, "); + + if ((targets & AttributeTargets.Module) != 0) + sb.Append ("module, "); + + if ((targets & AttributeTargets.Class) != 0) + sb.Append ("class, "); + + if ((targets & AttributeTargets.Struct) != 0) + sb.Append ("struct, "); + + if ((targets & AttributeTargets.Enum) != 0) + sb.Append ("enum, "); + + if ((targets & AttributeTargets.Constructor) != 0) + sb.Append ("constructor, "); + + if ((targets & AttributeTargets.Method) != 0) + sb.Append ("method, "); + + if ((targets & AttributeTargets.Property) != 0) + sb.Append ("property, indexer, "); + + if ((targets & AttributeTargets.Field) != 0) + sb.Append ("field, "); + + if ((targets & AttributeTargets.Event) != 0) + sb.Append ("event, "); + + if ((targets & AttributeTargets.Interface) != 0) + sb.Append ("interface, "); + + if ((targets & AttributeTargets.Parameter) != 0) + sb.Append ("parameter, "); + + if ((targets & AttributeTargets.Delegate) != 0) + sb.Append ("delegate, "); + + if ((targets & AttributeTargets.ReturnValue) != 0) + sb.Append ("return, "); + + if ((targets & AttributeTargets.GenericParameter) != 0) + sb.Append ("type parameter, "); + + return sb.Remove (sb.Length - 2, 2).ToString (); + } + + public AttributeUsageAttribute GetAttributeUsageAttribute () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return DefaultUsageAttribute; + + AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ()); + + var field = GetNamedValue ("AllowMultiple") as BoolConstant; + if (field != null) + usage_attribute.AllowMultiple = field.Value; + + field = GetNamedValue ("Inherited") as BoolConstant; + if (field != null) + usage_attribute.Inherited = field.Value; + + return usage_attribute; + } + + /// + /// Returns custom name of indexer + /// + public string GetIndexerAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error || PosArguments.Count != 1 || !(PosArguments [0].Expr is Constant)) + return null; + + return ((Constant) PosArguments [0].Expr).GetValue () as string; + } + + /// + /// Returns condition of ConditionalAttribute + /// + public string GetConditionalAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return null; + + return ((Constant) PosArguments[0].Expr).GetValue () as string; + } + + /// + /// Creates the instance of ObsoleteAttribute from this attribute instance + /// + public ObsoleteAttribute GetObsoleteAttribute () + { + if (!arg_resolved) { + // corlib only case when obsolete is used before is resolved + var c = type.MemberDefinition as Class; + if (c != null && !c.HasMembersDefined) + c.Define (); + + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + } + + if (resolve_error) + return null; + + if (PosArguments == null) + return new ObsoleteAttribute (); + + string msg = ((Constant) PosArguments[0].Expr).GetValue () as string; + if (PosArguments.Count == 1) + return new ObsoleteAttribute (msg); + + return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value); + } + + /// + /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called + /// before ApplyAttribute. We need to resolve the arguments. + /// This situation occurs when class deps is differs from Emit order. + /// + public bool GetClsCompliantAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return false; + + return ((BoolConstant) PosArguments[0].Expr).Value; + } + + public TypeSpec GetCoClassAttributeValue () + { + if (!arg_resolved) + Resolve (); + + if (resolve_error) + return null; + + return GetArgumentType (); + } + + public bool CheckTarget () + { + string[] valid_targets = Owner.ValidAttributeTargets; + if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) { + Target = Owner.AttributeTargets; + return true; + } + + // TODO: we can skip the first item + if (Array.Exists (valid_targets, i => i == ExplicitTarget)) { + switch (ExplicitTarget) { + case "return": Target = AttributeTargets.ReturnValue; return true; + case "param": Target = AttributeTargets.Parameter; return true; + case "field": Target = AttributeTargets.Field; return true; + case "method": Target = AttributeTargets.Method; return true; + case "property": Target = AttributeTargets.Property; return true; + case "module": Target = AttributeTargets.Module; return true; + } + throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget); + } + + StringBuilder sb = new StringBuilder (); + foreach (string s in valid_targets) { + sb.Append (s); + sb.Append (", "); + } + sb.Remove (sb.Length - 2, 2); + Report.Warning (657, 1, Location, + "`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'. All attributes in this section will be ignored", + ExplicitTarget, sb.ToString ()); + return false; + } + + /// + /// Tests permitted SecurityAction for assembly or other types + /// + bool IsSecurityActionValid () + { + SecurityAction action = GetSecurityActionValue (); + bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module; + + switch (action) { +#pragma warning disable 618 + case SecurityAction.Demand: + case SecurityAction.Assert: + case SecurityAction.Deny: + case SecurityAction.PermitOnly: + case SecurityAction.LinkDemand: + case SecurityAction.InheritanceDemand: + if (!for_assembly) + return true; + break; + + case SecurityAction.RequestMinimum: + case SecurityAction.RequestOptional: + case SecurityAction.RequestRefuse: + if (for_assembly) + return true; + break; +#pragma warning restore 618 + + default: + Error_AttributeEmitError ("SecurityAction is out of range"); + return false; + } + + Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration")); + return false; + } + + System.Security.Permissions.SecurityAction GetSecurityActionValue () + { + return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue (); + } + + /// + /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table. + /// + /// + public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions) + { +#if STATIC + object[] values = new object [PosArguments.Count]; + for (int i = 0; i < values.Length; ++i) + values [i] = ((Constant) PosArguments [i].Expr).GetValue (); + + PropertyInfo[] prop; + object[] prop_values; + if (named_values == null) { + prop = null; + prop_values = null; + } else { + prop = new PropertyInfo[named_values.Count]; + prop_values = new object [named_values.Count]; + for (int i = 0; i < prop.Length; ++i) { + prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo; + prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue (); + } + } + + if (permissions == null) + permissions = new SecurityType (); + + var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values); + permissions.Add (cab); +#else + throw new NotSupportedException (); +#endif + } + + public Constant GetNamedValue (string name) + { + if (named_values == null) + return null; + + for (int i = 0; i < named_values.Count; ++i) { + if (named_values [i].Value.Name == name) + return named_values [i].Value.Expr as Constant; + } + + return null; + } + + public CharSet GetCharSetValue () + { + return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ()); + } + + public bool HasField (string fieldName) + { + if (named_values == null) + return false; + + foreach (var na in named_values) { + if (na.Value.Name == fieldName) + return true; + } + + return false; + } + + // + // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value + // + public bool IsInternalCall () + { + MethodImplOptions options = 0; + if (PosArguments.Count == 1) { + options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + } else if (HasField ("Value")) { + var named = GetNamedValue ("Value"); + options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ()); + } + + return (options & MethodImplOptions.InternalCall) != 0; + } + + // + // Returns true for StructLayoutAttribute with LayoutKind.Explicit value + // + public bool IsExplicitLayoutKind () + { + if (PosArguments == null || PosArguments.Count != 1) + return false; + + var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + return value == LayoutKind.Explicit; + } + + public Expression GetParameterDefaultValue () + { + if (PosArguments == null) + return null; + + return PosArguments[0].Expr; + } + + public override bool Equals (object obj) + { + Attribute a = obj as Attribute; + if (a == null) + return false; + + return Type == a.Type && Target == a.Target; + } + + public override int GetHashCode () + { + return type.GetHashCode () ^ Target.GetHashCode (); + } + + /// + /// Emit attribute for Attributable symbol + /// + public void Emit (Dictionary> allEmitted) + { + var ctor = Resolve (); + if (ctor == null) + return; + + var predefined = context.Module.PredefinedAttributes; + + AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage); + if ((usage_attr.ValidOn & Target) == 0) { + Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " + + "It is valid on `{1}' declarations only", + GetSignatureForError (), GetValidTargets ()); + return; + } + + byte[] cdata; + if (PosArguments == null && named_values == null) { + cdata = AttributeEncoder.Empty; + } else { + AttributeEncoder encoder = new AttributeEncoder (); + + if (PosArguments != null) { + var param_types = ctor.Parameters.Types; + for (int j = 0; j < PosArguments.Count; ++j) { + var pt = param_types[j]; + var arg_expr = PosArguments[j].Expr; + if (j == 0) { + if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) { + string v = ((Constant) arg_expr).GetValue () as string; + if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) { + context.Module.Compiler.Report.Error (633, arg_expr.Location, + "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ()); + return; + } + } else if (Type == predefined.Guid) { + try { + string v = ((StringConstant) arg_expr).Value; + new Guid (v); + } catch (Exception e) { + Error_AttributeEmitError (e.Message); + return; + } + } else if (Type == predefined.AttributeUsage) { + int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value; + if (v == 0) { + context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", + "System.AttributeUsage"); + } + } else if (Type == predefined.MarshalAs) { + if (PosArguments.Count == 1) { + var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) { + Error_AttributeEmitError ("Specified unmanaged type is only valid on fields"); + } + } + } else if (Type == predefined.DllImport) { + if (PosArguments.Count == 1 && PosArguments[0].Expr is Constant) { + var value = ((Constant) PosArguments[0].Expr).GetValue () as string; + if (string.IsNullOrEmpty (value)) + Error_AttributeEmitError ("DllName cannot be empty"); + } + } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short && + !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) { + Error_AttributeEmitError ("Incorrect argument value."); + return; + } + } + + arg_expr.EncodeAttributeValue (context, encoder, pt); + } + } + + if (named_values != null) { + encoder.Encode ((ushort) named_values.Count); + foreach (var na in named_values) { + if (na.Key is FieldExpr) + encoder.Encode ((byte) 0x53); + else + encoder.Encode ((byte) 0x54); + + encoder.Encode (na.Key.Type); + encoder.Encode (na.Value.Name); + na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type); + } + } else { + encoder.EncodeEmptyNamedArguments (); + } + + cdata = encoder.ToArray (); + } + + try { + foreach (Attributable target in targets) + target.ApplyAttributeBuilder (this, ctor, cdata, predefined); + } catch (Exception e) { + if (e is BadImageFormat && Report.Errors > 0) + return; + + Error_AttributeEmitError (e.Message); + return; + } + + if (!usage_attr.AllowMultiple && allEmitted != null) { + if (allEmitted.ContainsKey (this)) { + var a = allEmitted [this]; + if (a == null) { + a = new List (2); + allEmitted [this] = a; + } + a.Add (this); + } else { + allEmitted.Add (this, null); + } + } + + if (!context.Module.Compiler.Settings.VerifyClsCompliance) + return; + + // Here we are testing attribute arguments for array usage (error 3016) + if (Owner.IsClsComplianceRequired ()) { + if (PosArguments != null) + PosArguments.CheckArrayAsAttribute (context.Module.Compiler); + + if (NamedArguments == null) + return; + + NamedArguments.CheckArrayAsAttribute (context.Module.Compiler); + } + } + + private Expression GetValue () + { + if (PosArguments == null || PosArguments.Count < 1) + return null; + + return PosArguments [0].Expr; + } + + public string GetString () + { + Expression e = GetValue (); + if (e is StringConstant) + return ((StringConstant)e).Value; + return null; + } + + public bool GetBoolean () + { + Expression e = GetValue (); + if (e is BoolConstant) + return ((BoolConstant)e).Value; + return false; + } + + public TypeSpec GetArgumentType () + { + TypeOf e = GetValue () as TypeOf; + if (e == null) + return null; + return e.TypeArgument; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + throw new NotImplementedException (); + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + } + + public class Attributes + { + public readonly List Attrs; +#if FULL_AST + public readonly List> Sections = new List> (); +#endif + + public Attributes (Attribute a) + { + Attrs = new List (); + Attrs.Add (a); + +#if FULL_AST + Sections.Add (Attrs); +#endif + } + + public Attributes (List attrs) + { + Attrs = attrs; +#if FULL_AST + Sections.Add (attrs); +#endif + } + + public void AddAttribute (Attribute attr) + { + Attrs.Add (attr); + } + + public void AddAttributes (List attrs) + { +#if FULL_AST + Sections.Add (attrs); +#else + Attrs.AddRange (attrs); +#endif + } + + public void AttachTo (Attributable attributable, IMemberContext context) + { + foreach (Attribute a in Attrs) + a.AttachTo (attributable, context); + } + + public Attributes Clone () + { + var al = new List (Attrs.Count); + foreach (Attribute a in Attrs) + al.Add (a.Clone ()); + + return new Attributes (al); + } + + /// + /// Checks whether attribute target is valid for the current element + /// + public bool CheckTargets () + { + for (int i = 0; i < Attrs.Count; ++i) { + if (!Attrs [i].CheckTarget ()) + Attrs.RemoveAt (i--); + } + + return true; + } + + public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal) + { + var member_explicit_targets = member.ValidAttributeTargets; + for (int i = 0; i < Attrs.Count; ++i) { + var attr = Attrs[0]; + if (attr.ExplicitTarget == null) + continue; + + int ii; + for (ii = 0; ii < member_explicit_targets.Length; ++ii) { + if (attr.ExplicitTarget == member_explicit_targets[ii]) { + ii = -1; + break; + } + } + + if (ii < 0 || !isGlobal) + continue; + + member.Module.AddAttribute (attr, currentNamespace); + Attrs.RemoveAt (i); + --i; + } + } + + public Attribute Search (PredefinedAttribute t) + { + return Search (null, t); + } + + public Attribute Search (string explicitTarget, PredefinedAttribute t) + { + foreach (Attribute a in Attrs) { + if (explicitTarget != null && a.ExplicitTarget != explicitTarget) + continue; + + if (a.ResolveType () == t) + return a; + } + return null; + } + + /// + /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true + /// + public Attribute[] SearchMulti (PredefinedAttribute t) + { + List ar = null; + + foreach (Attribute a in Attrs) { + if (a.ResolveType () == t) { + if (ar == null) + ar = new List (Attrs.Count); + ar.Add (a); + } + } + + return ar == null ? null : ar.ToArray (); + } + + public void Emit () + { + CheckTargets (); + + Dictionary> ld = Attrs.Count > 1 ? new Dictionary> () : null; + + foreach (Attribute a in Attrs) + a.Emit (ld); + + if (ld == null || ld.Count == 0) + return; + + foreach (var d in ld) { + if (d.Value == null) + continue; + + Attribute a = d.Key; + + foreach (Attribute collision in d.Value) + a.Report.SymbolRelatedToPreviousError (collision.Location, ""); + + a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", + a.GetSignatureForError ()); + } + } + + public bool Contains (PredefinedAttribute t) + { + return Search (t) != null; + } + } + + public sealed class AttributeEncoder + { + [Flags] + public enum EncodedTypeProperties + { + None = 0, + DynamicType = 1, + TypeParameter = 1 << 1 + } + + public static readonly byte[] Empty; + + byte[] buffer; + int pos; + const ushort Version = 1; + + static AttributeEncoder () + { + Empty = new byte[4]; + Empty[0] = (byte) Version; + } + + public AttributeEncoder () + { + buffer = new byte[32]; + Encode (Version); + } + + public void Encode (bool value) + { + Encode (value ? (byte) 1 : (byte) 0); + } + + public void Encode (byte value) + { + if (pos == buffer.Length) + Grow (1); + + buffer [pos++] = value; + } + + public void Encode (sbyte value) + { + Encode ((byte) value); + } + + public void Encode (short value) + { + if (pos + 2 > buffer.Length) + Grow (2); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + } + + public void Encode (ushort value) + { + Encode ((short) value); + } + + public void Encode (int value) + { + if (pos + 4 > buffer.Length) + Grow (4); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + buffer[pos++] = (byte) (value >> 16); + buffer[pos++] = (byte) (value >> 24); + } + + public void Encode (uint value) + { + Encode ((int) value); + } + + public void Encode (long value) + { + if (pos + 8 > buffer.Length) + Grow (8); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + buffer[pos++] = (byte) (value >> 16); + buffer[pos++] = (byte) (value >> 24); + buffer[pos++] = (byte) (value >> 32); + buffer[pos++] = (byte) (value >> 40); + buffer[pos++] = (byte) (value >> 48); + buffer[pos++] = (byte) (value >> 56); + } + + public void Encode (ulong value) + { + Encode ((long) value); + } + + public void Encode (float value) + { + Encode (SingleConverter.SingleToInt32Bits (value)); + } + + public void Encode (double value) + { + Encode (BitConverter.DoubleToInt64Bits (value)); + } + + public void Encode (string value) + { + if (value == null) { + Encode ((byte) 0xFF); + return; + } + + var buf = Encoding.UTF8.GetBytes(value); + WriteCompressedValue (buf.Length); + + if (pos + buf.Length > buffer.Length) + Grow (buf.Length); + + Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length); + pos += buf.Length; + } + + public EncodedTypeProperties Encode (TypeSpec type) + { + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + Encode ((byte) 0x02); + break; + case BuiltinTypeSpec.Type.Char: + Encode ((byte) 0x03); + break; + case BuiltinTypeSpec.Type.SByte: + Encode ((byte) 0x04); + break; + case BuiltinTypeSpec.Type.Byte: + Encode ((byte) 0x05); + break; + case BuiltinTypeSpec.Type.Short: + Encode ((byte) 0x06); + break; + case BuiltinTypeSpec.Type.UShort: + Encode ((byte) 0x07); + break; + case BuiltinTypeSpec.Type.Int: + Encode ((byte) 0x08); + break; + case BuiltinTypeSpec.Type.UInt: + Encode ((byte) 0x09); + break; + case BuiltinTypeSpec.Type.Long: + Encode ((byte) 0x0A); + break; + case BuiltinTypeSpec.Type.ULong: + Encode ((byte) 0x0B); + break; + case BuiltinTypeSpec.Type.Float: + Encode ((byte) 0x0C); + break; + case BuiltinTypeSpec.Type.Double: + Encode ((byte) 0x0D); + break; + case BuiltinTypeSpec.Type.String: + Encode ((byte) 0x0E); + break; + case BuiltinTypeSpec.Type.Type: + Encode ((byte) 0x50); + break; + case BuiltinTypeSpec.Type.Object: + Encode ((byte) 0x51); + break; + case BuiltinTypeSpec.Type.Dynamic: + Encode ((byte) 0x51); + return EncodedTypeProperties.DynamicType; + default: + if (type.IsArray) { + Encode ((byte) 0x1D); + return Encode (TypeManager.GetElementType (type)); + } + + if (type.Kind == MemberKind.Enum) { + Encode ((byte) 0x55); + EncodeTypeName (type); + } + + break; + } + + return EncodedTypeProperties.None; + } + + public void EncodeTypeName (TypeSpec type) + { + var old_type = type.GetMetaInfo (); + Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName); + } + + // + // Encodes single property named argument per call + // + public void EncodeNamedPropertyArgument (PropertySpec property, Constant value) + { + Encode ((ushort) 1); // length + Encode ((byte) 0x54); // property + Encode (property.MemberType); + Encode (property.Name); + value.EncodeAttributeValue (null, this, property.MemberType); + } + + // + // Encodes single field named argument per call + // + public void EncodeNamedFieldArgument (FieldSpec field, Constant value) + { + Encode ((ushort) 1); // length + Encode ((byte) 0x53); // field + Encode (field.MemberType); + Encode (field.Name); + value.EncodeAttributeValue (null, this, field.MemberType); + } + + public void EncodeNamedArguments (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec + { + Encode ((ushort) members.Length); + + for (int i = 0; i < members.Length; ++i) + { + var member = members[i]; + + if (member.Kind == MemberKind.Field) + Encode ((byte) 0x53); + else if (member.Kind == MemberKind.Property) + Encode ((byte) 0x54); + else + throw new NotImplementedException (member.Kind.ToString ()); + + Encode (member.MemberType); + Encode (member.Name); + values [i].EncodeAttributeValue (null, this, member.MemberType); + } + } + + public void EncodeEmptyNamedArguments () + { + Encode ((ushort) 0); + } + + void Grow (int inc) + { + int size = System.Math.Max (pos * 4, pos + inc + 2); + Array.Resize (ref buffer, size); + } + + void WriteCompressedValue (int value) + { + if (value < 0x80) { + Encode ((byte) value); + return; + } + + if (value < 0x4000) { + Encode ((byte) (0x80 | (value >> 8))); + Encode ((byte) value); + return; + } + + Encode (value); + } + + public byte[] ToArray () + { + byte[] buf = new byte[pos]; + Array.Copy (buffer, buf, pos); + return buf; + } + } + + + /// + /// Helper class for attribute verification routine. + /// + static class AttributeTester + { + public enum Result { + Ok, + RefOutArrayError, + ArrayArrayError + } + + /// + /// Returns true if parameters of two compared methods are CLS-Compliant. + /// It tests differing only in ref or out, or in array rank. + /// + public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb) + { + TypeSpec [] types_a = pa.Types; + TypeSpec [] types_b = pb.Types; + if (types_a == null || types_b == null) + return Result.Ok; + + if (types_a.Length != types_b.Length) + return Result.Ok; + + Result result = Result.Ok; + for (int i = 0; i < types_b.Length; ++i) { + TypeSpec aType = types_a [i]; + TypeSpec bType = types_b [i]; + + var ac_a = aType as ArrayContainer; + var ac_b = aType as ArrayContainer; + + if (ac_a != null && ac_b != null) { + if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) { + result = Result.RefOutArrayError; + continue; + } + + if (ac_a.Element.IsArray || ac_b.Element.IsArray) { + result = Result.ArrayArrayError; + continue; + } + } + + if (aType != bType) + return Result.Ok; + + const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod)) + result = Result.RefOutArrayError; + } + return result; + } + + /// + /// Common method for Obsolete error/warning reporting. + /// + public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report) + { + if (oa.IsError) { + Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); + return; + } + + if (oa.Message == null || oa.Message.Length == 0) { + Report.Warning (612, 1, loc, "`{0}' is obsolete", member); + return; + } + Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); + } + } + + // + // Predefined attribute types + // + public class PredefinedAttributes + { + // Build-in attributes + public readonly PredefinedAttribute ParamArray; + public readonly PredefinedAttribute Out; + + // Optional attributes + public readonly PredefinedAttribute Obsolete; + public readonly PredefinedAttribute DllImport; + public readonly PredefinedAttribute MethodImpl; + public readonly PredefinedAttribute MarshalAs; + public readonly PredefinedAttribute In; + public readonly PredefinedAttribute IndexerName; + public readonly PredefinedAttribute Conditional; + public readonly PredefinedAttribute CLSCompliant; + public readonly PredefinedAttribute Security; + public readonly PredefinedAttribute Required; + public readonly PredefinedAttribute Guid; + public readonly PredefinedAttribute AssemblyCulture; + public readonly PredefinedAttribute AssemblyVersion; + public readonly PredefinedAttribute AssemblyAlgorithmId; + public readonly PredefinedAttribute AssemblyFlags; + public readonly PredefinedAttribute AssemblyFileVersion; + public readonly PredefinedAttribute ComImport; + public readonly PredefinedAttribute CoClass; + public readonly PredefinedAttribute AttributeUsage; + public readonly PredefinedAttribute DefaultParameterValue; + public readonly PredefinedAttribute OptionalParameter; + public readonly PredefinedAttribute UnverifiableCode; + public readonly PredefinedAttribute DefaultCharset; + public readonly PredefinedAttribute TypeForwarder; + public readonly PredefinedAttribute FixedBuffer; + public readonly PredefinedAttribute CompilerGenerated; + public readonly PredefinedAttribute InternalsVisibleTo; + public readonly PredefinedAttribute RuntimeCompatibility; + public readonly PredefinedAttribute DebuggerHidden; + public readonly PredefinedAttribute UnsafeValueType; + public readonly PredefinedAttribute UnmanagedFunctionPointer; + + // New in .NET 3.5 + public readonly PredefinedAttribute Extension; + + // New in .NET 4.0 + public readonly PredefinedDynamicAttribute Dynamic; + + // + // Optional types which are used as types and for member lookup + // + public readonly PredefinedAttribute DefaultMember; + public readonly PredefinedDecimalAttribute DecimalConstant; + public readonly PredefinedAttribute StructLayout; + public readonly PredefinedAttribute FieldOffset; + + public PredefinedAttributes (ModuleContainer module) + { + ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute"); + Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute"); + ParamArray.Resolve (); + Out.Resolve (); + + Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute"); + DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute"); + MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute"); + MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute"); + In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute"); + IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute"); + Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute"); + CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute"); + Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute"); + Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute"); + Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute"); + AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute"); + AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute"); + AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute"); + AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute"); + AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute"); + ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute"); + CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute"); + AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute"); + DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute"); + OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute"); + UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute"); + + DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute"); + TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute"); + FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute"); + CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"); + InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute"); + RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute"); + DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute"); + UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute"); + UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); + + Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute"); + + Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute"); + + DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute"); + DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute"); + StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute"); + FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute"); + + // TODO: Should define only attributes which are used for comparison + const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly; + + foreach (var fi in GetType ().GetFields (all_fields)) { + ((PredefinedAttribute) fi.GetValue (this)).Define (); + } + } + } + + public class PredefinedAttribute : PredefinedType + { + protected MethodSpec ctor; + + public PredefinedAttribute (ModuleContainer module, string ns, string name) + : base (module, MemberKind.Class, ns, name) + { + } + + #region Properties + + public MethodSpec Constructor { + get { + return ctor; + } + } + + #endregion + + public static bool operator == (TypeSpec type, PredefinedAttribute pa) + { + return type == pa.type && pa.type != null; + } + + public static bool operator != (TypeSpec type, PredefinedAttribute pa) + { + return type != pa.type; + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + + public override bool Equals (object obj) + { + throw new NotSupportedException (); + } + + public void EmitAttribute (ConstructorBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (MethodBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (PropertyBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (FieldBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + public void EmitAttribute (TypeBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + public void EmitAttribute (AssemblyBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ModuleBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ParameterBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + ConstructorInfo GetCtorMetaInfo () + { + return (ConstructorInfo) ctor.GetMetaInfo (); + } + + public bool ResolveBuilder () + { + if (ctor != null) + return true; + + // + // Handle all parameter-less attributes as optional + // + if (!IsDefined) + return false; + + ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly); + return ctor != null; + } + } + + public class PredefinedDecimalAttribute : PredefinedAttribute + { + public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name) + : base (module, ns, name) + { + } + + public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc) + { + var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc); + if (ctor == null) + return; + + int[] bits = decimal.GetBits (value); + AttributeEncoder encoder = new AttributeEncoder (); + encoder.Encode ((byte) (bits[3] >> 16)); + encoder.Encode ((byte) (bits[3] >> 31)); + encoder.Encode ((uint) bits[2]); + encoder.Encode ((uint) bits[1]); + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + + public void EmitAttribute (FieldBuilder builder, decimal value, Location loc) + { + var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc); + if (ctor == null) + return; + + int[] bits = decimal.GetBits (value); + AttributeEncoder encoder = new AttributeEncoder (); + encoder.Encode ((byte) (bits[3] >> 16)); + encoder.Encode ((byte) (bits[3] >> 31)); + encoder.Encode ((uint) bits[2]); + encoder.Encode ((uint) bits[1]); + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + } + + public class PredefinedDynamicAttribute : PredefinedAttribute + { + MethodSpec tctor; + + public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name) + : base (module, ns, name) + { + } + + public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + // + // When any element of the type is a dynamic type + // + // This method builds a transformation array for dynamic types + // used in places where DynamicAttribute cannot be applied to. + // It uses bool flag when type is of dynamic type and each + // section always starts with "false" for some reason. + // + // LAMESPEC: This should be part of C# specification + // + // Example: Func + // Transformation: { false, true, false, false, true } + // + static bool[] GetTransformationFlags (TypeSpec t) + { + bool[] element; + var ac = t as ArrayContainer; + if (ac != null) { + element = GetTransformationFlags (ac.Element); + if (element == null) + return null; + + bool[] res = new bool[element.Length + 1]; + res[0] = false; + Array.Copy (element, 0, res, 1, element.Length); + return res; + } + + if (t == null) + return null; + + if (t.IsGeneric) { + List transform = null; + var targs = t.TypeArguments; + for (int i = 0; i < targs.Length; ++i) { + element = GetTransformationFlags (targs[i]); + if (element != null) { + if (transform == null) { + transform = new List (); + for (int ii = 0; ii <= i; ++ii) + transform.Add (false); + } + + transform.AddRange (element); + } else if (transform != null) { + transform.Add (false); + } + } + + if (transform != null) + return transform.ToArray (); + } + + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return new bool[] { true }; + + return null; + } + + bool ResolveTransformationCtor (Location loc) + { + if (tctor != null) + return true; + + tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc); + return tctor != null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs new file mode 100644 index 0000000000..1659dfe3a6 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs @@ -0,0 +1,1173 @@ +// +// cfold.cs: Constant Folding +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2002, 2003 Ximian, Inc. +// Copyright 2003-2008, Novell, Inc. +// +using System; + +namespace Mono.CSharp { + + public static class ConstantFold + { + public static TypeSpec[] CreateBinaryPromotionsTypes (BuiltinTypes types) + { + return new TypeSpec[] { + types.Decimal, types.Double, types.Float, + types.ULong, types.Long, types.UInt + }; + } + + // + // Performs the numeric promotions on the left and right expresions + // and deposits the results on `lc' and `rc'. + // + // On success, the types of `lc' and `rc' on output will always match, + // and the pair will be one of: + // + // TODO: BinaryFold should be called as an optimization step only, + // error checking here is weak + // + static bool DoBinaryNumericPromotions (ResolveContext rc, ref Constant left, ref Constant right) + { + TypeSpec ltype = left.Type; + TypeSpec rtype = right.Type; + + foreach (TypeSpec t in rc.BuiltinTypes.BinaryPromotionsTypes) { + if (t == ltype) + return t == rtype || ConvertPromotion (rc, ref right, ref left, t); + + if (t == rtype) + return t == ltype || ConvertPromotion (rc, ref left, ref right, t); + } + + left = left.ConvertImplicitly (rc.BuiltinTypes.Int); + right = right.ConvertImplicitly (rc.BuiltinTypes.Int); + return left != null && right != null; + } + + static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, TypeSpec type) + { + Constant c = prim.ConvertImplicitly (type); + if (c != null) { + prim = c; + return true; + } + + if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) { + type = rc.BuiltinTypes.Long; + prim = prim.ConvertImplicitly (type); + second = second.ConvertImplicitly (type); + return prim != null && second != null; + } + + return false; + } + + internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc) + { + rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode"); + } + + /// + /// Constant expression folder for binary operations. + /// + /// Returns null if the expression can not be folded. + /// + static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper, + Constant left, Constant right, Location loc) + { + Constant result = null; + + if (left is EmptyConstantCast) + return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc); + + if (left is SideEffectConstant) { + result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc); + if (result == null) + return null; + return new SideEffectConstant (result, left, loc); + } + + if (right is EmptyConstantCast) + return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc); + + if (right is SideEffectConstant) { + result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc); + if (result == null) + return null; + return new SideEffectConstant (result, right, loc); + } + + TypeSpec lt = left.Type; + TypeSpec rt = right.Type; + bool bool_res; + + if (lt.BuiltinType == BuiltinTypeSpec.Type.Bool && lt == rt) { + bool lv = (bool) left.GetValue (); + bool rv = (bool) right.GetValue (); + switch (oper) { + case Binary.Operator.BitwiseAnd: + case Binary.Operator.LogicalAnd: + return new BoolConstant (ec.BuiltinTypes, lv && rv, left.Location); + case Binary.Operator.BitwiseOr: + case Binary.Operator.LogicalOr: + return new BoolConstant (ec.BuiltinTypes, lv || rv, left.Location); + case Binary.Operator.ExclusiveOr: + return new BoolConstant (ec.BuiltinTypes, lv ^ rv, left.Location); + case Binary.Operator.Equality: + return new BoolConstant (ec.BuiltinTypes, lv == rv, left.Location); + case Binary.Operator.Inequality: + return new BoolConstant (ec.BuiltinTypes, lv != rv, left.Location); + } + return null; + } + + // + // During an enum evaluation, none of the rules are valid + // Not sure whether it is bug in csc or in documentation + // + if (ec.HasSet (ResolveContext.Options.EnumScope)){ + if (left is EnumConstant) + left = ((EnumConstant) left).Child; + + if (right is EnumConstant) + right = ((EnumConstant) right).Child; + } else if (left is EnumConstant && rt == lt) { + switch (oper){ + /// + /// E operator |(E x, E y); + /// E operator &(E x, E y); + /// E operator ^(E x, E y); + /// + case Binary.Operator.BitwiseOr: + case Binary.Operator.BitwiseAnd: + case Binary.Operator.ExclusiveOr: + result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + if (result != null) + result = result.TryReduce (ec, lt, loc); + return result; + + /// + /// U operator -(E x, E y); + /// + case Binary.Operator.Subtraction: + result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + if (result != null) + result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt), loc); + return result; + + /// + /// bool operator ==(E x, E y); + /// bool operator !=(E x, E y); + /// bool operator <(E x, E y); + /// bool operator >(E x, E y); + /// bool operator <=(E x, E y); + /// bool operator >=(E x, E y); + /// + case Binary.Operator.Equality: + case Binary.Operator.Inequality: + case Binary.Operator.LessThan: + case Binary.Operator.GreaterThan: + case Binary.Operator.LessThanOrEqual: + case Binary.Operator.GreaterThanOrEqual: + return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + } + return null; + } + + switch (oper){ + case Binary.Operator.BitwiseOr: + // + // bool? operator &(bool? x, bool? y); + // + if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || + (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { + var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + // false | null => null + // null | false => null + if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) + return Nullable.LiftedNull.CreateFromExpression (ec, b); + + // true | null => true + // null | true => true + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, true, loc), b); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + if (left is IntConstant){ + int res = ((IntConstant) left).Value | ((IntConstant) right).Value; + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value; + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value | ((LongConstant)right).Value; + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value | + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.BitwiseAnd: + // + // bool? operator &(bool? x, bool? y); + // + if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || + (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { + var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + // false & null => false + // null & false => false + if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, false, loc), b); + + // true & null => null + // null & true => null + return Nullable.LiftedNull.CreateFromExpression (ec, b); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + /// + /// int operator &(int x, int y); + /// uint operator &(uint x, uint y); + /// long operator &(long x, long y); + /// ulong operator &(ulong x, ulong y); + /// + if (left is IntConstant){ + int res = ((IntConstant) left).Value & ((IntConstant) right).Value; + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value; + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value & ((LongConstant)right).Value; + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value & + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.ExclusiveOr: + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + if (left is IntConstant){ + int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value; + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value; + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value; + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value ^ + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.Addition: + if (lt == InternalType.NullLiteral) + return right; + + if (rt == InternalType.NullLiteral) + return left; + + // + // If both sides are strings, then concatenate, if + // one is a string, and the other is not, then defer + // to runtime concatenation + // + if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){ + if (lt == rt) + return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (), + left.Location); + + return null; + } + + // + // handle "E operator + (E x, U y)" + // handle "E operator + (Y y, E x)" + // + EnumConstant lc = left as EnumConstant; + EnumConstant rc = right as EnumConstant; + if (lc != null || rc != null){ + if (lc == null) { + lc = rc; + lt = lc.Type; + right = left; + } + + // U has to be implicitly convetible to E.base + right = right.ConvertImplicitly (lc.Child.Type); + if (right == null) + return null; + + result = BinaryFold (ec, oper, lc.Child, right, loc); + if (result == null) + return null; + + result = result.TryReduce (ec, lt, loc); + if (result == null) + return null; + + return new EnumConstant (result, lt); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value + + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value + + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value + + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value + + ((FloatConstant) right).Value); + + result = new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value + + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value + + ((ULongConstant) right).Value); + + result = new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value + + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value + + ((LongConstant) right).Value); + + result = new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value + + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value + + ((UIntConstant) right).Value); + + result = new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value + + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value + + ((IntConstant) right).Value); + + result = new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value + + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value + + ((DecimalConstant) right).Value); + + result = new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + + return result; + + case Binary.Operator.Subtraction: + // + // handle "E operator - (E x, U y)" + // handle "E operator - (Y y, E x)" + // + lc = left as EnumConstant; + rc = right as EnumConstant; + if (lc != null || rc != null){ + if (lc == null) { + lc = rc; + lt = lc.Type; + right = left; + } + + // U has to be implicitly convetible to E.base + right = right.ConvertImplicitly (lc.Child.Type); + if (right == null) + return null; + + result = BinaryFold (ec, oper, lc.Child, right, loc); + if (result == null) + return null; + + result = result.TryReduce (ec, lt, loc); + if (result == null) + return null; + + return new EnumConstant (result, lt); + } + + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value - + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value - + ((DoubleConstant) right).Value); + + result = new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value - + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value - + ((FloatConstant) right).Value); + + result = new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value - + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value - + ((ULongConstant) right).Value); + + result = new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value - + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value - + ((LongConstant) right).Value); + + result = new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value - + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value - + ((UIntConstant) right).Value); + + result = new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value - + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value - + ((IntConstant) right).Value); + + result = new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value - + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value - + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected subtraction input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + + return result; + + case Binary.Operator.Multiply: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value * + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value * + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value * + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value * + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value * + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value * + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value * + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value * + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value * + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value * + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value * + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value * + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value * + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value * + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected multiply input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + break; + + case Binary.Operator.Division: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value / + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value / + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value / + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value / + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value / + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value / + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value / + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value / + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value / + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value / + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value / + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value / + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value / + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value / + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected division input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + + } catch (DivideByZeroException) { + ec.Report.Error (20, loc, "Division by constant zero"); + } + + break; + + case Binary.Operator.Modulus: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value % + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value % + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value % + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value % + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value % + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value % + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value % + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value % + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value % + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value % + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value % + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value % + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected modulus input: " + left); + } + } catch (DivideByZeroException){ + ec.Report.Error (20, loc, "Division by constant zero"); + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + break; + + // + // There is no overflow checking on left shift + // + case Binary.Operator.LeftShift: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; + if (ic == null){ + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + return null; + } + + int lshift_val = ic.Value; + switch (left.Type.BuiltinType) { + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location); + } + + // null << value => null + if (left is NullLiteral) + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + left = left.ConvertImplicitly (ec.BuiltinTypes.Int); + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location); + + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + break; + + // + // There is no overflow checking on right shift + // + case Binary.Operator.RightShift: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; + if (sic == null){ + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ; + return null; + } + int rshift_val = sic.Value; + switch (left.Type.BuiltinType) { + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location); + } + + // null >> value => null + if (left is NullLiteral) + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + left = left.ConvertImplicitly (ec.BuiltinTypes.Int); + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location); + + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + break; + + case Binary.Operator.Equality: + if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || + (left is Nullable.LiftedNull && right.IsNull) || + (right is Nullable.LiftedNull && left.IsNull)) { + if (left.IsNull || right.IsNull) { + return ReducedExpression.Create ( + new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location), + new Binary (oper, left, right, loc)); + } + + if (left is StringConstant && right is StringConstant) + return new BoolConstant (ec.BuiltinTypes, + ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location); + + return null; + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value == + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value == + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value == + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value == + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value == + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value == + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.Inequality: + if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || + (left is Nullable.LiftedNull && right.IsNull) || + (right is Nullable.LiftedNull && left.IsNull)) { + if (left.IsNull || right.IsNull) { + return ReducedExpression.Create ( + new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location), + new Binary (oper, left, right, loc)); + } + + if (left is StringConstant && right is StringConstant) + return new BoolConstant (ec.BuiltinTypes, + ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location); + + return null; + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value != + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value != + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value != + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value != + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value != + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value != + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.LessThan: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value < + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value < + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value < + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value < + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value < + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value < + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.GreaterThan: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value > + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value > + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value > + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value > + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value > + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value > + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.GreaterThanOrEqual: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value >= + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value >= + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value >= + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value >= + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value >= + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value >= + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.LessThanOrEqual: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value <= + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value <= + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value <= + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value <= + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value <= + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value <= + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + } + + return null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs new file mode 100644 index 0000000000..83fbea0b38 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs @@ -0,0 +1,3622 @@ +// +// class.cs: Class and Struct handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Linq; + +#if NET_2_1 +using XmlElement = System.Object; +#endif + +#if STATIC +using SecurityType = System.Collections.Generic.List; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + + public interface ITypesContainer + { + Location Location { get; } + MemberName MemberName { get; } + } + + /// + /// This is the base class for structs and classes. + /// + public abstract class TypeContainer : DeclSpace, ITypeDefinition, ITypesContainer + { + // + // Different context is needed when resolving type container base + // types. Type names come from the parent scope but type parameter + // names from the container scope. + // + public struct BaseContext : IMemberContext + { + TypeContainer tc; + + public BaseContext (TypeContainer tc) + { + this.tc = tc; + } + + #region IMemberContext Members + + public CompilerContext Compiler { + get { return tc.Compiler; } + } + + public TypeSpec CurrentType { + get { return tc.Parent.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return tc.PartialContainer.CurrentTypeParameters; } + } + + public MemberCore CurrentMemberDefinition { + get { return tc; } + } + + public bool IsObsolete { + get { return tc.IsObsolete; } + } + + public bool IsUnsafe { + get { return tc.IsUnsafe; } + } + + public bool IsStatic { + get { return tc.IsStatic; } + } + + public ModuleContainer Module { + get { return tc.Module; } + } + + public string GetSignatureForError () + { + return tc.GetSignatureForError (); + } + + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return null; + } + + public FullNamedExpression LookupNamespaceAlias (string name) + { + return tc.Parent.LookupNamespaceAlias (name); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter t = TypeParameter.FindTypeParameter (tp, name); + if (t != null) + return new TypeParameterExpr (t, loc); + } + } + + return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc); + } + + #endregion + } + + [Flags] + enum CachedMethods + { + Equals = 1, + GetHashCode = 1 << 1, + HasStaticFieldInitializer = 1 << 2 + } + + + // Whether this is a struct, class or interface + public readonly MemberKind Kind; + + // Holds a list of classes and structures + protected List types; + + List ordered_explicit_member_list; + List ordered_member_list; + + // Holds the list of properties + List properties; + + // Holds the list of constructors + protected List instance_constructors; + + // Holds the list of fields + protected List fields; + + // Holds a list of fields that have initializers + protected List initialized_fields; + + // Holds a list of static fields that have initializers + protected List initialized_static_fields; + + // Holds the list of constants + protected List constants; + + // Holds the methods. + List methods; + + // Holds the events + protected List events; + + // Holds the indexers + List indexers; + + // Holds the operators + List operators; + + // Holds the compiler generated classes + protected List compiler_generated; + + Dictionary hoisted_base_call_proxies; + + Dictionary Cache = new Dictionary (); + + // + // Pointers to the default constructor and the default static constructor + // + protected Constructor default_constructor; + protected Constructor default_static_constructor; + + // + // Points to the first non-static field added to the container. + // + // This is an arbitrary choice. We are interested in looking at _some_ non-static field, + // and the first one's as good as any. + // + FieldBase first_nonstatic_field; + + // + // This one is computed after we can distinguish interfaces + // from classes from the arraylist `type_bases' + // + protected TypeSpec base_type; + protected FullNamedExpression base_type_expr; // TODO: It's temporary variable + protected TypeSpec[] iface_exprs; + + protected List type_bases; + + bool members_defined; + bool members_defined_ok; + bool type_defined; + + TypeContainer InTransit; + + GenericTypeParameterBuilder[] all_tp_builders; + + public const string DefaultIndexerName = "Item"; + + private bool seen_normal_indexers = false; + private string indexer_name = DefaultIndexerName; + protected bool requires_delayed_unmanagedtype_check; + bool error; + + private CachedMethods cached_method; + + protected TypeSpec spec; + TypeSpec current_type; + + List partial_parts; + + public int DynamicSitesCounter; + + /// + /// The pending methods that need to be implemented + // (interfaces or abstract methods) + /// + PendingImplementation pending; + + public TypeContainer (NamespaceContainer ns, DeclSpace parent, MemberName name, + Attributes attrs, MemberKind kind) + : base (ns, parent, name, attrs) + { + if (parent != null && parent.NamespaceEntry != ns) + throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class"); + + this.Kind = kind; + this.PartialContainer = this; + } + + List orderedAllMembers = new List (); + public List OrderedAllMembers { + get { + return this.orderedAllMembers; + } + } + + #region Properties + + public override TypeSpec CurrentType { + get { + if (current_type == null) { + if (IsGeneric) { + // + // Switch to inflated version as it's used by all expressions + // + var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Select (l => l.Type).ToArray (); + current_type = spec.MakeGenericType (this, targs); + } else { + current_type = spec; + } + } + + return current_type; + } + } + + public override TypeParameter[] CurrentTypeParameters { + get { + return PartialContainer.type_params; + } + } + + int CurrentTypeParametersStartIndex { + get { + int total = all_tp_builders.Length; + if (CurrentTypeParameters != null) { + return total - CurrentTypeParameters.Length; + } + return total; + } + } + + public virtual AssemblyDefinition DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + public TypeSpec Definition { + get { + return spec; + } + } + + public bool HasMembersDefined { + get { + return members_defined; + } + } + + public List TypeBaseExpressions { + get { + return type_bases; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public bool AddMember (MemberCore symbol) + { + return AddToContainer (symbol, symbol.MemberName.Basename); + } + + public bool AddMember (MemberCore symbol, string name) + { + return AddToContainer (symbol, name); + } + + protected virtual bool AddMemberType (TypeContainer ds) + { + return AddToContainer (ds, ds.Basename); + } + + protected virtual void RemoveMemberType (TypeContainer ds) + { + RemoveFromContainer (ds.Basename); + } + + public void AddConstant (Const constant) + { + orderedAllMembers.Add (constant); + if (!AddMember (constant)) + return; + + if (constants == null) + constants = new List (); + constants.Add (constant); + } + + public TypeContainer AddTypeContainer (TypeContainer tc) + { + orderedAllMembers.Add (tc); + if (!AddMemberType (tc)) + return tc; + + if (types == null) + types = new List (); + + types.Add (tc); + return tc; + } + + public virtual TypeContainer AddPartial (TypeContainer next_part) + { + return AddPartial (next_part, next_part.Basename); + } + + protected TypeContainer AddPartial (TypeContainer next_part, string name) + { + next_part.ModFlags |= Modifiers.PARTIAL; + TypeContainer tc = GetDefinition (name) as TypeContainer; + if (tc == null) + return AddTypeContainer (next_part); + + if ((tc.ModFlags & Modifiers.PARTIAL) == 0) { + Report.SymbolRelatedToPreviousError (next_part); + Error_MissingPartialModifier (tc); + } + + if (tc.Kind != next_part.Kind) { + Report.SymbolRelatedToPreviousError (tc); + Report.Error (261, next_part.Location, + "Partial declarations of `{0}' must be all classes, all structs or all interfaces", + next_part.GetSignatureForError ()); + } + + if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) && + ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 && + (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) { + Report.SymbolRelatedToPreviousError (tc); + Report.Error (262, next_part.Location, + "Partial declarations of `{0}' have conflicting accessibility modifiers", + next_part.GetSignatureForError ()); + } + + if (tc.partial_parts == null) + tc.partial_parts = new List (1); + + if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) { + tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask); + } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) { + tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask); + tc.ModFlags |= next_part.ModFlags; + } else { + tc.ModFlags |= next_part.ModFlags; + } + + tc.spec.Modifiers = tc.ModFlags; + + if (next_part.attributes != null) { + if (tc.attributes == null) + tc.attributes = next_part.attributes; + else + tc.attributes.AddAttributes (next_part.attributes.Attrs); + } + + next_part.PartialContainer = tc; + tc.partial_parts.Add (next_part); + return tc; + } + + public virtual void RemoveTypeContainer (TypeContainer next_part) + { + if (types != null) + types.Remove (next_part); + + Cache.Remove (next_part.Basename); + RemoveMemberType (next_part); + } + + public void AddDelegate (Delegate d) + { + AddTypeContainer (d); + } + + private void AddMemberToList (MemberCore mc, List alist, bool isexplicit) + { + if (ordered_explicit_member_list == null) { + ordered_explicit_member_list = new List (); + ordered_member_list = new List (); + } + + if (isexplicit) { + if (Kind == MemberKind.Interface) { + Report.Error (541, mc.Location, + "`{0}': explicit interface declaration can only be declared in a class or struct", + mc.GetSignatureForError ()); + } + + ordered_explicit_member_list.Add (mc); + alist.Insert (0, mc); + } else { + ordered_member_list.Add (mc); + alist.Add (mc); + } + + } + + public void AddMethod (MethodOrOperator method) + { + orderedAllMembers.Add (method); + if (!AddToContainer (method, method.MemberName.Basename)) + return; + + if (methods == null) + methods = new List (); + + if (method.MemberName.Left != null) + AddMemberToList (method, methods, true); + else + AddMemberToList (method, methods, false); + } + + public void AddConstructor (Constructor c) + { + orderedAllMembers.Add (c); + bool is_static = (c.ModFlags & Modifiers.STATIC) != 0; + if (!AddToContainer (c, is_static ? Constructor.ConstructorName : Constructor.TypeConstructorName)) + return; + + if (is_static && c.ParameterInfo.IsEmpty){ + if (default_static_constructor != null) { + Report.SymbolRelatedToPreviousError (default_static_constructor); + Report.Error (111, c.Location, + "A member `{0}' is already defined. Rename this member or use different parameter types", + c.GetSignatureForError ()); + return; + } + + default_static_constructor = c; + } else { + if (c.ParameterInfo.IsEmpty) + default_constructor = c; + if (instance_constructors == null) + instance_constructors = new List (); + + instance_constructors.Add (c); + } + } + + public bool AddField (FieldBase field) + { + orderedAllMembers.Add (field); + if (!AddMember (field)) + return false; + if (fields == null) + fields = new List (); + + fields.Add (field); + + if ((field.ModFlags & Modifiers.STATIC) != 0) + return true; + + if (first_nonstatic_field == null) { + first_nonstatic_field = field; + return true; + } + + if (Kind == MemberKind.Struct && first_nonstatic_field.Parent != field.Parent) { + Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent); + Report.Warning (282, 3, field.Location, + "struct instance field `{0}' found in different declaration from instance field `{1}'", + field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ()); + } + return true; + } + + public void AddProperty (Property prop) + { + orderedAllMembers.Add (prop); + if (!AddMember (prop)) + return; + if (properties == null) + properties = new List (); + + if (prop.MemberName.Left != null) + AddMemberToList (prop, properties, true); + else + AddMemberToList (prop, properties, false); + } + + public void AddEvent (Event e) + { + orderedAllMembers.Add (e); + if (!AddMember (e)) + return; + if (events == null) + events = new List (); + + events.Add (e); + } + + /// + /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute + /// + public void AddIndexer (Indexer i) + { + orderedAllMembers.Add (i); + if (indexers == null) + indexers = new List (); + if (i.IsExplicitImpl) + AddMemberToList (i, indexers, true); + else + AddMemberToList (i, indexers, false); + } + + public void AddOperator (Operator op) + { + orderedAllMembers.Add (op); + if (!AddMember (op)) + return; + if (operators == null) + operators = new List (); + + operators.Add (op); + } + + public void AddCompilerGeneratedClass (CompilerGeneratedClass c) + { + if (compiler_generated == null) + compiler_generated = new List (); + + compiler_generated.Add (c); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.DefaultMember) { + if (Indexers != null) { + Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer"); + return; + } + } + + if (a.Type == pa.Required) { + Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types"); + return; + } + + TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override AttributeTargets AttributeTargets { + get { + throw new NotSupportedException (); + } + } + + public IList Types { + get { + return types; + } + } + + public IList Methods { + get { + return methods; + } + } + + public IList Constants { + get { + return constants; + } + } + + public TypeSpec BaseType { + get { + return spec.BaseType; + } + } + + public IList Fields { + get { + return fields; + } + } + + public IList InstanceConstructors { + get { + return instance_constructors; + } + } + + public IList Properties { + get { + return properties; + } + } + + public IList Events { + get { + return events; + } + } + + public IList Indexers { + get { + return indexers; + } + } + + public IList Operators { + get { + return operators; + } + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel); + } + } + + public int TypeParametersCount { + get { + return MemberName.Arity; + } + } + + TypeParameterSpec[] ITypeDefinition.TypeParameters { + get { + // TODO MemberCache: this is going to hurt + return PartialContainer.type_params.Select (l => l.Type).ToArray (); + } + } + + public string GetAttributeDefaultMember () + { + return indexers == null ? DefaultIndexerName : indexer_name; + } + + public bool IsComImport { + get { + if (OptAttributes == null) + return false; + + return OptAttributes.Contains (Module.PredefinedAttributes.ComImport); + } + } + + string ITypeDefinition.Namespace { + get { + return NamespaceEntry.NS.MemberName.GetSignatureForError (); + } + } + + public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) + { + if ((field.ModFlags & Modifiers.STATIC) != 0){ + if (initialized_static_fields == null) { + PartialContainer.HasStaticFieldInitializer = true; + initialized_static_fields = new List (4); + } + + initialized_static_fields.Add (expression); + } else { + if (initialized_fields == null) + initialized_fields = new List (4); + + initialized_fields.Add (expression); + } + } + + public void ResolveFieldInitializers (BlockContext ec) + { + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) { + part.DoResolveFieldInitializers (ec); + } + } + DoResolveFieldInitializers (ec); + } + + void DoResolveFieldInitializers (BlockContext ec) + { + if (ec.IsStatic) { + if (initialized_static_fields == null) + return; + + bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize; + int i; + ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count]; + for (i = 0; i < initialized_static_fields.Count; ++i) { + FieldInitializer fi = initialized_static_fields [i]; + ExpressionStatement s = fi.ResolveStatement (ec); + if (s == null) { + s = EmptyExpressionStatement.Instance; + } else if (fi.IsComplexInitializer) { + has_complex_initializer |= true; + } + + init [i] = s; + } + + for (i = 0; i < initialized_static_fields.Count; ++i) { + FieldInitializer fi = initialized_static_fields [i]; + // + // Need special check to not optimize code like this + // static int a = b = 5; + // static int b = 0; + // + if (!has_complex_initializer && fi.IsDefaultInitializer) + continue; + + ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i])); + } + + return; + } + + if (initialized_fields == null) + return; + + for (int i = 0; i < initialized_fields.Count; ++i) { + FieldInitializer fi = initialized_fields [i]; + ExpressionStatement s = fi.ResolveStatement (ec); + if (s == null) + continue; + + // + // Field is re-initialized to its default value => removed + // + if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize) + continue; + + ec.CurrentBlock.AddScopeStatement (new StatementExpression (s)); + } + } + + public override string DocComment { + get { + return comment; + } + set { + if (value == null) + return; + + comment += value; + } + } + + public PendingImplementation PendingImplementations { + get { return pending; } + } + + internal override void GenerateDocComment (DocumentationBuilder builder) + { + base.GenerateDocComment (builder); + + if (DefaultStaticConstructor != null) + DefaultStaticConstructor.GenerateDocComment (builder); + + if (InstanceConstructors != null) + foreach (Constructor c in InstanceConstructors) + c.GenerateDocComment (builder); + + if (Types != null) + foreach (TypeContainer tc in Types) + tc.GenerateDocComment (builder); + + if (Constants != null) + foreach (Const c in Constants) + c.GenerateDocComment (builder); + + if (Fields != null) + foreach (FieldBase f in Fields) + f.GenerateDocComment (builder); + + if (Events != null) + foreach (Event e in Events) + e.GenerateDocComment (builder); + + if (Indexers != null) + foreach (Indexer ix in Indexers) + ix.GenerateDocComment (builder); + + if (Properties != null) + foreach (Property p in Properties) + p.GenerateDocComment (builder); + + if (Methods != null) + foreach (MethodOrOperator m in Methods) + m.GenerateDocComment (builder); + + if (Operators != null) + foreach (Operator o in Operators) + o.GenerateDocComment (builder); + } + + public TypeSpec GetAttributeCoClass () + { + if (OptAttributes == null) + return null; + + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass); + if (a == null) + return null; + + return a.GetCoClassAttributeValue (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + Attribute a = null; + if (OptAttributes != null) { + a = OptAttributes.Search (pa); + } + + if (a == null) + return null; + + return a.GetAttributeUsageAttribute (); + } + + public virtual void AddBasesForPart (DeclSpace part, List bases) + { + // FIXME: get rid of partial_parts and store lists of bases of each part here + // assumed, not verified: 'part' is in 'partial_parts' + ((TypeContainer) part).type_bases = bases; + } + + /// + /// This function computes the Base class and also the + /// list of interfaces that the class or struct @c implements. + /// + /// The return value is an array (might be null) of + /// interfaces implemented (as Types). + /// + /// The @base_class argument is set to the base object or null + /// if this is `System.Object'. + /// + protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_class = null; + if (type_bases == null) + return null; + + int count = type_bases.Count; + TypeSpec[] ifaces = null; + var base_context = new BaseContext (this); + for (int i = 0, j = 0; i < count; i++){ + FullNamedExpression fne = type_bases [i]; + + var fne_resolved = fne.ResolveAsType (base_context); + if (fne_resolved == null) + continue; + + if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) { + if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type", + GetSignatureForError ()); + + continue; + } + + base_type = fne_resolved; + base_class = fne; + continue; + } + + if (ifaces == null) + ifaces = new TypeSpec [count - i]; + + if (fne_resolved.IsInterface) { + for (int ii = 0; ii < j; ++ii) { + if (fne_resolved == ifaces [ii]) { + Report.Error (528, Location, "`{0}' is already listed in interface list", + fne_resolved.GetSignatureForError ()); + break; + } + } + + if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) { + Report.Error (61, fne.Location, + "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'", + fne_resolved.GetSignatureForError (), GetSignatureForError ()); + } + } else { + Report.SymbolRelatedToPreviousError (fne_resolved); + if (Kind != MemberKind.Class) { + Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ()); + } else if (base_class != null) + Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')", + GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ()); + else { + Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first", + GetSignatureForError (), fne_resolved.GetSignatureForError ()); + } + } + + ifaces [j++] = fne_resolved; + } + + return ifaces; + } + + TypeSpec[] GetNormalPartialBases () + { + var ifaces = new List (0); + if (iface_exprs != null) + ifaces.AddRange (iface_exprs); + + foreach (TypeContainer part in partial_parts) { + FullNamedExpression new_base_class; + var new_ifaces = part.ResolveBaseTypes (out new_base_class); + if (new_base_class != null) { + if (base_type_expr != null && part.base_type != base_type) { + Report.SymbolRelatedToPreviousError (new_base_class.Location, ""); + Report.Error (263, part.Location, + "Partial declarations of `{0}' must not specify different base classes", + part.GetSignatureForError ()); + } else { + base_type_expr = new_base_class; + base_type = part.base_type; + } + } + + if (new_ifaces == null) + continue; + + foreach (var iface in new_ifaces) { + if (ifaces.Contains (iface)) + continue; + + ifaces.Add (iface); + } + } + + if (ifaces.Count == 0) + return null; + + return ifaces.ToArray (); + } + + // + // Checks that some operators come in pairs: + // == and != + // > and < + // >= and <= + // true and false + // + // They are matched based on the return type and the argument types + // + void CheckPairedOperators () + { + bool has_equality_or_inequality = false; + var operators = this.operators.ToArray (); + bool[] has_pair = new bool[operators.Length]; + + for (int i = 0; i < operators.Length; ++i) { + if (operators[i] == null) + continue; + + Operator o_a = (Operator) operators[i]; + Operator.OpType o_type = o_a.OperatorType; + if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality) + has_equality_or_inequality = true; + + Operator.OpType matching_type = o_a.GetMatchingOperator (); + if (matching_type == Operator.OpType.TOP) { + operators[i] = null; + continue; + } + + for (int ii = 0; ii < operators.Length; ++ii) { + Operator o_b = (Operator) operators[ii]; + if (o_b == null || o_b.OperatorType != matching_type) + continue; + + if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType)) + continue; + + if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes)) + continue; + + operators[i] = null; + + // + // Used to ignore duplicate user conversions + // + has_pair[ii] = true; + } + } + + for (int i = 0; i < operators.Length; ++i) { + if (operators[i] == null || has_pair[i]) + continue; + + Operator o = (Operator) operators [i]; + Report.Error (216, o.Location, + "The operator `{0}' requires a matching operator `{1}' to also be defined", + o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ())); + } + + if (has_equality_or_inequality) { + if (Methods == null || !HasEquals) + Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", + GetSignatureForError ()); + + if (Methods == null || !HasGetHashCode) + Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", + GetSignatureForError ()); + } + } + + bool CreateTypeBuilder () + { + // + // Sets .size to 1 for structs with no instance fields + // + int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0; + + if (IsTopLevel) { + TypeBuilder = Module.CreateBuilder (Name, TypeAttr, type_size); + } else { + TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size); + } + + if (DeclaringAssembly.Importer != null) + DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec); + + spec.SetMetaInfo (TypeBuilder); + spec.MemberCache = new MemberCache (this); + spec.DeclaringType = Parent.CurrentType; + + if (!IsTopLevel) + Parent.MemberCache.AddMember (spec); + + if (IsGeneric) { + string[] param_names = new string[TypeParameters.Length]; + for (int i = 0; i < TypeParameters.Length; i++) + param_names [i] = TypeParameters[i].Name; + + all_tp_builders = TypeBuilder.DefineGenericParameters (param_names); + + int offset = CurrentTypeParametersStartIndex; + for (int i = offset; i < all_tp_builders.Length; i++) { + CurrentTypeParameters [i - offset].Define (all_tp_builders [i], spec); + } + } + + return true; + } + + // + // Creates a proxy base method call inside this container for hoisted base member calls + // + public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method) + { + Method proxy_method; + + // + // One proxy per base method is enough + // + if (hoisted_base_call_proxies == null) { + hoisted_base_call_proxies = new Dictionary (); + proxy_method = null; + } else { + hoisted_base_call_proxies.TryGetValue (method, out proxy_method); + } + + if (proxy_method == null) { + string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count); + var base_parameters = new Parameter[method.Parameters.Count]; + for (int i = 0; i < base_parameters.Length; ++i) { + var base_param = method.Parameters.FixedParameters[i]; + base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location), + base_param.Name, base_param.ModFlags, null, Location); + base_parameters[i].Resolve (this, i); + } + + var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types); + if (method.Parameters.HasArglist) { + cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location); + cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (); + } + + GenericMethod generic_method; + MemberName member_name; + TypeArguments targs = null; + if (method.IsGeneric) { + // + // Copy all base generic method type parameters info + // + var hoisted_tparams = method.GenericDefinition.TypeParameters; + var type_params = new TypeParameter[hoisted_tparams.Length]; + targs = new TypeArguments (); + targs.Arguments = new TypeSpec[type_params.Length]; + for (int i = 0; i < type_params.Length; ++i) { + var tp = hoisted_tparams[i]; + targs.Add (new TypeParameterName (tp.Name, null, Location)); + targs.Arguments[i] = tp; + type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null); + } + + member_name = new MemberName (name, targs, Location); + generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params, + new TypeExpression (method.ReturnType, Location), cloned_params); + } else { + member_name = new MemberName (name); + generic_method = null; + } + + // Compiler generated proxy + proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location), + Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN, + member_name, cloned_params, null); + + var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location); + + var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location); + mg.InstanceExpression = new BaseThis (method.DeclaringType, Location); + if (targs != null) + mg.SetTypeArguments (rc, targs); + + // Get all the method parameters and pass them as arguments + var real_base_call = new Invocation (mg, block.GetAllParametersArguments ()); + Statement statement; + if (method.ReturnType.Kind == MemberKind.Void) + statement = new StatementExpression (real_base_call); + else + statement = new Return (real_base_call, Location); + + block.AddStatement (statement); + proxy_method.Block = block; + + methods.Add (proxy_method); + proxy_method.Define (); + + hoisted_base_call_proxies.Add (method, proxy_method); + } + + return proxy_method.Spec; + } + + bool DefineBaseTypes () + { + iface_exprs = ResolveBaseTypes (out base_type_expr); + if (partial_parts != null) { + iface_exprs = GetNormalPartialBases (); + } + + var cycle = CheckRecursiveDefinition (this); + if (cycle != null) { + Report.SymbolRelatedToPreviousError (cycle); + if (this is Interface) { + Report.Error (529, Location, + "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'", + GetSignatureForError (), cycle.GetSignatureForError ()); + + iface_exprs = null; + } else { + Report.Error (146, Location, + "Circular base class dependency involving `{0}' and `{1}'", + GetSignatureForError (), cycle.GetSignatureForError ()); + + base_type = null; + } + } + + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + // Prevents a crash, the interface might not have been resolved: 442144 + if (iface_type == null) + continue; + + if (!spec.AddInterface (iface_type)) + continue; + + TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ()); + + // Ensure the base is always setup + var compiled_iface = iface_type.MemberDefinition as Interface; + if (compiled_iface != null) { + // TODO: Need DefineBaseType only + compiled_iface.DefineType (); + } + + if (iface_type.Interfaces != null) { + var base_ifaces = new List (iface_type.Interfaces); + for (int i = 0; i < base_ifaces.Count; ++i) { + var ii_iface_type = base_ifaces[i]; + if (spec.AddInterface (ii_iface_type)) { + TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ()); + + if (ii_iface_type.Interfaces != null) + base_ifaces.AddRange (ii_iface_type.Interfaces); + } + } + } + } + } + + if (Kind == MemberKind.Interface) { + spec.BaseType = Compiler.BuiltinTypes.Object; + return true; + } + + if (base_type != null) { + spec.BaseType = base_type; + + // Set base type after type creation + TypeBuilder.SetParent (base_type.GetMetaInfo ()); + } else { + TypeBuilder.SetParent (null); + } + + return true; + } + + public virtual void DefineConstants () + { + if (constants != null) { + foreach (Const c in constants) { + c.DefineValue (); + } + } + + if (instance_constructors != null) { + foreach (MethodCore m in instance_constructors) { + var p = m.ParameterInfo; + if (!p.IsEmpty) { + p.ResolveDefaultValues (m); + } + } + } + + if (methods != null) { + foreach (MethodCore m in methods) { + var p = m.ParameterInfo; + if (!p.IsEmpty) { + p.ResolveDefaultValues (m); + } + } + } + + if (indexers != null) { + foreach (Indexer i in indexers) { + i.ParameterInfo.ResolveDefaultValues (i); + } + } + + if (types != null) { + foreach (var t in types) + t.DefineConstants (); + } + } + + // + // Defines the type in the appropriate ModuleBuilder or TypeBuilder. + // + public bool CreateType () + { + if (TypeBuilder != null) + return !error; + + if (error) + return false; + + if (!CreateTypeBuilder ()) { + error = true; + return false; + } + + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) { + part.spec = spec; + part.current_type = current_type; + part.TypeBuilder = TypeBuilder; + } + } + + if (Types != null) { + foreach (TypeContainer tc in Types) { + tc.CreateType (); + } + } + + return true; + } + + public override void DefineType () + { + if (error) + return; + if (type_defined) + return; + + type_defined = true; + + // TODO: Driver resolves only first level of namespace, do the rest here for now + if (IsTopLevel && (ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + NamespaceEntry.Resolve (); + } + + if (!DefineBaseTypes ()) { + error = true; + return; + } + + if (!DefineNestedTypes ()) { + error = true; + return; + } + } + + public override void SetParameterInfo (List constraints_list) + { + base.SetParameterInfo (constraints_list); + + if (PartialContainer.CurrentTypeParameters == null || PartialContainer == this) + return; + + TypeParameter[] tc_names = PartialContainer.CurrentTypeParameters; + for (int i = 0; i < tc_names.Length; ++i) { + if (tc_names [i].Name != type_params [i].Name) { + Report.SymbolRelatedToPreviousError (PartialContainer.Location, ""); + Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order", + GetSignatureForError ()); + break; + } + + if (tc_names [i].Variance != type_params [i].Variance) { + Report.SymbolRelatedToPreviousError (PartialContainer.Location, ""); + Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers", + GetSignatureForError ()); + break; + } + } + } + + // + // Replaces normal spec with predefined one when compiling corlib + // and this type container defines predefined type + // + public void SetPredefinedSpec (BuiltinTypeSpec spec) + { + // When compiling build-in types we start with two + // version of same type. One is of BuiltinTypeSpec and + // second one is ordinary TypeSpec. The unification + // happens at later stage when we know which type + // really matches the builtin type signature. However + // that means TypeSpec create during CreateType of this + // type has to be replaced with builtin one + // + spec.SetMetaInfo (TypeBuilder); + spec.MemberCache = this.spec.MemberCache; + spec.DeclaringType = this.spec.DeclaringType; + + this.spec = spec; + current_type = null; + } + + void UpdateTypeParameterConstraints (TypeContainer part) + { + TypeParameter[] current_params = type_params; + for (int i = 0; i < current_params.Length; i++) { + if (current_params [i].AddPartialConstraints (part, part.type_params [i])) + continue; + + Report.SymbolRelatedToPreviousError (Location, ""); + Report.Error (265, part.Location, + "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'", + GetSignatureForError (), current_params [i].GetSignatureForError ()); + } + } + + public bool ResolveTypeParameters () + { + if (!DoResolveTypeParameters ()) + return false; + + if (types != null) { + foreach (var type in types) + if (!type.ResolveTypeParameters ()) + return false; + } + + if (compiler_generated != null) { + foreach (CompilerGeneratedClass c in compiler_generated) + if (!c.ResolveTypeParameters ()) + return false; + } + + return true; + } + + protected virtual bool DoResolveTypeParameters () + { + if (CurrentTypeParameters == null) + return true; + + if (PartialContainer != this) + throw new InternalErrorException (); + + var base_context = new BaseContext (this); + foreach (TypeParameter type_param in CurrentTypeParameters) { + if (!type_param.ResolveConstraints (base_context)) { + error = true; + return false; + } + } + + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) + UpdateTypeParameterConstraints (part); + } + + return true; + } + + protected virtual bool DefineNestedTypes () + { + if (Types != null) { + foreach (TypeContainer tc in Types) + tc.DefineType (); + } + + return true; + } + + TypeSpec CheckRecursiveDefinition (TypeContainer tc) + { + if (InTransit != null) + return spec; + + InTransit = tc; + + if (base_type != null) { + var ptc = base_type.MemberDefinition as TypeContainer; + if (ptc != null && ptc.CheckRecursiveDefinition (this) != null) + return base_type; + } + + if (iface_exprs != null) { + foreach (var iface in iface_exprs) { + // the interface might not have been resolved, prevents a crash, see #442144 + if (iface == null) + continue; + var ptc = iface.MemberDefinition as Interface; + if (ptc != null && ptc.CheckRecursiveDefinition (this) != null) + return iface; + } + } + + if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null) + return spec; + + InTransit = null; + return null; + } + + /// + /// Populates our TypeBuilder with fields and methods + /// + public sealed override bool Define () + { + if (members_defined) + return members_defined_ok; + + members_defined_ok = DoDefineMembers (); + members_defined = true; + + if (types != null) { + foreach (var nested in types) + nested.Define (); + } + + return members_defined_ok; + } + + protected virtual bool DoDefineMembers () + { + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + if (iface_type == null) + continue; + + // Ensure the base is always setup + var compiled_iface = iface_type.MemberDefinition as Interface; + if (compiled_iface != null) + compiled_iface.Define (); + + if (Kind == MemberKind.Interface) + MemberCache.AddInterface (iface_type); + + ObsoleteAttribute oa = iface_type.GetAttributeObsolete (); + if (oa != null && !IsObsolete) + AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report); + + if (iface_type.Arity > 0) { + // TODO: passing `this' is wrong, should be base type iface instead + TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this); + + if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) { + Report.Error (1966, Location, + "`{0}': cannot implement a dynamic interface `{1}'", + GetSignatureForError (), iface_type.GetSignatureForError ()); + return false; + } + + if (spec.Interfaces != null) { + foreach (var prev_iface in iface_exprs) { + if (prev_iface == iface_type) + break; + + if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface)) + continue; + + Report.Error (695, Location, + "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions", + GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ()); + } + } + } + } + } + + if (base_type != null) { + // + // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType) + // + if (base_type_expr != null) { + ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete (); + if (obsolete_attr != null && !IsObsolete) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report); + + if (IsGeneric && base_type.IsAttribute) { + Report.Error (698, base_type_expr.Location, + "A generic type cannot derive from `{0}' because it is an attribute class", + base_type.GetSignatureForError ()); + } + } + + if (base_type.Interfaces != null) { + foreach (var iface in base_type.Interfaces) + spec.AddInterface (iface); + } + + var baseContainer = base_type.MemberDefinition as ClassOrStruct; + if (baseContainer != null) { + baseContainer.Define (); + + // + // It can trigger define of this type (for generic types only) + // + if (HasMembersDefined) + return true; + } + } + + DefineContainerMembers (constants); + DefineContainerMembers (fields); + + if (Kind == MemberKind.Struct || Kind == MemberKind.Class) { + pending = PendingImplementation.GetPendingImplementations (this); + + if (requires_delayed_unmanagedtype_check) { + requires_delayed_unmanagedtype_check = false; + foreach (FieldBase f in fields) { + if (f.MemberType != null && f.MemberType.IsPointer) + TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location); + } + } + } + + // + // Constructors are not in the defined_names array + // + DefineContainerMembers (instance_constructors); + + DefineContainerMembers (events); + DefineContainerMembers (ordered_explicit_member_list); + DefineContainerMembers (ordered_member_list); + + if (operators != null) { + DefineContainerMembers (operators); + CheckPairedOperators (); + } + + ComputeIndexerName(); + CheckEqualsAndGetHashCode(); + + if (Kind == MemberKind.Interface && iface_exprs != null) { + MemberCache.RemoveHiddenMembers (spec); + } + + return true; + } + + protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList + { + if (mcal != null) { + for (int i = 0; i < mcal.Count; ++i) { + MemberCore mc = (MemberCore) mcal[i]; + try { + mc.Define (); + } catch (Exception e) { + throw new InternalErrorException (mc, e); + } + } + } + } + + protected virtual void ComputeIndexerName () + { + if (indexers == null) + return; + + string class_indexer_name = null; + + // + // If there's both an explicit and an implicit interface implementation, the + // explicit one actually implements the interface while the other one is just + // a normal indexer. See bug #37714. + // + + // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers + foreach (Indexer i in indexers) { + if (i.InterfaceType != null) { + if (seen_normal_indexers) + throw new Exception ("Internal Error: 'Indexers' array not sorted properly."); + continue; + } + + seen_normal_indexers = true; + + if (class_indexer_name == null) { + class_indexer_name = i.ShortName; + continue; + } + + if (i.ShortName != class_indexer_name) + Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type"); + } + + if (class_indexer_name != null) + indexer_name = class_indexer_name; + } + + void EmitIndexerName () + { + if (!seen_normal_indexers) + return; + + var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get (); + if (ctor == null) + return; + + var encoder = new AttributeEncoder (); + encoder.Encode (GetAttributeDefaultMember ()); + encoder.EncodeEmptyNamedArguments (); + + TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + + protected virtual void CheckEqualsAndGetHashCode () + { + if (methods == null) + return; + + if (HasEquals && !HasGetHashCode) { + Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ()); + } + } + + // Indicated whether container has StructLayout attribute set Explicit + public bool HasExplicitLayout { + get { return (caching_flags & Flags.HasExplicitLayout) != 0; } + set { caching_flags |= Flags.HasExplicitLayout; } + } + + public bool HasStructLayout { + get { return (caching_flags & Flags.HasStructLayout) != 0; } + set { caching_flags |= Flags.HasStructLayout; } + } + + public MemberCache MemberCache { + get { + return spec.MemberCache; + } + } + + void CheckMemberUsage (List al, string member_type) + { + if (al == null) + return; + + foreach (MemberCore mc in al) { + if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) + continue; + + if ((mc.ModFlags & Modifiers.PARTIAL) != 0) + continue; + + if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) { + Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ()); + } + } + } + + public virtual void VerifyMembers () + { + // + // Check for internal or private fields that were never assigned + // + if (Report.WarningLevel >= 3) { + if (Compiler.Settings.EnhancedWarnings) { + CheckMemberUsage (properties, "property"); + CheckMemberUsage (methods, "method"); + CheckMemberUsage (constants, "constant"); + } + + if (fields != null){ + bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly (); + foreach (FieldBase f in fields) { + if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) { + if (is_type_exposed) + continue; + + f.SetIsUsed (); + } + + if (!f.IsUsed){ + if ((f.caching_flags & Flags.IsAssigned) == 0) + Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ()); + else { + Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used", + f.GetSignatureForError ()); + } + continue; + } + + if ((f.caching_flags & Flags.IsAssigned) != 0) + continue; + + // + // Only report 649 on level 4 + // + if (Report.WarningLevel < 4) + continue; + + // + // Don't be pendatic over serializable attributes + // + if (f.OptAttributes != null || PartialContainer.HasStructLayout) + continue; + + Constant c = New.Constantify (f.MemberType, f.Location); + string value; + if (c != null) { + value = c.GetValueAsLiteral (); + } else if (TypeSpec.IsReferenceType (f.MemberType)) { + value = "null"; + } else { + // Ignore this warning for struct value fields (they are always initialized) + if (f.MemberType.IsStruct) + continue; + + value = null; + } + + if (value != null) + value = " `" + value + "'"; + + Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}", + f.GetSignatureForError (), value); + } + } + } + } + + public override void Emit () + { + if (!IsTopLevel) { + MemberSpec candidate; + bool overrides = false; + var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides); + if (conflict_symbol == null && candidate == null) { + if ((ModFlags & Modifiers.NEW) != 0) + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } else { + if ((ModFlags & Modifiers.NEW) == 0) { + if (candidate == null) + candidate = conflict_symbol; + + Report.SymbolRelatedToPreviousError (candidate); + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), candidate.GetSignatureForError ()); + } + } + } + + // Run constraints check on all possible generic types + if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + if (base_type != null && base_type_expr != null) { + ConstraintChecker.Check (this, base_type, base_type_expr.Location); + } + + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + if (iface_type == null) + continue; + + ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong + } + } + } + + if (all_tp_builders != null) { + int current_starts_index = CurrentTypeParametersStartIndex; + for (int i = 0; i < all_tp_builders.Length; i++) { + if (i < current_starts_index) { + TypeParameters[i].EmitConstraints (all_tp_builders [i]); + } else { + var tp = CurrentTypeParameters [i - current_starts_index]; + tp.CheckGenericConstraints (!IsObsolete); + tp.Emit (); + } + } + } + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder); + +#if STATIC + if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet) + TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType); +#endif + + base.Emit (); + } + + // TODO: move to ClassOrStruct + void EmitConstructors () + { + if (instance_constructors == null) + return; + + if (spec.IsAttribute && IsExposedFromAssembly () && Compiler.Settings.VerifyClsCompliance && IsClsComplianceRequired ()) { + bool has_compliant_args = false; + + foreach (Constructor c in instance_constructors) { + try { + c.Emit (); + } + catch (Exception e) { + throw new InternalErrorException (c, e); + } + + if (has_compliant_args) + continue; + + has_compliant_args = c.HasCompliantArgs; + } + if (!has_compliant_args) + Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ()); + } else { + foreach (Constructor c in instance_constructors) { + try { + c.Emit (); + } + catch (Exception e) { + throw new InternalErrorException (c, e); + } + } + } + } + + /// + /// Emits the code, this step is performed after all + /// the types, enumerations, constructors + /// + public virtual void EmitType () + { + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + + if (OptAttributes != null) + OptAttributes.Emit (); + + Emit (); + + EmitConstructors (); + + if (constants != null) + foreach (Const con in constants) + con.Emit (); + + if (default_static_constructor != null) + default_static_constructor.Emit (); + + if (operators != null) + foreach (Operator o in operators) + o.Emit (); + + if (properties != null) + foreach (Property p in properties) + p.Emit (); + + if (indexers != null) { + foreach (Indexer indx in indexers) + indx.Emit (); + EmitIndexerName (); + } + + if (events != null){ + foreach (Event e in Events) + e.Emit (); + } + + if (methods != null) { + for (int i = 0; i < methods.Count; ++i) + ((MethodOrOperator) methods [i]).Emit (); + } + + if (fields != null) + foreach (FieldBase f in fields) + f.Emit (); + + if (types != null) { + foreach (TypeContainer t in types) + t.EmitType (); + } + + if (pending != null) + pending.VerifyPendingMethods (); + + if (Report.Errors > 0) + return; + + if (compiler_generated != null) { + for (int i = 0; i < compiler_generated.Count; ++i) + compiler_generated [i].EmitType (); + } + } + + public virtual void CloseType () + { + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + + // Close base type container first to avoid TypeLoadException + if (spec.BaseType != null) { + var btype = spec.BaseType.MemberDefinition as TypeContainer; + if (btype != null) { + btype.CloseType (); + + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + } + } + + try { + caching_flags |= Flags.CloseTypeCreated; + TypeBuilder.CreateType (); + } catch (TypeLoadException){ + // + // This is fine, the code still created the type + // +// Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name); +// Console.WriteLine (e.Message); + } catch (Exception e) { + throw new InternalErrorException (this, e); + } + + if (Types != null){ + foreach (TypeContainer tc in Types) + tc.CloseType (); + } + + if (compiler_generated != null) + foreach (CompilerGeneratedClass c in compiler_generated) + c.CloseType (); + + types = null; + initialized_fields = null; + initialized_static_fields = null; + constants = null; + ordered_explicit_member_list = null; + ordered_member_list = null; + methods = null; + events = null; + indexers = null; + operators = null; + compiler_generated = null; + default_constructor = null; + default_static_constructor = null; + type_bases = null; + OptAttributes = null; + } + + // + // Performs the validation on a Method's modifiers (properties have + // the same properties). + // + // TODO: Why is it not done at parse stage, move to Modifiers::Check + // + public bool MethodModifiersValid (MemberCore mc) + { + const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE); + const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL); + bool ok = true; + var flags = mc.ModFlags; + + // + // At most one of static, virtual or override + // + if ((flags & Modifiers.STATIC) != 0){ + if ((flags & vao) != 0){ + Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract", + mc.GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){ + Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual", + mc.GetSignatureForError ()); + ok = false; + } + + // + // If the declaration includes the abstract modifier, then the + // declaration does not include static, virtual or extern + // + if ((flags & Modifiers.ABSTRACT) != 0){ + if ((flags & Modifiers.EXTERN) != 0){ + Report.Error ( + 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ()); + ok = false; + } + + if ((flags & Modifiers.SEALED) != 0) { + Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ()); + ok = false; + } + + if ((flags & Modifiers.VIRTUAL) != 0){ + Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ()); + ok = false; + } + + if ((ModFlags & Modifiers.ABSTRACT) == 0){ + Report.SymbolRelatedToPreviousError (this); + Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'", + mc.GetSignatureForError (), GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.PRIVATE) != 0){ + if ((flags & vao) != 0){ + Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.SEALED) != 0){ + if ((flags & Modifiers.OVERRIDE) == 0){ + Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ()); + ok = false; + } + } + + return ok; + } + + public Constructor DefaultStaticConstructor { + get { return default_static_constructor; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + // Check this name against other containers + NamespaceEntry.NS.VerifyClsCompliance (); + + // Check all container names for user classes + if (Kind != MemberKind.Delegate) + MemberCache.VerifyClsCompliance (Definition, Report); + + if (BaseType != null && !BaseType.IsCLSCompliant ()) { + Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", + GetSignatureForError (), BaseType.GetSignatureForError ()); + } + return true; + } + + /// + /// Performs checks for an explicit interface implementation. First it + /// checks whether the `interface_type' is a base inteface implementation. + /// Then it checks whether `name' exists in the interface type. + /// + public bool VerifyImplements (InterfaceMemberBase mb) + { + var ifaces = spec.Interfaces; + if (ifaces != null) { + foreach (TypeSpec t in ifaces){ + if (t == mb.InterfaceType) + return true; + } + } + + Report.SymbolRelatedToPreviousError (mb.InterfaceType); + Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'", + mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType)); + return false; + } + + // + // Used for visiblity checks to tests whether this definition shares + // base type baseType, it does member-definition search + // + public bool IsBaseTypeDefinition (TypeSpec baseType) + { + // RootContext check + if (TypeBuilder == null) + return false; + + var type = spec; + do { + if (type.MemberDefinition == baseType.MemberDefinition) + return true; + + type = type.BaseType; + } while (type != null); + + return false; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return Module.DeclaringAssembly == assembly; + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ()); + } + + // + // Public function used to locate types. + // + // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors. + // + // Returns: Type or null if they type can not be found. + // + public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + FullNamedExpression e; + if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility) + return e; + + e = null; + + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name); + if (tparam != null) + e = new TypeParameterExpr (tparam, Location.Null); + } + } + + if (e == null) { + TypeSpec t = LookupNestedTypeInHierarchy (name, arity); + + if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility)) + e = new TypeExpression (t, Location.Null); + else if (Parent != null) { + e = Parent.LookupNamespaceOrType (name, arity, mode, loc); + } else { + int errors = Report.Errors; + + e = NamespaceEntry.LookupNamespaceOrType (name, arity, mode, loc); + + if (errors != Report.Errors) + return e; + } + } + + // TODO MemberCache: How to cache arity stuff ? + if (arity == 0 && mode == LookupMode.Normal) + Cache[name] = e; + + return e; + } + + TypeSpec LookupNestedTypeInHierarchy (string name, int arity) + { + // TODO: GenericMethod only + if (PartialContainer == null) + return null; + + // Has any nested type + // Does not work, because base type can have + //if (PartialContainer.Types == null) + // return null; + + var container = PartialContainer.CurrentType; + + // Is not Root container + if (container == null) + return null; + + return MemberCache.FindNestedType (container, name, arity); + } + + public void Mark_HasEquals () + { + cached_method |= CachedMethods.Equals; + } + + public void Mark_HasGetHashCode () + { + cached_method |= CachedMethods.GetHashCode; + } + + /// + /// Method container contains Equals method + /// + public bool HasEquals { + get { + return (cached_method & CachedMethods.Equals) != 0; + } + } + + /// + /// Method container contains GetHashCode method + /// + public bool HasGetHashCode { + get { + return (cached_method & CachedMethods.GetHashCode) != 0; + } + } + + public bool HasStaticFieldInitializer { + get { + return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0; + } + set { + if (value) + cached_method |= CachedMethods.HasStaticFieldInitializer; + else + cached_method &= ~CachedMethods.HasStaticFieldInitializer; + } + } + + public override string DocCommentHeader { + get { return "T:"; } + } + } + + public abstract class ClassOrStruct : TypeContainer + { + SecurityType declarative_security; + + public ClassOrStruct (NamespaceContainer ns, DeclSpace parent, + MemberName name, Attributes attrs, MemberKind kind) + : base (ns, parent, name, attrs, kind) + { + } + + protected override bool AddToContainer (MemberCore symbol, string name) + { + if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) { + if (symbol is TypeParameter) { + Report.Error (694, symbol.Location, + "Type parameter `{0}' has same name as containing type, or method", + symbol.GetSignatureForError ()); + return false; + } + + InterfaceMemberBase imb = symbol as InterfaceMemberBase; + if (imb == null || !imb.IsExplicitImpl) { + Report.SymbolRelatedToPreviousError (this); + Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type", + symbol.GetSignatureForError ()); + return false; + } + } + + return base.AddToContainer (symbol, name); + } + + public override void VerifyMembers () + { + base.VerifyMembers (); + + if ((events != null) && Report.WarningLevel >= 3) { + foreach (Event e in events){ + // Note: The event can be assigned from same class only, so we can report + // this warning for all accessibility modes + if ((e.caching_flags & Flags.IsUsed) == 0) + Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ()); + } + } + + if (types != null) { + foreach (var t in types) + t.VerifyMembers (); + } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.StructLayout) { + PartialContainer.HasStructLayout = true; + if (a.IsExplicitLayoutKind ()) + PartialContainer.HasExplicitLayout = true; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + /// + /// Defines the default constructors + /// + protected void DefineDefaultConstructor (bool is_static) + { + // The default instance constructor is public + // If the class is abstract, the default constructor is protected + // The default static constructor is private + + Modifiers mods; + if (is_static) { + mods = Modifiers.STATIC | Modifiers.PRIVATE; + } else { + mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC; + } + + Constructor c = new Constructor (this, MemberName.Name, mods, + null, ParametersCompiled.EmptyReadOnlyParameters, + new GeneratedBaseInitializer (Location), + Location); + + AddConstructor (c); + c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + } + + protected override bool DoDefineMembers () + { + CheckProtectedModifier (); + + base.DoDefineMembers (); + + if (default_static_constructor != null) + default_static_constructor.Define (); + + return true; + } + + public override void Emit () + { + if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) { + DefineDefaultConstructor (true); + default_static_constructor.Define (); + } + + base.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + TypeBuilder.__AddDeclarativeSecurity (de); +#else + TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + } + + public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + DeclSpace top_level = Parent; + if (top_level != null) { + var candidates = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity); + if (candidates != null) { + scope = NamespaceEntry; + return candidates; + } + } + + return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + protected override TypeAttributes TypeAttr { + get { + if (default_static_constructor == null) + return base.TypeAttr | TypeAttributes.BeforeFieldInit; + + return base.TypeAttr; + } + } + } + + + // TODO: should be sealed + public class Class : ClassOrStruct { + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.ABSTRACT | + Modifiers.SEALED | + Modifiers.STATIC | + Modifiers.UNSAFE; + + public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed; + + public Class (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Class) + { + var accmods = (Parent == null || Parent.Parent == null) ? Modifiers.INTERNAL : Modifiers.PRIVATE; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report); + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void AddBasesForPart (DeclSpace part, List bases) + { + if (part.Name == "System.Object") + Report.Error (537, part.Location, + "The class System.Object cannot have a base class or implement an interface."); + base.AddBasesForPart (part, bases); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.AttributeUsage) { + if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) { + Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ()); + } + } + + if (a.Type == pa.Conditional && !BaseType.IsAttribute) { + Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes"); + return; + } + + if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) { + a.Error_MissingGuidAttribute (); + return; + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + if (a.Type.IsConditionallyExcluded (Compiler, Location)) + return; + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Class; + } + } + + protected override void DefineContainerMembers (System.Collections.IList list) + { + if (list == null) + return; + + if (!IsStatic) { + base.DefineContainerMembers (list); + return; + } + + foreach (MemberCore m in list) { + if (m is Operator) { + Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ()); + continue; + } + + if (m is Destructor) { + Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ()); + continue; + } + + if (m is Indexer) { + Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ()); + continue; + } + + if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate) + continue; + + if (m is Constructor) { + Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ()); + continue; + } + + Method method = m as Method; + if (method != null && method.ParameterInfo.HasExtensionMethodType) { + Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ()); + continue; + } + + Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ()); + } + + base.DefineContainerMembers (list); + } + + protected override bool DoDefineMembers () + { + if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) { + Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ()); + } + + if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) { + Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ()); + } + + if (InstanceConstructors == null && !IsStatic) + DefineDefaultConstructor (false); + + return base.DoDefineMembers (); + } + + public override void Emit () + { + base.Emit (); + + if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0) + Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder); + + if (base_type != null && base_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location); + } + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var ifaces = base.ResolveBaseTypes (out base_class); + + if (base_class == null) { + if (spec.BuiltinType != BuiltinTypeSpec.Type.Object) + base_type = Compiler.BuiltinTypes.Object; + } else { + if (base_type.IsGenericParameter){ + Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (base_type.IsStatic) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (base_type.IsSealed) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) { + Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object", + GetSignatureForError (), base_type.GetSignatureForError ()); + } + + switch (base_type.BuiltinType) { + case BuiltinTypeSpec.Type.Enum: + case BuiltinTypeSpec.Type.ValueType: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.Array: + if (!(spec is BuiltinTypeSpec)) { + Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + + base_type = Compiler.BuiltinTypes.Object; + } + break; + } + + if (!IsAccessibleAs (base_type)) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'", + base_type.GetSignatureForError (), GetSignatureForError ()); + } + } + + if (PartialContainer.IsStatic && ifaces != null) { + foreach (var t in ifaces) + Report.SymbolRelatedToPreviousError (t); + Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ()); + } + + return ifaces; + } + + /// Search for at least one defined condition in ConditionalAttribute of attribute class + /// Valid only for attribute classes. + public override string[] ConditionalConditions () + { + if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0) + return null; + + caching_flags &= ~Flags.Excluded_Undetected; + + if (OptAttributes == null) + return null; + + Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional); + if (attrs == null) + return null; + + string[] conditions = new string[attrs.Length]; + for (int i = 0; i < conditions.Length; ++i) + conditions[i] = attrs[i].GetConditionalAttributeValue (); + + caching_flags |= Flags.Excluded; + return conditions; + } + + // + // FIXME: How do we deal with the user specifying a different + // layout? + // + protected override TypeAttributes TypeAttr { + get { + TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class; + if (IsStatic) + ta |= StaticClassAttribute; + return ta; + } + } + } + + public sealed class Struct : ClassOrStruct { + + bool is_unmanaged, has_unmanaged_check_done; + bool InTransit; + + // + // Modifiers allowed in a struct declaration + // + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Struct (NamespaceContainer ns, DeclSpace parent, MemberName name, + Modifiers mod, Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Struct) + { + var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ; + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Struct; + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + + // + // When struct constains fixed fixed and struct layout has explicitly + // set CharSet, its value has to be propagated to compiler generated + // fixed types + // + if (a.Type == pa.StructLayout && Fields != null) { + var value = a.GetNamedValue ("CharSet"); + if (value == null) + return; + + for (int i = 0; i < Fields.Count; ++i) { + FixedField ff = Fields [i] as FixedField; + if (ff == null) + continue; + + ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ()); + } + } + } + + bool CheckStructCycles (Struct s) + { + if (s.Fields == null) + return true; + + if (s.InTransit) + return false; + + s.InTransit = true; + foreach (FieldBase field in s.Fields) { + TypeSpec ftype = field.Spec.MemberType; + if (!ftype.IsStruct) + continue; + + if (ftype is BuiltinTypeSpec) + continue; + + foreach (var targ in ftype.TypeArguments) { + if (!CheckFieldTypeCycle (targ)) { + Report.Error (523, field.Location, + "Struct member `{0}' of type `{1}' causes a cycle in the struct layout", + field.GetSignatureForError (), ftype.GetSignatureForError ()); + break; + } + } + + if ((field.IsStatic && (!ftype.IsGeneric || ftype == CurrentType))) + continue; + + if (!CheckFieldTypeCycle (ftype)) { + Report.Error (523, field.Location, + "Struct member `{0}' of type `{1}' causes a cycle in the struct layout", + field.GetSignatureForError (), ftype.GetSignatureForError ()); + break; + } + } + + s.InTransit = false; + return true; + } + + bool CheckFieldTypeCycle (TypeSpec ts) + { + var fts = ts.MemberDefinition as Struct; + if (fts == null) + return true; + + return CheckStructCycles (fts); + } + + public override void Emit () + { + CheckStructCycles (this); + + base.Emit (); + } + + public override bool IsUnmanagedType () + { + if (fields == null) + return true; + + if (has_unmanaged_check_done) + return is_unmanaged; + + if (requires_delayed_unmanagedtype_check) + return true; + + requires_delayed_unmanagedtype_check = true; + + foreach (FieldBase f in fields) { + if (f.IsStatic) + continue; + + // It can happen when recursive unmanaged types are defined + // struct S { S* s; } + TypeSpec mt = f.MemberType; + if (mt == null) { + return true; + } + + while (mt.IsPointer) + mt = TypeManager.GetElementType (mt); + + if (mt.IsGenericOrParentIsGeneric || mt.IsGenericParameter) { + has_unmanaged_check_done = true; + return false; + } + + if (TypeManager.IsUnmanagedType (mt)) + continue; + + has_unmanaged_check_done = true; + return false; + } + + has_unmanaged_check_done = true; + is_unmanaged = true; + return true; + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var ifaces = base.ResolveBaseTypes (out base_class); + base_type = Compiler.BuiltinTypes.ValueType; + return ifaces; + } + + protected override TypeAttributes TypeAttr { + get { + const + TypeAttributes DefaultTypeAttributes = + TypeAttributes.SequentialLayout | + TypeAttributes.Sealed ; + + return base.TypeAttr | DefaultTypeAttributes; + } + } + + public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) + { + if ((field.ModFlags & Modifiers.STATIC) == 0) { + Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers", + field.GetSignatureForError ()); + return; + } + base.RegisterFieldForInitialization (field, expression); + } + + } + + /// + /// Interfaces + /// + public sealed class Interface : TypeContainer { + + /// + /// Modifiers allowed in a class declaration + /// + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Interface (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Interface) + { + var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report); + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Interface; + } + } + + protected override TypeAttributes TypeAttr { + get { + const TypeAttributes DefaultTypeAttributes = + TypeAttributes.AutoLayout | + TypeAttributes.Abstract | + TypeAttributes.Interface; + + return base.TypeAttr | DefaultTypeAttributes; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) { + a.Error_MissingGuidAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (iface_exprs != null) { + foreach (var iface in iface_exprs) { + if (iface.IsCLSCompliant ()) + continue; + + Report.SymbolRelatedToPreviousError (iface); + Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant", + GetSignatureForError (), TypeManager.CSharpName (iface)); + } + } + + return true; + } + } + + public abstract class InterfaceMemberBase : MemberBase + { + // + // Common modifiers allowed in a class declaration + // + protected const Modifiers AllowedModifiersClass = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.VIRTUAL | + Modifiers.SEALED | + Modifiers.OVERRIDE | + Modifiers.ABSTRACT | + Modifiers.UNSAFE | + Modifiers.EXTERN; + + // + // Common modifiers allowed in a struct declaration + // + protected const Modifiers AllowedModifiersStruct = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.OVERRIDE | + Modifiers.UNSAFE | + Modifiers.EXTERN; + + // + // Common modifiers allowed in a interface declaration + // + protected const Modifiers AllowedModifiersInterface = + Modifiers.NEW | + Modifiers.UNSAFE; + + // + // Whether this is an interface member. + // + public bool IsInterface; + + // + // If true, this is an explicit interface implementation + // + public bool IsExplicitImpl; + + protected bool is_external_implementation; + + // + // The interface type we are explicitly implementing + // + public TypeSpec InterfaceType; + + // + // The method we're overriding if this is an override method. + // + protected MethodSpec base_method; + + readonly Modifiers explicit_mod_flags; + public MethodAttributes flags; + + public InterfaceMemberBase (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs) + : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE, + name, attrs) + { + IsInterface = parent.PartialContainer.Kind == MemberKind.Interface; + IsExplicitImpl = (MemberName.Left != null); + explicit_mod_flags = mod; + } + + public abstract Variance ExpectedMemberTypeVariance { get; } + + protected override bool CheckBase () + { + if (!base.CheckBase ()) + return false; + + if ((caching_flags & Flags.MethodOverloadsExist) != 0) + CheckForDuplications (); + + if (IsExplicitImpl) + return true; + + // For System.Object only + if (Parent.BaseType == null) + return true; + + MemberSpec candidate; + bool overrides = false; + var base_member = FindBaseMember (out candidate, ref overrides); + + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + if (base_member == null) { + if (candidate == null) { + if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) { + Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead", + "object.Finalize()"); + } else { + Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override", + GetSignatureForError (), SimpleName.GetMemberType (this)); + } + } else { + Report.SymbolRelatedToPreviousError (candidate); + if (this is Event) + Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + else if (this is PropertyBase) + Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + else + Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + } + + return false; + } + + // + // Handles ambiguous overrides + // + if (candidate != null) { + Report.SymbolRelatedToPreviousError (candidate); + Report.SymbolRelatedToPreviousError (base_member); + + // Get member definition for error reporting + var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member); + var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate); + + Report.Error (462, Location, + "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'", + GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ()); + } + + if (!CheckOverrideAgainstBase (base_member)) + return false; + + ObsoleteAttribute oa = base_member.GetAttributeObsolete (); + if (oa != null) { + if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'", + GetSignatureForError (), TypeManager.GetFullNameSignature (base_member)); + } + } else { + if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'", + GetSignatureForError (), TypeManager.GetFullNameSignature (base_member)); + } + } + + base_method = base_member as MethodSpec; + return true; + } + + if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember))) + base_member = candidate; + + if (base_member == null) { + if ((ModFlags & Modifiers.NEW) != 0) { + if (base_member == null) { + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } + } + } else { + if ((ModFlags & Modifiers.NEW) == 0) { + ModFlags |= Modifiers.NEW; + if (!IsCompilerGenerated) { + Report.SymbolRelatedToPreviousError (base_member); + if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) { + Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", + GetSignatureForError (), base_member.GetSignatureForError ()); + } else { + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), base_member.GetSignatureForError ()); + } + } + } + + if (!IsInterface && base_member.IsAbstract && !overrides) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'", + GetSignatureForError (), base_member.GetSignatureForError ()); + } + } + + return true; + } + + protected virtual bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters); + } + + // + // Performs various checks on the MethodInfo `mb' regarding the modifier flags + // that have been defined. + // + protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member) + { + bool ok = true; + + if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (506, Location, + "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override", + GetSignatureForError (), TypeManager.CSharpSignature (base_member)); + ok = false; + } + + // Now we check that the overriden method is not final + if ((base_member.Modifiers & Modifiers.SEALED) != 0) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed", + GetSignatureForError (), TypeManager.CSharpSignature (base_member)); + ok = false; + } + + var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType; + if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) { + Report.SymbolRelatedToPreviousError (base_member); + if (this is PropertyBasedMember) { + Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'", + GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member)); + } else { + Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'", + GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member)); + } + ok = false; + } + + return ok; + } + + protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member) + { + var thisp = this_member.ModFlags & Modifiers.AccessibilityMask; + var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask; + + if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) { + // + // It must be at least "protected" + // + if ((thisp & Modifiers.PROTECTED) == 0) { + return false; + } + + // + // when overriding protected internal, the method can be declared + // protected internal only within the same assembly or assembly + // which has InternalsVisibleTo + // + if ((thisp & Modifiers.INTERNAL) != 0) { + return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly); + } + + // + // protected overriding protected internal inside same assembly + // requires internal modifier as well + // + if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) { + return false; + } + + return true; + } + + return thisp == base_classp; + } + + public override bool Define () + { + if (IsInterface) { + ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT | + Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW)); + + flags = MethodAttributes.Public | + MethodAttributes.Abstract | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.Virtual; + } else { + Parent.PartialContainer.MethodModifiersValid (this); + + flags = ModifiersExtensions.MethodAttr (ModFlags); + } + + if (IsExplicitImpl) { + InterfaceType = MemberName.Left.GetTypeExpression ().ResolveAsType (Parent); + if (InterfaceType == null) + return false; + + if ((ModFlags & Modifiers.PARTIAL) != 0) { + Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface", + GetSignatureForError ()); + } + + if (!InterfaceType.IsInterface) { + Report.SymbolRelatedToPreviousError (InterfaceType); + Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface", + TypeManager.CSharpName (InterfaceType)); + } else { + Parent.PartialContainer.VerifyImplements (this); + } + + ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report); + } + + return base.Define (); + } + + protected bool DefineParameters (ParametersCompiled parameters) + { + if (!parameters.Resolve (this)) + return false; + + bool error = false; + for (int i = 0; i < parameters.Count; ++i) { + Parameter p = parameters [i]; + + if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1))) + p.Warning_UselessOptionalParameter (Report); + + if (p.CheckAccessibility (this)) + continue; + + TypeSpec t = parameters.Types [i]; + Report.SymbolRelatedToPreviousError (t); + if (this is Indexer) + Report.Error (55, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + else if (this is Operator) + Report.Error (57, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + else + Report.Error (51, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + error = true; + } + return !error; + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this); + } + + public override void Emit() + { + // for extern static method must be specified either DllImport attribute or MethodImplAttribute. + // We are more strict than csc and report this as an error because SRE does not allow emit that + if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) { + if (this is Constructor) { + Report.Warning (824, 1, Location, + "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ()); + } else { + Report.Warning (626, 1, Location, + "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation", + GetSignatureForError ()); + } + } + + base.Emit (); + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + // + // Two members can differ in their explicit interface + // type parameter only + // + InterfaceMemberBase imb = overload as InterfaceMemberBase; + if (imb != null && imb.IsExplicitImpl) { + if (IsExplicitImpl) { + caching_flags |= Flags.MethodOverloadsExist; + } + return true; + } + + return IsExplicitImpl; + } + + protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member) + { + var base_modifiers = base_member.Modifiers; + + // Remove internal modifier from types which are not internally accessible + if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) && + !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly)) + base_modifiers = Modifiers.PROTECTED; + + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (507, member.Location, + "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'", + member.GetSignatureForError (), + ModifiersExtensions.AccessibilityName (base_modifiers), + base_member.GetSignatureForError ()); + } + + protected void Error_StaticReturnType () + { + Report.Error (722, Location, + "`{0}': static types cannot be used as return types", + MemberType.GetSignatureForError ()); + } + + /// + /// Gets base method and its return type + /// + protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides); + } + + // + // The "short" name of this property / indexer / event. This is the + // name without the explicit interface. + // + public string ShortName { + get { return MemberName.Name; } + set { SetMemberName (new MemberName (MemberName.Left, value, Location)); } + } + + // + // Returns full metadata method name + // + public string GetFullName (MemberName name) + { + return GetFullName (name.Name); + } + + public string GetFullName (string name) + { + if (!IsExplicitImpl) + return name; + + // + // When dealing with explicit members a full interface type + // name is added to member name to avoid possible name conflicts + // + // We use CSharpName which gets us full name with benefit of + // replacing predefined names which saves some space and name + // is still unique + // + return TypeManager.CSharpName (InterfaceType) + "." + name; + } + + public override string GetSignatureForDocumentation () + { + if (IsExplicitImpl) + return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName; + + return Parent.GetSignatureForDocumentation () + "." + ShortName; + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + if (GenericMethod != null) + GenericMethod.VerifyClsCompliance (); + + return true; + } + + public override bool IsUsed + { + get { return IsExplicitImpl || base.IsUsed; } + } + + } + + public abstract class MemberBase : MemberCore + { + protected FullNamedExpression type_expr; + protected TypeSpec member_type; + + public readonly DeclSpace ds; + public readonly GenericMethod GenericMethod; + + public FullNamedExpression TypeName { + get { + return type_expr; + } + } + + protected MemberBase (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, + MemberName name, Attributes attrs) + : base (parent, name, attrs) + { + this.ds = generic != null ? generic : (DeclSpace) parent; + this.type_expr = type; + ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report); + GenericMethod = generic; + if (GenericMethod != null) + GenericMethod.ModFlags = ModFlags; + } + + #region Properties + + public TypeSpec MemberType { + get { + return member_type; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + } + + #endregion + + // + // Main member define entry + // + public override bool Define () + { + DoMemberTypeIndependentChecks (); + + // + // Returns false only when type resolution failed + // + if (!ResolveMemberType ()) + return false; + + DoMemberTypeDependentChecks (); + return true; + } + + // + // Any type_name independent checks + // + protected virtual void DoMemberTypeIndependentChecks () + { + if ((Parent.ModFlags & Modifiers.SEALED) != 0 && + (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { + Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'", + GetSignatureForError (), Parent.GetSignatureForError ()); + } + } + + // + // Any type_name dependent checks + // + protected virtual void DoMemberTypeDependentChecks () + { + // verify accessibility + if (!IsAccessibleAs (MemberType)) { + Report.SymbolRelatedToPreviousError (MemberType); + if (this is Property) + Report.Error (53, Location, + "Inconsistent accessibility: property type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than property `" + GetSignatureForError () + "'"); + else if (this is Indexer) + Report.Error (54, Location, + "Inconsistent accessibility: indexer return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than indexer `" + GetSignatureForError () + "'"); + else if (this is MethodCore) { + if (this is Operator) + Report.Error (56, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than operator `" + GetSignatureForError () + "'"); + else + Report.Error (50, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than method `" + GetSignatureForError () + "'"); + } else { + Report.Error (52, Location, + "Inconsistent accessibility: field type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than field `" + GetSignatureForError () + "'"); + } + } + } + + protected bool IsTypePermitted () + { + if (MemberType.IsSpecialRuntimeType) { + Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType)); + return false; + } + return true; + } + + protected virtual bool CheckBase () + { + CheckProtectedModifier (); + + return true; + } + + public override string GetSignatureForDocumentation () + { + return Parent.Name + "." + Name; + } + + protected virtual bool ResolveMemberType () + { + if (member_type != null) + throw new InternalErrorException ("Multi-resolve"); + + member_type = type_expr.ResolveAsType (this); + return member_type != null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs new file mode 100644 index 0000000000..abd114d2f9 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs @@ -0,0 +1,728 @@ +// +// codegen.cs: The code generator +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + /// + /// An Emit Context is created for each body of code (from methods, + /// properties bodies, indexer bodies or constructor bodies) + /// + public class EmitContext : BuilderContext + { + // TODO: Has to be private + public readonly ILGenerator ig; + + /// + /// The value that is allowed to be returned or NULL if there is no + /// return type. + /// + readonly TypeSpec return_type; + + /// + /// Keeps track of the Type to LocalBuilder temporary storage created + /// to store structures (used to compute the address of the structure + /// value on structure method invocations) + /// + Dictionary temporary_storage; + + /// + /// The location where we store the return value. + /// + public LocalBuilder return_value; + + /// + /// The location where return has to jump to return the + /// value + /// + public Label ReturnLabel; + + /// + /// If we already defined the ReturnLabel + /// + public bool HasReturnLabel; + + /// + /// Current loop begin and end labels. + /// + public Label LoopBegin, LoopEnd; + + /// + /// Default target in a switch statement. Only valid if + /// InSwitch is true + /// + public Label DefaultTarget; + + /// + /// If this is non-null, points to the current switch statement + /// + public Switch Switch; + + /// + /// Whether we are inside an anonymous method. + /// + public AnonymousExpression CurrentAnonymousMethod; + + readonly IMemberContext member_context; + + DynamicSiteClass dynamic_site_container; + + public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type) + { + this.member_context = rc; + this.ig = ig; + + this.return_type = return_type; + +#if STATIC + ig.__CleverExceptionBlockAssistance (); +#endif + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return MemberContext.Module.Compiler.BuiltinTypes; + } + } + + public TypeSpec CurrentType { + get { return member_context.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return member_context.CurrentTypeParameters; } + } + + public MemberCore CurrentTypeDefinition { + get { return member_context.CurrentMemberDefinition; } + } + + public bool IsStatic { + get { return member_context.IsStatic; } + } + + public bool IsAnonymousStoreyMutateRequired { + get { + return CurrentAnonymousMethod != null && + CurrentAnonymousMethod.Storey != null && + CurrentAnonymousMethod.Storey.Mutator != null; + } + } + + public IMemberContext MemberContext { + get { + return member_context; + } + } + + public ModuleContainer Module { + get { + return member_context.Module; + } + } + + // Has to be used for specific emitter errors only any + // possible resolver errors have to be reported during Resolve + public Report Report { + get { + return member_context.Module.Compiler.Report; + } + } + + public TypeSpec ReturnType { + get { + return return_type; + } + } + #endregion + + /// + /// This is called immediately before emitting an IL opcode to tell the symbol + /// writer to which source line this opcode belongs. + /// + public void Mark (Location loc) + { + if (!SymbolWriter.HasSymbolWriter || HasSet (Options.OmitDebugInfo) || loc.IsNull) + return; + + SymbolWriter.MarkSequencePoint (ig, loc); + } + + public void DefineLocalVariable (string name, LocalBuilder builder) + { + SymbolWriter.DefineLocalVariable (name, builder); + } + + public void BeginCatchBlock (TypeSpec type) + { + ig.BeginCatchBlock (type.GetMetaInfo ()); + } + + public void BeginExceptionBlock () + { + ig.BeginExceptionBlock (); + } + + public void BeginFinallyBlock () + { + ig.BeginFinallyBlock (); + } + + public void BeginScope () + { + SymbolWriter.OpenScope(ig); + } + + public void EndExceptionBlock () + { + ig.EndExceptionBlock (); + } + + public void EndScope () + { + SymbolWriter.CloseScope(ig); + } + + // + // Creates a nested container in this context for all dynamic compiler generated stuff + // + internal DynamicSiteClass CreateDynamicSite () + { + if (dynamic_site_container == null) { + var mc = member_context.CurrentMemberDefinition as MemberBase; + dynamic_site_container = new DynamicSiteClass (CurrentTypeDefinition.Parent.PartialContainer, mc, CurrentTypeParameters); + + CurrentTypeDefinition.Module.AddCompilerGeneratedClass (dynamic_site_container); + dynamic_site_container.CreateType (); + dynamic_site_container.DefineType (); + dynamic_site_container.ResolveTypeParameters (); + dynamic_site_container.Define (); + + var inflator = new TypeParameterInflator (Module, CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + var inflated = dynamic_site_container.CurrentType.InflateMember (inflator); + CurrentType.MemberCache.AddMember (inflated); + } + + return dynamic_site_container; + } + + public LocalBuilder DeclareLocal (TypeSpec type, bool pinned) + { + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + return ig.DeclareLocal (type.GetMetaInfo (), pinned); + } + + public Label DefineLabel () + { + return ig.DefineLabel (); + } + + public void MarkLabel (Label label) + { + ig.MarkLabel (label); + } + + public void Emit (OpCode opcode) + { + ig.Emit (opcode); + } + + public void Emit (OpCode opcode, LocalBuilder local) + { + ig.Emit (opcode, local); + } + + public void Emit (OpCode opcode, string arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, double arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, float arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, int arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, byte arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, Label label) + { + ig.Emit (opcode, label); + } + + public void Emit (OpCode opcode, Label[] labels) + { + ig.Emit (opcode, labels); + } + + public void Emit (OpCode opcode, TypeSpec type) + { + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (opcode, type.GetMetaInfo ()); + } + + public void Emit (OpCode opcode, FieldSpec field) + { + if (IsAnonymousStoreyMutateRequired) + field = field.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (opcode, field.GetMetaInfo ()); + } + + public void Emit (OpCode opcode, MethodSpec method) + { + if (IsAnonymousStoreyMutateRequired) + method = method.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + if (method.IsConstructor) + ig.Emit (opcode, (ConstructorInfo) method.GetMetaInfo ()); + else + ig.Emit (opcode, (MethodInfo) method.GetMetaInfo ()); + } + + // TODO: REMOVE breaks mutator + public void Emit (OpCode opcode, MethodInfo method) + { + ig.Emit (opcode, method); + } + + public void Emit (OpCode opcode, MethodSpec method, MetaType[] vargs) + { + // TODO MemberCache: This should mutate too + ig.EmitCall (opcode, (MethodInfo) method.GetMetaInfo (), vargs); + } + + public void EmitArrayNew (ArrayContainer ac) + { + if (ac.Rank == 1) { + Emit (OpCodes.Newarr, ac.Element); + } else { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Newobj, ac.GetConstructor ()); + } + } + + public void EmitArrayAddress (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetAddressMethod ()); + } else { + Emit (OpCodes.Ldelema, ac.Element); + } + } + + // + // Emits the right opcode to load from an array + // + public void EmitArrayLoad (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetGetMethod ()); + return; + } + + var type = ac.Element; + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Bool: + Emit (OpCodes.Ldelem_U1); + return; + case BuiltinTypeSpec.Type.SByte: + Emit (OpCodes.Ldelem_I1); + return; + case BuiltinTypeSpec.Type.Short: + Emit (OpCodes.Ldelem_I2); + return; + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + Emit (OpCodes.Ldelem_U2); + return; + case BuiltinTypeSpec.Type.Int: + Emit (OpCodes.Ldelem_I4); + return; + case BuiltinTypeSpec.Type.UInt: + Emit (OpCodes.Ldelem_U4); + return; + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + Emit (OpCodes.Ldelem_I8); + return; + case BuiltinTypeSpec.Type.Float: + Emit (OpCodes.Ldelem_R4); + return; + case BuiltinTypeSpec.Type.Double: + Emit (OpCodes.Ldelem_R8); + return; + case BuiltinTypeSpec.Type.IntPtr: + Emit (OpCodes.Ldelem_I); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + Emit (OpCodes.Ldelema, type); + Emit (OpCodes.Ldobj, type); + break; + case MemberKind.TypeParameter: + Emit (OpCodes.Ldelem, type); + break; + case MemberKind.PointerType: + Emit (OpCodes.Ldelem_I); + break; + default: + Emit (OpCodes.Ldelem_Ref); + break; + } + } + + // + // Emits the right opcode to store to an array + // + public void EmitArrayStore (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetSetMethod ()); + return; + } + + var type = ac.Element; + + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + Emit (OpCodes.Stelem_I1); + return; + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + Emit (OpCodes.Stelem_I2); + return; + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + Emit (OpCodes.Stelem_I4); + return; + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + Emit (OpCodes.Stelem_I8); + return; + case BuiltinTypeSpec.Type.Float: + Emit (OpCodes.Stelem_R4); + return; + case BuiltinTypeSpec.Type.Double: + Emit (OpCodes.Stelem_R8); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + Emit (OpCodes.Stobj, type); + break; + case MemberKind.TypeParameter: + Emit (OpCodes.Stelem, type); + break; + case MemberKind.PointerType: + Emit (OpCodes.Stelem_I); + break; + default: + Emit (OpCodes.Stelem_Ref); + break; + } + } + + public void EmitInt (int i) + { + switch (i) { + case -1: + ig.Emit (OpCodes.Ldc_I4_M1); + break; + + case 0: + ig.Emit (OpCodes.Ldc_I4_0); + break; + + case 1: + ig.Emit (OpCodes.Ldc_I4_1); + break; + + case 2: + ig.Emit (OpCodes.Ldc_I4_2); + break; + + case 3: + ig.Emit (OpCodes.Ldc_I4_3); + break; + + case 4: + ig.Emit (OpCodes.Ldc_I4_4); + break; + + case 5: + ig.Emit (OpCodes.Ldc_I4_5); + break; + + case 6: + ig.Emit (OpCodes.Ldc_I4_6); + break; + + case 7: + ig.Emit (OpCodes.Ldc_I4_7); + break; + + case 8: + ig.Emit (OpCodes.Ldc_I4_8); + break; + + default: + if (i >= -128 && i <= 127) { + ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i); + } else + ig.Emit (OpCodes.Ldc_I4, i); + break; + } + } + + public void EmitLong (long l) + { + if (l >= int.MinValue && l <= int.MaxValue) { + EmitInt (unchecked ((int) l)); + ig.Emit (OpCodes.Conv_I8); + return; + } + + if (l >= 0 && l <= uint.MaxValue) { + EmitInt (unchecked ((int) l)); + ig.Emit (OpCodes.Conv_U8); + return; + } + + ig.Emit (OpCodes.Ldc_I8, l); + } + + // + // Load the object from the pointer. + // + public void EmitLoadFromPtr (TypeSpec type) + { + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + ig.Emit (OpCodes.Ldind_I4); + return; + case BuiltinTypeSpec.Type.UInt: + ig.Emit (OpCodes.Ldind_U4); + return; + case BuiltinTypeSpec.Type.Short: + ig.Emit (OpCodes.Ldind_I2); + return; + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + ig.Emit (OpCodes.Ldind_U2); + return; + case BuiltinTypeSpec.Type.Byte: + ig.Emit (OpCodes.Ldind_U1); + return; + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + ig.Emit (OpCodes.Ldind_I1); + return; + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + ig.Emit (OpCodes.Ldind_I8); + return; + case BuiltinTypeSpec.Type.Float: + ig.Emit (OpCodes.Ldind_R4); + return; + case BuiltinTypeSpec.Type.Double: + ig.Emit (OpCodes.Ldind_R8); + return; + case BuiltinTypeSpec.Type.IntPtr: + ig.Emit (OpCodes.Ldind_I); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + case MemberKind.TypeParameter: + Emit (OpCodes.Ldobj, type); + break; + case MemberKind.PointerType: + ig.Emit (OpCodes.Ldind_I); + break; + default: + ig.Emit (OpCodes.Ldind_Ref); + break; + } + } + + // + // The stack contains the pointer and the value of type `type' + // + public void EmitStoreFromPtr (TypeSpec type) + { + if (type.IsEnum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + ig.Emit (OpCodes.Stind_I4); + return; + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + ig.Emit (OpCodes.Stind_I8); + return; + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + ig.Emit (OpCodes.Stind_I2); + return; + case BuiltinTypeSpec.Type.Float: + ig.Emit (OpCodes.Stind_R4); + return; + case BuiltinTypeSpec.Type.Double: + ig.Emit (OpCodes.Stind_R8); + return; + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + ig.Emit (OpCodes.Stind_I1); + return; + case BuiltinTypeSpec.Type.IntPtr: + ig.Emit (OpCodes.Stind_I); + return; + } + + if (type.IsStruct || TypeManager.IsGenericParameter (type)) + Emit (OpCodes.Stobj, type); + else + ig.Emit (OpCodes.Stind_Ref); + } + + /// + /// Returns a temporary storage for a variable of type t as + /// a local variable in the current body. + /// + public LocalBuilder GetTemporaryLocal (TypeSpec t) + { + if (temporary_storage != null) { + object o; + if (temporary_storage.TryGetValue (t, out o)) { + if (o is Stack) { + var s = (Stack) o; + o = s.Count == 0 ? null : s.Pop (); + } else { + temporary_storage.Remove (t); + } + } + if (o != null) + return (LocalBuilder) o; + } + return DeclareLocal (t, false); + } + + public void FreeTemporaryLocal (LocalBuilder b, TypeSpec t) + { + if (temporary_storage == null) { + temporary_storage = new Dictionary (ReferenceEquality.Default); + temporary_storage.Add (t, b); + return; + } + object o; + + if (!temporary_storage.TryGetValue (t, out o)) { + temporary_storage.Add (t, b); + return; + } + var s = o as Stack; + if (s == null) { + s = new Stack (); + s.Push ((LocalBuilder)o); + temporary_storage [t] = s; + } + s.Push (b); + } + + /// + /// ReturnValue creates on demand the LocalBuilder for the + /// return value from the function. By default this is not + /// used. This is only required when returns are found inside + /// Try or Catch statements. + /// + /// This method is typically invoked from the Emit phase, so + /// we allow the creation of a return label if it was not + /// requested during the resolution phase. Could be cleaned + /// up, but it would replicate a lot of logic in the Emit phase + /// of the code that uses it. + /// + public LocalBuilder TemporaryReturn () + { + if (return_value == null){ + return_value = DeclareLocal (return_type, false); + if (!HasReturnLabel){ + ReturnLabel = DefineLabel (); + HasReturnLabel = true; + } + } + + return return_value; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc new file mode 100644 index 0000000000..952437601c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc @@ -0,0 +1,116 @@ +Compiler operation + +The compiler has a number of phases: + +* Parsing. + + Initially the compiler parses all the source files and keeps a + parsed representation in memory. Very syntax error checking + is performed at this point. + + The compiler stores the information in classes whose names + represent the language construct, for example, the "if" + construct is stored in an `If' class. A class is stored in a + `Class'. + +* The TypeManager + + The TypeManager loads all the assemblies that were referenced + by the programmer. The CLR type system is used as our + repository for types defined as well. + + So the same interface that is used to query the types, + properties and flags about system types is the same interface + that we use for our types. + + As we work our way through the code generation and semantic + analysis, new types are entered into the Type system through + the use of System.Reflection.Emit. The TypeManager will + lookup types on both the user defined types and on the system + defined ones. + + So special care has to be used. The order in which we + proceeed from here is important. + +* Base class resolution and type definition. + + Once the parsing has happened, the compiler resolves the + inheritance tree for interfaces. This is done recursively + and we catch recursive interface definitions here. + + After this is done, we continue on with classes. Classes have + can have an optional "parent" inherit from or the implicit + System.Object class (for normal builds, builds with /nostdlib + will allow you to compile class System.Object with no parent). + + At this point we do some error checking and verify that the + inherits/implements section of a class is correct (since we + have previously built the interface inheritance). + + By the time we are done, all classes, structs and interfaces + have been created using System.Reflection.Emit and registered + with the Type Manager. + + This allows us to define fields and resolve argument names for + methods, properties, indexers and events. + +* Field generation + + Fields are generated next, we go through all the type + containers (classes and structs) and enter the fields into + their types. + +* Method, Properties, Indexers and events definitions + + Now all the methods, constructors, properties, indexers and + events are entered. They are only `defined' using + System.Reflection.Emit. No code generation will happen until + everything has been entered into System.Reflection.Emit. + + This is important because to actually generate code we need to + know everything about the environment in which the code is + being generated. + +* Code Generation + + At this point all the definitions have been entered into the + type manager through System.Reflection.Emit. We can now use + System.Reflection to query all the information about the + types. + + Your normal semantic analysis and code generation phase lives + here. + +* Statements + + Most of the statements are handled in the codegen.cs file. + +* Expressions + +* Error reporting + + Always use `Report::Error' or `Report::Warning' methods of Report + class. The actual Report instance is available via local context. + An expression error reporting has to be done during Resolve phase, + except when it's Emit specific (very rare). + + Error reporting should try to use the same codes that the + Microsoft compiler uses (if only so we can track which errors + we handle and which ones we dont). + + If there is an error which is specific to MSC, use negative + numbers, and register the number in mcs/errors/errors.txt + + Try to write a test case for any error that you run into the + code of the compiler if there is none already. + + Put your test case in a file called csNNNN.cs in the + mcs/errors directory, and have the first two lines be: + + // csNNNN.cs: This is the error message + // Line: XXX + // Compiler options: an optional compiler options + + Where `XXX' is the line where the error ocurrs. We will later + use this as a regression test suite for catching errors in the + compiler. diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs new file mode 100644 index 0000000000..965416e79b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs @@ -0,0 +1,200 @@ +// +// complete.cs: Expression that are used for completion suggestions. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2009 Novell, Inc. +// +// Completion* classes derive from ExpressionStatement as this allows +// them to pass through the parser in many conditions that require +// statements even when the expression is incomplete (for example +// completing inside a lambda +// +using System.Collections.Generic; +using System.Linq; + +namespace Mono.CSharp { + + // + // A common base class for Completing expressions, it + // is just a very simple ExpressionStatement + // + public abstract class CompletingExpression : ExpressionStatement + { + public static void AppendResults (List results, string prefix, IEnumerable names) + { + foreach (string name in names) { + if (name == null) + continue; + + if (prefix != null && !name.StartsWith (prefix)) + continue; + + if (results.Contains (name)) + continue; + + if (prefix != null) + results.Add (name.Substring (prefix.Length)); + else + results.Add (name); + } + } + + public override void EmitStatement (EmitContext ec) + { + // Do nothing + } + + public override void Emit (EmitContext ec) + { + // Do nothing + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return null; + } + } + + public class CompletionSimpleName : CompletingExpression { + public string Prefix; + + public CompletionSimpleName (string prefix, Location l) + { + this.loc = l; + this.Prefix = prefix; + } + + protected override Expression DoResolve (ResolveContext ec) + { + var results = new List (); + + AppendResults (results, Prefix, ec.Module.Evaluator.GetVarNames ()); + AppendResults (results, Prefix, ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (Prefix)); + AppendResults (results, Prefix, ec.Module.Evaluator.GetUsingList ()); + + throw new CompletionResult (Prefix, results.ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + } + + public class CompletionMemberAccess : CompletingExpression { + Expression expr; + string partial_name; + TypeArguments targs; + + public CompletionMemberAccess (Expression e, string partial_name, Location l) + { + this.expr = e; + this.loc = l; + this.partial_name = partial_name; + } + + public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l) + { + this.expr = e; + this.loc = l; + this.partial_name = partial_name; + this.targs = targs; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression expr_resolved = expr.Resolve (ec, + ResolveFlags.VariableOrValue | ResolveFlags.Type); + + if (expr_resolved == null) + return null; + + TypeSpec expr_type = expr_resolved.Type; + if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) { + Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type); + return null; + } + + if (targs != null) { + if (!targs.Resolve (ec)) + return null; + } + + var results = new List (); + if (expr_resolved is Namespace){ + Namespace nexpr = expr_resolved as Namespace; + string namespaced_partial; + + if (partial_name == null) + namespaced_partial = nexpr.Name; + else + namespaced_partial = nexpr.Name + "." + partial_name; + +#if false + Console.WriteLine ("Workign with: namespaced partial {0}", namespaced_partial); + foreach (var x in ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial)){ + Console.WriteLine (" {0}", x); + } +#endif + + CompletionSimpleName.AppendResults ( + results, + partial_name, + ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (namespaced_partial)); + } else { + var r = MemberCache.GetCompletitionMembers (ec, expr_type, partial_name).Select (l => l.Name); + AppendResults (results, partial_name, r); + } + + throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CompletionMemberAccess target = (CompletionMemberAccess) t; + + if (targs != null) + target.targs = targs.Clone (); + + target.expr = expr.Clone (clonectx); + } + } + + public class CompletionElementInitializer : CompletingExpression { + string partial_name; + + public CompletionElementInitializer (string partial_name, Location l) + { + this.partial_name = partial_name; + this.loc = l; + } + + protected override Expression DoResolve (ResolveContext ec) + { + var members = MemberCache.GetCompletitionMembers (ec, ec.CurrentInitializerVariable.Type, partial_name); + +// TODO: Does this mean exact match only ? +// if (partial_name != null && results.Count > 0 && result [0] == "") +// throw new CompletionResult ("", new string [] { "=" }); + + var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList (); + if (partial_name != null) { + var temp = new List (); + AppendResults (temp, partial_name, results); + results = temp; + } + + throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + } + +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs new file mode 100644 index 0000000000..0ff7bf81f8 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs @@ -0,0 +1,237 @@ +// +// const.cs: Constant declarations. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001-2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +#if STATIC +using IKVM.Reflection; +#else +using System.Reflection; +#endif + +namespace Mono.CSharp { + + public class Const : FieldBase + { + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + public Const (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, AllowedModifiers, name, attrs) + { + ModFlags |= Modifiers.STATIC; + } + + /// + /// Defines the constant in the @parent + /// + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!member_type.IsConstantCompatible) { + Error_InvalidConstantType (member_type, Location, Report); + } + + FieldAttributes field_attr = FieldAttributes.Static | ModifiersExtensions.FieldAttr (ModFlags); + // Decimals cannot be emitted into the constant blob. So, convert to 'readonly'. + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + field_attr |= FieldAttributes.InitOnly; + } else { + field_attr |= FieldAttributes.Literal; + } + + FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), field_attr); + spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer); + + Parent.MemberCache.AddMember (spec); + + if ((field_attr & FieldAttributes.InitOnly) != 0) + Parent.PartialContainer.RegisterFieldForInitialization (this, + new FieldInitializer (spec, initializer, this)); + + if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Constants.IndexOf (this); + foreach (var d in declarators) { + var c = new Const (Parent, t, ModFlags & ~Modifiers.STATIC, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + c.initializer = d.Initializer; + ((ConstInitializer) c.initializer).Name = d.Name.Value; + Parent.PartialContainer.Constants.Insert (++index, c); + } + } + + return true; + } + + public void DefineValue () + { + var rc = new ResolveContext (this); + ((ConstSpec) spec).GetConstant (rc); + } + + /// + /// Emits the field value by evaluating the expression + /// + public override void Emit () + { + var c = ((ConstSpec) spec).Value as Constant; + if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + Module.PredefinedAttributes.DecimalConstant.EmitAttribute (FieldBuilder, (decimal) c.GetValue (), c.Location); + } else { + FieldBuilder.SetConstant (c.GetValue ()); + } + + base.Emit (); + } + + public static void Error_InvalidConstantType (TypeSpec t, Location loc, Report Report) + { + if (t.IsGenericParameter) { + Report.Error (1959, loc, + "Type parameter `{0}' cannot be declared const", TypeManager.CSharpName (t)); + } else { + Report.Error (283, loc, + "The type `{0}' cannot be declared const", TypeManager.CSharpName (t)); + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class ConstSpec : FieldSpec + { + Expression value; + + public ConstSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo fi, Modifiers mod, Expression value) + : base (declaringType, definition, memberType, fi, mod) + { + this.value = value; + } + + // + // This expresion is guarantee to be a constant at emit phase only + // + public Expression Value { + get { + return value; + } + } + + // + // For compiled constants we have to resolve the value as there could be constant dependecies. This + // is needed for imported constants too to get the right context type + // + public Constant GetConstant (ResolveContext rc) + { + if (value.eclass != ExprClass.Value) + value = value.Resolve (rc); + + return (Constant) value; + } + } + + public class ConstInitializer : ShimExpression + { + bool in_transit; + readonly FieldBase field; + + public ConstInitializer (FieldBase field, Expression value, Location loc) + : base (value) + { + this.loc = loc; + this.field = field; + } + + public string Name { get; set; } + + protected override Expression DoResolve (ResolveContext unused) + { + if (type != null) + return expr; + + var opt = ResolveContext.Options.ConstantScope; + if (field is EnumMember) + opt |= ResolveContext.Options.EnumScope; + + // + // Use a context in which the constant was declared and + // not the one in which is referenced + // + var rc = new ResolveContext (field, opt); + expr = DoResolveInitializer (rc); + type = expr.Type; + + return expr; + } + + protected virtual Expression DoResolveInitializer (ResolveContext rc) + { + if (in_transit) { + field.Compiler.Report.Error (110, expr.Location, + "The evaluation of the constant value for `{0}' involves a circular definition", + GetSignatureForError ()); + + expr = null; + } else { + in_transit = true; + expr = expr.Resolve (rc); + } + + in_transit = false; + + if (expr != null) { + Constant c = expr as Constant; + if (c != null) + c = field.ConvertInitializer (rc, c); + + if (c == null) { + if (TypeSpec.IsReferenceType (field.MemberType)) + Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, expr.Location, GetSignatureForError ()); + else if (!(expr is Constant)) + Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ()); + else + expr.Error_ValueCannotBeConverted (rc, expr.Location, field.MemberType, false); + } + + expr = c; + } + + if (expr == null) { + expr = New.Constantify (field.MemberType, Location); + if (expr == null) + expr = Constant.CreateConstantFromValue (field.MemberType, null, Location); + expr = expr.Resolve (rc); + } + + return expr; + } + + public override string GetSignatureForError () + { + if (Name == null) + return field.GetSignatureForError (); + + return field.Parent.GetSignatureForError () + "." + Name; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs new file mode 100644 index 0000000000..2848e46a7e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs @@ -0,0 +1,2232 @@ +// +// constant.cs: Constants. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001-2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Globalization; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Base class for constants and literals. + /// + public abstract class Constant : Expression + { + static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; + + protected Constant (Location loc) + { + this.loc = loc; + } + + override public string ToString () + { + return this.GetType ().Name + " (" + GetValueAsLiteral () + ")"; + } + + /// + /// This is used to obtain the actual value of the literal + /// cast into an object. + /// + public abstract object GetValue (); + + public abstract long GetValueAsLong (); + + public abstract string GetValueAsLiteral (); + +#if !STATIC + // + // Returns an object value which is typed to contant type + // + public virtual object GetTypedValue () + { + return GetValue (); + } +#endif + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + if (!expl && IsLiteral && + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) && + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) { + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + GetValueAsLiteral (), TypeManager.CSharpName (target)); + } else { + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + } + + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) + { + Constant c = ConvertImplicitly (type); + if (c == null) + Error_ValueCannotBeConverted (ec, loc, type, false); + + return c; + } + + public virtual Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) + return this; + + if (Convert.ImplicitNumericConversion (this, type) == null) + return null; + + bool fail; + object constant_value = ChangeType (GetValue (), type, out fail); + if (fail){ + // + // We should always catch the error before this is ever + // reached, by calling Convert.ImplicitStandardConversionExists + // + throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'", + TypeManager.CSharpName (Type), TypeManager.CSharpName (type)); + } + + return CreateConstant (type, constant_value, loc); + } + + // + // Returns a constant instance based on Type + // + public static Constant CreateConstant (TypeSpec t, object v, Location loc) + { + return CreateConstantFromValue (t, v, loc); + } + + public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return new IntConstant (t, (int) v, loc); + case BuiltinTypeSpec.Type.String: + return new StringConstant (t, (string) v, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (t, (uint) v, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (t, (long) v, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (t, (ulong) v, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (t, (float) v, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (t, (double) v, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (t, (short) v, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (t, (ushort) v, loc); + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (t, (sbyte) v, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (t, (byte) v, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (t, (char) v, loc); + case BuiltinTypeSpec.Type.Bool: + return new BoolConstant (t, (bool) v, loc); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (t, (decimal) v, loc); + } + + if (t.IsEnum) { + var real_type = EnumSpec.GetUnderlyingType (t); + return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); + } + + if (v == null) { + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); + + if (TypeSpec.IsReferenceType (t)) + return new NullConstant (t, loc); + } + + throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", + v, TypeManager.CSharpName (t)); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + /// + /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type. + /// It throws OverflowException + /// + // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS + public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type); + + // This is a custom version of Convert.ChangeType() which works + // with the TypeBuilder defined types when compiling corlib. + static object ChangeType (object value, TypeSpec targetType, out bool error) + { + IConvertible convert_value = value as IConvertible; + + if (convert_value == null) { + error = true; + return null; + } + + // + // We cannot rely on build-in type conversions as they are + // more limited than what C# supports. + // See char -> float/decimal/double conversion + // + error = false; + try { + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + return convert_value.ToBoolean (nfi); + case BuiltinTypeSpec.Type.Byte: + return convert_value.ToByte (nfi); + case BuiltinTypeSpec.Type.Char: + return convert_value.ToChar (nfi); + case BuiltinTypeSpec.Type.Short: + return convert_value.ToInt16 (nfi); + case BuiltinTypeSpec.Type.Int: + return convert_value.ToInt32 (nfi); + case BuiltinTypeSpec.Type.Long: + return convert_value.ToInt64 (nfi); + case BuiltinTypeSpec.Type.SByte: + return convert_value.ToSByte (nfi); + case BuiltinTypeSpec.Type.Decimal: + if (convert_value.GetType () == typeof (char)) + return (decimal) convert_value.ToInt32 (nfi); + return convert_value.ToDecimal (nfi); + case BuiltinTypeSpec.Type.Double: + if (convert_value.GetType () == typeof (char)) + return (double) convert_value.ToInt32 (nfi); + return convert_value.ToDouble (nfi); + case BuiltinTypeSpec.Type.Float: + if (convert_value.GetType () == typeof (char)) + return (float) convert_value.ToInt32 (nfi); + return convert_value.ToSingle (nfi); + case BuiltinTypeSpec.Type.String: + return convert_value.ToString (nfi); + case BuiltinTypeSpec.Type.UShort: + return convert_value.ToUInt16 (nfi); + case BuiltinTypeSpec.Type.UInt: + return convert_value.ToUInt32 (nfi); + case BuiltinTypeSpec.Type.ULong: + return convert_value.ToUInt64 (nfi); + case BuiltinTypeSpec.Type.Object: + return value; + } + } catch { + } + + error = true; + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + return this; + } + + /// + /// Attempts to do a compile-time folding of a constant cast. + /// + public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc) + { + try { + return TryReduce (ec, target_type); + } + catch (OverflowException) { + if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + ec.Report.Error (221, loc, + "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", + GetValueAsLiteral (), target_type.GetSignatureForError ()); + } else { + Error_ValueCannotBeConverted (ec, loc, target_type, false); + } + + return New.Constantify (target_type, loc); + } + } + + Constant TryReduce (ResolveContext ec, TypeSpec target_type) + { + if (Type == target_type) + return this; + + Constant c; + if (TypeManager.IsEnumType (target_type)) { + c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); + if (c == null) + return null; + + return new EnumConstant (c, target_type); + } + + return ConvertExplicitly (ec.ConstantCheckState, target_type); + } + + /// + /// Need to pass type as the constant can require a boxing + /// and in such case no optimization is possible + /// + public bool IsDefaultInitializer (TypeSpec type) + { + if (type == Type) + return IsDefaultValue; + + return this is NullLiteral; + } + + public abstract bool IsDefaultValue { + get; + } + + public abstract bool IsNegative { + get; + } + + // + // When constant is declared as literal + // + public virtual bool IsLiteral { + get { return false; } + } + + public virtual bool IsOneInteger { + get { return false; } + } + + // + // Returns true iff 1) the stack type of this is one of Object, + // int32, int64 and 2) this == 0 or this == null. + // + public virtual bool IsZeroInteger { + get { return false; } + } + + public override void EmitSideEffect (EmitContext ec) + { + // do nothing + } + + public sealed override Expression Clone (CloneContext clonectx) + { + // No cloning is not needed for constants + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + throw new NotSupportedException ("should not be reached"); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ()); +#endif + } + + public new bool Resolve (ResolveContext rc) + { + // It exists only as hint not to call Resolve on constants + return true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public abstract class IntegralConstant : Constant + { + protected IntegralConstant (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + try { + ConvertExplicitly (true, target); + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + catch + { + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + GetValue ().ToString (), TypeManager.CSharpName (target)); + } + } + + public override string GetValueAsLiteral () + { + return GetValue ().ToString (); + } + + public abstract Constant Increment (); + } + + public class BoolConstant : Constant { + public readonly bool Value; + + public BoolConstant (BuiltinTypes types, bool val, Location loc) + : this (types.Bool, val, loc) + { + } + + public BoolConstant (TypeSpec type, bool val, Location loc) + : base (loc) + { + eclass = ExprClass.Value; + this.type = type; + + Value = val; + } + + public override object GetValue () + { + return (object) Value; + } + + public override string GetValueAsLiteral () + { + return Value ? "true" : "false"; + } + + public override long GetValueAsLong () + { + return Value ? 1 : 0; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + if (Value) + ec.Emit (OpCodes.Ldc_I4_1); + else + ec.Emit (OpCodes.Ldc_I4_0); + } + + public override bool IsDefaultValue { + get { + return !Value; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == false; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + return null; + } + + } + + public class ByteConstant : IntegralConstant + { + public readonly byte Value; + + public ByteConstant (BuiltinTypes types, byte v, Location loc) + : this (types.Byte, v, loc) + { + } + + public ByteConstant (TypeSpec type, byte v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new ByteConstant (type, checked ((byte)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context){ + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class CharConstant : Constant { + public readonly char Value; + + public CharConstant (BuiltinTypes types, char v, Location loc) + : this (types.Char, v, loc) + { + } + + public CharConstant (TypeSpec type, char v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode ((ushort) Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + static string descape (char c) + { + switch (c){ + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\n': + return "\\n"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + case '\r': + return "\\r"; + case '\\': + return "\\\\"; + case '\f': + return "\\f"; + case '\0': + return "\\0"; + case '"': + return "\\\""; + case '\'': + return "\\\'"; + } + return c.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return "\"" + descape (Value) + "\""; + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == '\0'; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class SByteConstant : IntegralConstant + { + public readonly sbyte Value; + + public SByteConstant (BuiltinTypes types, sbyte v, Location loc) + : this (types.SByte, v, loc) + { + } + + public SByteConstant (TypeSpec type, sbyte v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new SByteConstant (type, checked((sbyte)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class ShortConstant : IntegralConstant { + public readonly short Value; + + public ShortConstant (BuiltinTypes types, short v, Location loc) + : this (types.Short, v, loc) + { + } + + public ShortConstant (TypeSpec type, short v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new ShortConstant (type, checked((short)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value < 0) + throw new OverflowException (); + + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class UShortConstant : IntegralConstant + { + public readonly ushort Value; + + public UShortConstant (BuiltinTypes types, ushort v, Location loc) + : this (types.UShort, v, loc) + { + } + + public UShortConstant (TypeSpec type, ushort v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new UShortConstant (type, checked((ushort)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + } + + public class IntConstant : IntegralConstant + { + public readonly int Value; + + public IntConstant (BuiltinTypes types, int v, Location loc) + : this (types.Int, v, loc) + { + } + + public IntConstant (TypeSpec type, int v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new IntConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < Int16.MinValue || Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < UInt32.MinValue) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) + return this; + + Constant c = TryImplicitIntConversion (type); + if (c != null) + return c; //.Resolve (rc); + + return base.ConvertImplicitly (type); + } + + /// + /// Attempts to perform an implicit constant conversion of the IntConstant + /// into a different data type using casts (See Implicit Constant + /// Expression Conversions) + /// + Constant TryImplicitIntConversion (TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (Value >= SByte.MinValue && Value <= SByte.MaxValue) + return new SByteConstant (target_type, (sbyte) Value, loc); + break; + case BuiltinTypeSpec.Type.Byte: + if (Value >= Byte.MinValue && Value <= Byte.MaxValue) + return new ByteConstant (target_type, (byte) Value, loc); + break; + case BuiltinTypeSpec.Type.Short: + if (Value >= Int16.MinValue && Value <= Int16.MaxValue) + return new ShortConstant (target_type, (short) Value, loc); + break; + case BuiltinTypeSpec.Type.UShort: + if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue) + return new UShortConstant (target_type, (ushort) Value, loc); + break; + case BuiltinTypeSpec.Type.UInt: + if (Value >= 0) + return new UIntConstant (target_type, (uint) Value, loc); + break; + case BuiltinTypeSpec.Type.ULong: + // + // we can optimize this case: a positive int32 + // always fits on a uint64. But we need an opcode + // to do it. + // + if (Value >= 0) + return new ULongConstant (target_type, (ulong) Value, loc); + break; + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + } + + return null; + } + } + + public class UIntConstant : IntegralConstant { + public readonly uint Value; + + public UIntConstant (BuiltinTypes types, uint v, Location loc) + : this (types.UInt, v, loc) + { + } + + public UIntConstant (TypeSpec type, uint v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (unchecked ((int) Value)); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new UIntConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < 0 || Value > byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value > Int32.MaxValue) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class LongConstant : IntegralConstant { + public readonly long Value; + + public LongConstant (BuiltinTypes types, long v, Location loc) + : this (types.Long, v, loc) + { + } + + public LongConstant (TypeSpec type, long v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitLong (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new LongConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < Int16.MinValue || Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < Int32.MinValue || Value > Int32.MaxValue) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < UInt32.MinValue || Value > UInt32.MaxValue) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + return new ULongConstant (type, (ulong) Value, loc); + } + + return base.ConvertImplicitly (type); + } + } + + public class ULongConstant : IntegralConstant { + public readonly ulong Value; + + public ULongConstant (BuiltinTypes types, ulong v, Location loc) + : this (types.ULong, v, loc) + { + } + + public ULongConstant (TypeSpec type, ulong v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitLong (unchecked ((long) Value)); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return (long) Value; + } + + public override Constant Increment () + { + return new ULongConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context && Value > Byte.MaxValue) + throw new OverflowException (); + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context && Value > ((ulong) SByte.MaxValue)) + throw new OverflowException (); + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context && Value > ((ulong) Int16.MaxValue)) + throw new OverflowException (); + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value > UInt16.MaxValue) + throw new OverflowException (); + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context && Value > UInt32.MaxValue) + throw new OverflowException (); + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value > UInt32.MaxValue) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context && Value > Int64.MaxValue) + throw new OverflowException (); + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context && Value > Char.MaxValue) + throw new OverflowException (); + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class FloatConstant : Constant { + public readonly float Value; + + public FloatConstant (BuiltinTypes types, float v, Location loc) + : this (types.Float, v, loc) + { + } + + public FloatConstant (TypeSpec type, float v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_R4, Value); + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class DoubleConstant : Constant + { + public readonly double Value; + + public DoubleConstant (BuiltinTypes types, double v, Location loc) + : this (types.Double, v, loc) + { + } + + public DoubleConstant (TypeSpec type, double v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_R8, Value); + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class DecimalConstant : Constant { + public readonly decimal Value; + + public DecimalConstant (BuiltinTypes types, decimal d, Location loc) + : this (types.Decimal, d, loc) + { + } + + public DecimalConstant (TypeSpec type, decimal d, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = d; + } + + public override void Emit (EmitContext ec) + { + MethodSpec m; + + int [] words = decimal.GetBits (Value); + int power = (words [3] >> 16) & 0xff; + + if (power == 0) { + if (Value <= int.MaxValue && Value >= int.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); + if (m == null) { + return; + } + + ec.EmitInt ((int) Value); + ec.Emit (OpCodes.Newobj, m); + return; + } + + if (Value <= long.MaxValue && Value >= long.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); + if (m == null) { + return; + } + + ec.EmitLong ((long) Value); + ec.Emit (OpCodes.Newobj, m); + return; + } + } + + ec.EmitInt (words [0]); + ec.EmitInt (words [1]); + ec.EmitInt (words [2]); + + // sign + ec.EmitInt (words [3] >> 31); + + // power + ec.EmitInt (power); + + m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); + if (m != null) { + ec.Emit (OpCodes.Newobj, m); + } + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (target_type, (sbyte) Value, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (target_type, (byte) Value, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, loc); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + } + + return null; + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString () + "M"; + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + } + + public class StringConstant : Constant { + public readonly string Value; + + public StringConstant (BuiltinTypes types, string s, Location loc) + : this (types.String, s, loc) + { + } + + public StringConstant (TypeSpec type, string s, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = s; + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + // FIXME: Escape the string. + return "\"" + Value + "\""; + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override void Emit (EmitContext ec) + { + if (Value == null) { + ec.Emit (OpCodes.Ldnull); + return; + } + + // + // Use string.Empty for both literals and constants even if + // it's not allowed at language level + // + if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) { + var string_type = ec.BuiltinTypes.String; + if (ec.CurrentType != string_type) { + var m = ec.Module.PredefinedMembers.StringEmpty.Get (); + if (m != null) { + ec.Emit (OpCodes.Ldsfld, m); + return; + } + } + } + + ec.Emit (OpCodes.Ldstr, Value); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // cast to object + if (type != targetType) + enc.Encode (type); + + enc.Encode (Value); + } + + public override bool IsDefaultValue { + get { + return Value == null; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsNull { + get { + return IsDefaultValue; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + return null; + } + } + + // + // Null constant can have its own type, think of `default (Foo)' + // + public class NullConstant : Constant + { + public NullConstant (TypeSpec type, Location loc) + : base (loc) + { + eclass = ExprClass.Value; + this.type = type; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) { + // Optimized version, also avoids referencing literal internal type + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + return base.CreateExpressionTree (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Object: + // Type it as string cast + enc.Encode (rc.Module.Compiler.BuiltinTypes.String); + goto case BuiltinTypeSpec.Type.String; + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Type: + enc.Encode (byte.MaxValue); + return; + default: + var ac = targetType as ArrayContainer; + if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) { + enc.Encode (uint.MaxValue); + return; + } + + break; + } + + base.EncodeAttributeValue (rc, enc, targetType); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldnull); + + // Only to make verifier happy + if (type.IsGenericParameter) + ec.Emit (OpCodes.Unbox_Any, type); + } + + public override string ExprClassName { + get { + return GetSignatureForError (); + } + } + + public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType) + { + if (targetType.IsPointer) { + if (IsLiteral || this is NullPointer) + return new NullPointer (targetType, loc); + + return null; + } + + // Exlude internal compiler types + if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic) + return null; + + if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType)) + return null; + + if (TypeSpec.IsReferenceType (targetType)) + return new NullConstant (targetType, loc); + + if (targetType.IsNullableType) + return Nullable.LiftedNull.Create (targetType, loc); + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec targetType) + { + return ConvertExplicitly (false, targetType); + } + + public override string GetSignatureForError () + { + return "null"; + } + + public override object GetValue () + { + return null; + } + + public override string GetValueAsLiteral () + { + return GetSignatureForError (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { return true; } + } + + public override bool IsNegative { + get { return false; } + } + + public override bool IsNull { + get { return true; } + } + + public override bool IsZeroInteger { + get { return true; } + } + } + + + // + // A null constant in a pointer context + // + class NullPointer : NullConstant + { + public NullPointer (TypeSpec type, Location loc) + : base (type, loc) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + // + // Emits null pointer + // + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Conv_U); + } + } + + /// + /// The value is constant, but when emitted has a side effect. This is + /// used by BitwiseAnd to ensure that the second expression is invoked + /// regardless of the value of the left side. + /// + public class SideEffectConstant : Constant { + public readonly Constant value; + Expression side_effect; + + public SideEffectConstant (Constant value, Expression side_effect, Location loc) + : base (loc) + { + this.value = value; + type = value.Type; + eclass = ExprClass.Value; + + while (side_effect is SideEffectConstant) + side_effect = ((SideEffectConstant) side_effect).side_effect; + this.side_effect = side_effect; + } + + public override object GetValue () + { + return value.GetValue (); + } + + public override string GetValueAsLiteral () + { + return value.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return value.GetValueAsLong (); + } + + public override void Emit (EmitContext ec) + { + side_effect.EmitSideEffect (ec); + value.Emit (ec); + } + + public override void EmitSideEffect (EmitContext ec) + { + side_effect.EmitSideEffect (ec); + value.EmitSideEffect (ec); + } + + public override bool IsDefaultValue { + get { return value.IsDefaultValue; } + } + + public override bool IsNegative { + get { return value.IsNegative; } + } + + public override bool IsZeroInteger { + get { return value.IsZeroInteger; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + Constant new_value = value.ConvertExplicitly (in_checked_context, target_type); + if (new_value == null) + return null; + + var c = new SideEffectConstant (new_value, side_effect, new_value.Location); + c.type = target_type; + c.eclass = eclass; + return c; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs new file mode 100644 index 0000000000..316968454e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs @@ -0,0 +1,741 @@ +// +// context.cs: Various compiler contexts. +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// Miguel de Icaza (miguel@ximian.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004-2009 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.IO; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public enum LookupMode + { + Normal = 0, + Probing = 1, + IgnoreAccessibility = 2 + } + + // + // Implemented by elements which can act as independent contexts + // during resolve phase. Used mostly for lookups. + // + public interface IMemberContext : IModuleContext + { + // + // A scope type context, it can be inflated for generic types + // + TypeSpec CurrentType { get; } + + // + // A scope type parameters either VAR or MVAR + // + TypeParameter[] CurrentTypeParameters { get; } + + // + // A member definition of the context. For partial types definition use + // CurrentTypeDefinition.PartialContainer otherwise the context is local + // + // TODO: Obsolete it in this context, dynamic context cannot guarantee sensible value + // + MemberCore CurrentMemberDefinition { get; } + + bool IsObsolete { get; } + bool IsUnsafe { get; } + bool IsStatic { get; } + + string GetSignatureForError (); + + IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope); + FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc); + FullNamedExpression LookupNamespaceAlias (string name); + } + + public interface IModuleContext + { + ModuleContainer Module { get; } + } + + // + // Block or statement resolving context + // + public class BlockContext : ResolveContext + { + FlowBranching current_flow_branching; + + TypeSpec return_type; + + /// + /// The location where return has to jump to return the + /// value + /// + public Label ReturnLabel; // TODO: It's emit dependant + + /// + /// If we already defined the ReturnLabel + /// + public bool HasReturnLabel; + + public int FlowOffset; + + public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType) + : base (mc) + { + if (returnType == null) + throw new ArgumentNullException ("returnType"); + + this.return_type = returnType; + + // TODO: check for null value + CurrentBlock = block; + } + + public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType) + : this (rc.MemberContext, block, returnType) + { + if (rc.IsUnsafe) + flags |= ResolveContext.Options.UnsafeScope; + + if (rc.HasSet (ResolveContext.Options.CheckedScope)) + flags |= ResolveContext.Options.CheckedScope; + } + + public override FlowBranching CurrentBranching { + get { return current_flow_branching; } + } + + // + // Starts a new code branching. This inherits the state of all local + // variables and parameters from the current branching. + // + public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc) + { + current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc); + return current_flow_branching; + } + + // + // Starts a new code branching for block `block'. + // + public FlowBranching StartFlowBranching (Block block) + { + Set (Options.DoFlowAnalysis); + + current_flow_branching = FlowBranching.CreateBranching ( + CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation); + return current_flow_branching; + } + + public FlowBranchingTryCatch StartFlowBranching (TryCatch stmt) + { + FlowBranchingTryCatch branching = new FlowBranchingTryCatch (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingException StartFlowBranching (ExceptionStatement stmt) + { + FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt) + { + FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingIterator StartFlowBranching (StateMachineInitializer iterator, FlowBranching parent) + { + FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent) + { + FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt); + current_flow_branching = branching; + return branching; + } + + // + // Ends a code branching. Merges the state of locals and parameters + // from all the children of the ending branching. + // + public bool EndFlowBranching () + { + FlowBranching old = current_flow_branching; + current_flow_branching = current_flow_branching.Parent; + + FlowBranching.UsageVector vector = current_flow_branching.MergeChild (old); + return vector.IsUnreachable; + } + + // + // Kills the current code branching. This throws away any changed state + // information and should only be used in case of an error. + // + // FIXME: this is evil + public void KillFlowBranching () + { + current_flow_branching = current_flow_branching.Parent; + } + + // + // This method is used during the Resolution phase to flag the + // need to define the ReturnLabel + // + public void NeedReturnLabel () + { + if (!HasReturnLabel) + HasReturnLabel = true; + } + + public TypeSpec ReturnType { + get { return return_type; } + } + } + + // + // Expression resolving context + // + public class ResolveContext : IMemberContext + { + [Flags] + public enum Options + { + /// + /// This flag tracks the `checked' state of the compilation, + /// it controls whether we should generate code that does overflow + /// checking, or if we generate code that ignores overflows. + /// + /// The default setting comes from the command line option to generate + /// checked or unchecked code plus any source code changes using the + /// checked/unchecked statements or expressions. Contrast this with + /// the ConstantCheckState flag. + /// + CheckedScope = 1 << 0, + + /// + /// The constant check state is always set to `true' and cant be changed + /// from the command line. The source code can change this setting with + /// the `checked' and `unchecked' statements and expressions. + /// + ConstantCheckState = 1 << 1, + + AllCheckStateFlags = CheckedScope | ConstantCheckState, + + // + // unsafe { ... } scope + // + UnsafeScope = 1 << 2, + CatchScope = 1 << 3, + FinallyScope = 1 << 4, + FieldInitializerScope = 1 << 5, + CompoundAssignmentScope = 1 << 6, + FixedInitializerScope = 1 << 7, + BaseInitializer = 1 << 8, + + // + // Inside an enum definition, we do not resolve enumeration values + // to their enumerations, but rather to the underlying type/value + // This is so EnumVal + EnumValB can be evaluated. + // + // There is no "E operator + (E x, E y)", so during an enum evaluation + // we relax the rules + // + EnumScope = 1 << 9, + + ConstantScope = 1 << 10, + + ConstructorScope = 1 << 11, + + UsingInitializerScope = 1 << 12, + + LockScope = 1 << 13, + + /// + /// Whether control flow analysis is enabled + /// + DoFlowAnalysis = 1 << 20, + + /// + /// Whether control flow analysis is disabled on structs + /// (only meaningful when DoFlowAnalysis is set) + /// + OmitStructFlowAnalysis = 1 << 21, + + /// + /// Indicates the current context is in probing mode, no errors are reported. + /// + ProbingMode = 1 << 22, + + // + // Return and ContextualReturn statements will set the ReturnType + // value based on the expression types of each return statement + // instead of the method return type which is initially null. + // + InferReturnType = 1 << 23, + + OmitDebuggingInfo = 1 << 24, + + ExpressionTreeConversion = 1 << 25, + + InvokeSpecialName = 1 << 26 + } + + // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements + // it's public so that we can use a struct at the callsite + public struct FlagsHandle : IDisposable + { + ResolveContext ec; + readonly Options invmask, oldval; + + public FlagsHandle (ResolveContext ec, Options flagsToSet) + : this (ec, flagsToSet, flagsToSet) + { + } + + internal FlagsHandle (ResolveContext ec, Options mask, Options val) + { + this.ec = ec; + invmask = ~mask; + oldval = ec.flags & mask; + ec.flags = (ec.flags & invmask) | (val & mask); + +// if ((mask & Options.ProbingMode) != 0) +// ec.Report.DisableReporting (); + } + + public void Dispose () + { +// if ((invmask & Options.ProbingMode) == 0) +// ec.Report.EnableReporting (); + + ec.flags = (ec.flags & invmask) | oldval; + } + } + + protected Options flags; + + // + // Whether we are inside an anonymous method. + // + public AnonymousExpression CurrentAnonymousMethod; + + // + // Holds a varible used during collection or object initialization. + // + public Expression CurrentInitializerVariable; + + public Block CurrentBlock; + + public readonly IMemberContext MemberContext; + + /// + /// If this is non-null, points to the current switch statement + /// + public Switch Switch; + + public ResolveContext (IMemberContext mc) + { + if (mc == null) + throw new ArgumentNullException (); + + MemberContext = mc; + + // + // The default setting comes from the command line option + // + if (mc.Module.Compiler.Settings.Checked) + flags |= Options.CheckedScope; + + // + // The constant check state is always set to true + // + flags |= Options.ConstantCheckState; + } + + public ResolveContext (IMemberContext mc, Options options) + : this (mc) + { + flags |= options; + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return MemberContext.Module.Compiler.BuiltinTypes; + } + } + + public virtual ExplicitBlock ConstructorBlock { + get { + return CurrentBlock.Explicit; + } + } + + public virtual FlowBranching CurrentBranching { + get { return null; } + } + + // + // The current iterator + // + public Iterator CurrentIterator { + get { return CurrentAnonymousMethod as Iterator; } + } + + public TypeSpec CurrentType { + get { return MemberContext.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return MemberContext.CurrentTypeParameters; } + } + + public MemberCore CurrentMemberDefinition { + get { return MemberContext.CurrentMemberDefinition; } + } + + public bool ConstantCheckState { + get { return (flags & Options.ConstantCheckState) != 0; } + } + + public bool DoFlowAnalysis { + get { return (flags & Options.DoFlowAnalysis) != 0; } + } + + public bool IsInProbingMode { + get { + return (flags & Options.ProbingMode) != 0; + } + } + + public bool IsObsolete { + get { + // Disables obsolete checks when probing is on + return MemberContext.IsObsolete; + } + } + + public bool IsStatic { + get { + return MemberContext.IsStatic; + } + } + + public bool IsUnsafe { + get { + return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe; + } + } + + public bool IsRuntimeBinder { + get { + return Module.Compiler.IsRuntimeBinder; + } + } + + public bool IsVariableCapturingRequired { + get { + return !IsInProbingMode && (CurrentBranching == null || !CurrentBranching.CurrentUsageVector.IsUnreachable); + } + } + + public ModuleContainer Module { + get { + return MemberContext.Module; + } + } + + public bool OmitStructFlowAnalysis { + get { return (flags & Options.OmitStructFlowAnalysis) != 0; } + } + + public Report Report { + get { + return Module.Compiler.Report; + } + } + + #endregion + + public bool MustCaptureVariable (INamedBlockVariable local) + { + if (CurrentAnonymousMethod == null) + return false; + + // FIXME: IsIterator is too aggressive, we should capture only if child + // block contains yield + if (CurrentAnonymousMethod.IsIterator) + return true; + + return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original; + } + + public bool HasSet (Options options) + { + return (this.flags & options) == options; + } + + public bool HasAny (Options options) + { + return (this.flags & options) != 0; + } + + + // Temporarily set all the given flags to the given value. Should be used in an 'using' statement + public FlagsHandle Set (Options options) + { + return new FlagsHandle (this, options); + } + + public FlagsHandle With (Options options, bool enable) + { + return new FlagsHandle (this, options, enable ? options : 0); + } + + #region IMemberContext Members + + public string GetSignatureForError () + { + return MemberContext.GetSignatureForError (); + } + + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return MemberContext.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + return MemberContext.LookupNamespaceOrType (name, arity, mode, loc); + } + + public FullNamedExpression LookupNamespaceAlias (string name) + { + return MemberContext.LookupNamespaceAlias (name); + } + + #endregion + } + + // + // This class is used during the Statement.Clone operation + // to remap objects that have been cloned. + // + // Since blocks are cloned by Block.Clone, we need a way for + // expressions that must reference the block to be cloned + // pointing to the new cloned block. + // + public class CloneContext + { + Dictionary block_map = new Dictionary (); + + public void AddBlockMap (Block from, Block to) + { + block_map.Add (from, to); + } + + public Block LookupBlock (Block from) + { + Block result; + if (!block_map.TryGetValue (from, out result)) { + result = (Block) from.Clone (this); + } + + return result; + } + + /// + /// Remaps block to cloned copy if one exists. + /// + public Block RemapBlockCopy (Block from) + { + Block mapped_to; + if (!block_map.TryGetValue (from, out mapped_to)) + return from; + + return mapped_to; + } + } + + // + // Main compiler context + // + public class CompilerContext + { + static readonly TimeReporter DisabledTimeReporter = new TimeReporter (false); + + readonly Report report; + readonly BuiltinTypes builtin_types; + readonly CompilerSettings settings; + + Dictionary all_source_files; + + public CompilerContext (CompilerSettings settings, Report report) + { + this.settings = settings; + this.report = report; + this.builtin_types = new BuiltinTypes (); + this.TimeReporter = DisabledTimeReporter; + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return builtin_types; + } + } + + // Used for special handling of runtime dynamic context mostly + // by error reporting but also by member accessibility checks + public bool IsRuntimeBinder { + get; set; + } + + public Report Report { + get { + return report; + } + } + + public CompilerSettings Settings { + get { + return settings; + } + } + + public List SourceFiles { + get { + return settings.SourceFiles; + } + } + + internal TimeReporter TimeReporter { + get; set; + } + + #endregion + + // + // This is used when we encounter a #line preprocessing directive during parsing + // to register additional source file names + // + public SourceFile LookupFile (CompilationSourceFile comp_unit, string name) + { + if (all_source_files == null) { + all_source_files = new Dictionary (); + foreach (var source in SourceFiles) + all_source_files[source.FullPathName] = source; + } + + string path; + if (!Path.IsPathRooted (name)) { + string root = Path.GetDirectoryName (comp_unit.FullPathName); + path = Path.Combine (root, name); + } else + path = name; + + SourceFile retval; + if (all_source_files.TryGetValue (path, out retval)) + return retval; + + retval = Location.AddFile (name, path); + all_source_files.Add (path, retval); + return retval; + } + } + + // + // Generic code emitter context + // + public class BuilderContext + { + [Flags] + public enum Options + { + /// + /// This flag tracks the `checked' state of the compilation, + /// it controls whether we should generate code that does overflow + /// checking, or if we generate code that ignores overflows. + /// + /// The default setting comes from the command line option to generate + /// checked or unchecked code plus any source code changes using the + /// checked/unchecked statements or expressions. Contrast this with + /// the ConstantCheckState flag. + /// + CheckedScope = 1 << 0, + + /// + /// The constant check state is always set to `true' and cant be changed + /// from the command line. The source code can change this setting with + /// the `checked' and `unchecked' statements and expressions. + /// + ConstantCheckState = 1 << 1, + + AllCheckStateFlags = CheckedScope | ConstantCheckState, + + OmitDebugInfo = 1 << 2, + + ConstructorScope = 1 << 3 + } + + // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements + // it's public so that we can use a struct at the callsite + public struct FlagsHandle : IDisposable + { + BuilderContext ec; + readonly Options invmask, oldval; + + public FlagsHandle (BuilderContext ec, Options flagsToSet) + : this (ec, flagsToSet, flagsToSet) + { + } + + internal FlagsHandle (BuilderContext ec, Options mask, Options val) + { + this.ec = ec; + invmask = ~mask; + oldval = ec.flags & mask; + ec.flags = (ec.flags & invmask) | (val & mask); + } + + public void Dispose () + { + ec.flags = (ec.flags & invmask) | oldval; + } + } + + Options flags; + + public bool HasSet (Options options) + { + return (this.flags & options) == options; + } + + // Temporarily set all the given flags to the given value. Should be used in an 'using' statement + public FlagsHandle With (Options options, bool enable) + { + return new FlagsHandle (this, options, enable ? options : 0); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs new file mode 100644 index 0000000000..020c842755 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs @@ -0,0 +1,2150 @@ +// +// conversion.cs: various routines for implementing conversions. +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + // + // A container class for all the conversion operations + // + static class Convert + { + // + // From a one-dimensional array-type S[] to System.Collections.IList and base + // interfaces of this interface, provided there is an implicit reference conversion + // from S to T. + // + static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit) + { + if (array.Rank != 1 || !list.IsGenericIterateInterface) + return false; + + var arg_type = list.TypeArguments[0]; + if (array.Element == arg_type) + return true; + + // + // Reject conversion from T[] to IList even if T has U dependency + // + if (arg_type.IsGenericParameter) + return false; + + if (isExplicit) + return ExplicitReferenceConversionExists (array.Element, arg_type); + + return ImplicitReferenceConversionExists (array.Element, arg_type); + } + + static bool IList_To_Array(TypeSpec list, ArrayContainer array) + { + if (array.Rank != 1 || !list.IsGenericIterateInterface) + return false; + + var arg_type = list.TypeArguments[0]; + if (array.Element == arg_type) + return true; + + return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type); + } + + public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type) + { + // + // From T to a type parameter U, provided T depends on U + // + if (target_type.IsGenericParameter) { + if (expr_type.TypeArguments != null) { + foreach (var targ in expr_type.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (target_type, targ)) + continue; + + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType) + return new BoxedCast (expr, target_type); + + return new ClassCast (expr, target_type); + } + } + + return null; + } + + // + // LAMESPEC: From T to dynamic type because it's like T to object + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + // + // From T to its effective base class C + // From T to any base class of C (it cannot contain dynamic or be of dynamic type) + // From T to any interface implemented by C + // + var base_type = expr_type.GetEffectiveBase (); + if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + return null; + } + + static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type) + { + var target_tp = target_type as TypeParameterSpec; + if (target_tp != null) { + if (target_tp.TypeArguments != null) { + foreach (var targ in target_tp.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (source_type, targ)) + continue; + + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + } +/* + if (target_tp.Interfaces != null) { + foreach (TypeSpec iface in target_tp.Interfaces) { + if (!TypeManager.IsGenericParameter (iface)) + continue; + + if (TypeManager.IsSubclassOf (source_type, iface)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true); + } + } +*/ + return null; + } + + if (target_type.IsInterface) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true); + + return null; + } + + public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast) + { + TypeSpec expr_type = expr.Type; + + if (expr_type.Kind == MemberKind.TypeParameter) + return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type); + + // + // from the null type to any reference-type. + // + NullLiteral nl = expr as NullLiteral; + if (nl != null) { + return nl.ConvertImplicitly (target_type); + } + + if (ImplicitReferenceConversionExists (expr_type, target_type)) { + // + // Avoid wrapping implicitly convertible reference type + // + if (!explicit_cast) + return expr; + + return EmptyCast.Create (expr, target_type); + } + + return null; + } + + // + // Implicit reference conversions + // + public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type) + { + return ImplicitReferenceConversionExists (expr_type, target_type, true); + } + + static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter) + { + // It's here only to speed things up + if (target_type.IsStruct) + return false; + + switch (expr_type.Kind) { + case MemberKind.TypeParameter: + return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null && + (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type)); + + case MemberKind.Class: + // + // From any class-type to dynamic (+object to speed up common path) + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (target_type.IsClass) { + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any class-type S to any class-type T, provided S is derived from T + // + return TypeSpec.IsBaseClass (expr_type, target_type, true); + } + + // + // From any class-type S to any interface-type T, provided S implements T + // + if (target_type.IsInterface) + return expr_type.ImplementsInterface (target_type, true); + + return false; + + case MemberKind.ArrayType: + // + // Identity array conversion + // + if (expr_type == target_type) + return true; + + // + // From any array-type to System.Array + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Array: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + var expr_type_array = (ArrayContainer) expr_type; + var target_type_array = target_type as ArrayContainer; + + // + // From an array-type S to an array-type of type T + // + if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) { + + // + // Both SE and TE are reference-types. TE check is defered + // to ImplicitReferenceConversionExists + // + TypeSpec expr_element_type = expr_type_array.Element; + if (!TypeSpec.IsReferenceType (expr_element_type)) + return false; + + // + // An implicit reference conversion exists from SE to TE + // + return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element); + } + + // + // From any array-type to the interfaces it implements + // + if (target_type.IsInterface) { + if (expr_type.ImplementsInterface (target_type, false)) + return true; + + // from an array-type of type T to IList + if (ArrayToIList (expr_type_array, target_type, false)) + return true; + } + + return false; + + case MemberKind.Delegate: + // + // From any delegate-type to System.Delegate (and its base types) + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any delegate-type to the interfaces it implements + // From any reference-type to an delegate type if is variance-convertible + // + return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type); + + case MemberKind.Interface: + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any interface type S to interface-type T + // From any reference-type to an interface if is variance-convertible + // + if (target_type.IsInterface) + return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true); + + return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + } + + // + // from the null literal to any reference-type. + // + if (expr_type == InternalType.NullLiteral) { + // Exlude internal compiler types + if (target_type.Kind == MemberKind.InternalCompilerType) + return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + + return TypeSpec.IsReferenceType (target_type); + } + + return false; + } + + public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + // + // From any non-nullable-value-type to the type object and dynamic + // + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + // + // From any non-nullable-value-type to the type System.ValueType + // + case BuiltinTypeSpec.Type.ValueType: + // + // No ned to check for nullable type as underlying type is always convertible + // + if (!TypeSpec.IsValueType (expr_type)) + return null; + + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + + case BuiltinTypeSpec.Type.Enum: + // + // From any enum-type to the type System.Enum. + // + if (expr_type.IsEnum) + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + + break; + } + + // + // From a nullable-type to a reference type, if a boxing conversion exists from + // the underlying type to the reference type + // + if (expr_type.IsNullableType) { + if (!TypeSpec.IsReferenceType (target_type)) + return null; + + var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); + + // "cast" underlying type to target type to emit correct InvalidCastException when + // underlying hierarchy changes without recompilation + if (res != null && expr != null) + res = new UnboxCast (res, target_type); + + return res; + } + + // + // A value type has a boxing conversion to an interface type I if it has a boxing conversion + // to an interface or delegate type I0 and I0 is variance-convertible to I + // + if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) { + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + } + + return null; + } + + public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type) + { + TypeSpec expr_type = expr.Type; + + // + // From null to any nullable type + // + if (expr_type == InternalType.NullLiteral) + return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location); + + // S -> T? + TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type); + + // S? -> T? + if (expr_type.IsNullableType) + expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type); + + // + // Predefined implicit identity or implicit numeric conversion + // has to exist between underlying type S and underlying type T + // + + // conversion exists only mode + if (ec == null) { + if (TypeSpecComparer.IsEqual (expr_type, t_el)) + return EmptyExpression.Null; + + if (expr is Constant) + return ((Constant) expr).ConvertImplicitly (t_el); + + return ImplicitNumericConversion (null, expr_type, t_el); + } + + Expression unwrap; + if (expr_type != expr.Type) + unwrap = Nullable.Unwrap.Create (expr); + else + unwrap = expr; + + Expression conv = unwrap; + if (!TypeSpecComparer.IsEqual (expr_type, t_el)) { + if (conv is Constant) + conv = ((Constant)conv).ConvertImplicitly (t_el); + else + conv = ImplicitNumericConversion (conv, expr_type, t_el); + + if (conv == null) + return null; + } + + if (expr_type != expr.Type) + return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec); + + return Nullable.Wrap.Create (conv, target_type); + } + + /// + /// Implicit Numeric Conversions. + /// + /// expr is the expression to convert, returns a new expression of type + /// target_type or null if an implicit conversion is not possible. + /// + public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type) + { + return ImplicitNumericConversion (expr, expr.Type, target_type); + } + + static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) + { + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + // + // From sbyte to short, int, long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Short: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + + } + + break; + case BuiltinTypeSpec.Type.Byte: + // + // From byte to short, ushort, int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Short: + // + // From short to int, long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UShort: + // + // From ushort to int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Int: + // + // From int to long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UInt: + // + // From uint to long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Long: + // + // From long to float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.ULong: + // + // From ulong to float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Char: + // + // From char to ushort, int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Float: + // + // float to double + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + break; + } + + return null; + } + + // + // Full version of implicit conversion + // + public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type) + { + if (ImplicitStandardConversionExists (expr, target_type)) + return true; + + if (expr.Type == InternalType.AnonymousMethod) { + if (!target_type.IsDelegate && !target_type.IsExpressionTreeType) + return false; + + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; + return ame.ImplicitStandardConversionExists (ec, target_type); + } + + if (expr.eclass == ExprClass.MethodGroup) { + if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) { + MethodGroupExpr mg = expr as MethodGroupExpr; + if (mg != null) + return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type); + } + + return false; + } + + // Conversion from __arglist to System.ArgIterator + if (expr.Type == InternalType.Arglist) + return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec; + + return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null; + } + + // + // Implicit standard conversion (only core conversions are used here) + // + public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type) + { + // + // Identity conversions + // Implicit numeric conversions + // Implicit nullable conversions + // Implicit reference conversions + // Boxing conversions + // Implicit constant expression conversions + // Implicit conversions involving type parameters + // + + TypeSpec expr_type = expr.Type; + + if (expr_type == target_type) + return true; + + if (target_type.IsNullableType) + return ImplicitNulableConversion (null, expr, target_type) != null; + + if (ImplicitNumericConversion (null, expr_type, target_type) != null) + return true; + + if (ImplicitReferenceConversionExists (expr_type, target_type, false)) + return true; + + if (ImplicitBoxingConversion (null, expr_type, target_type) != null) + return true; + + // + // Implicit Constant Expression Conversions + // + if (expr is IntConstant){ + int value = ((IntConstant) expr).Value; + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (value >= SByte.MinValue && value <= SByte.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.Byte: + if (value >= 0 && value <= Byte.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.Short: + if (value >= Int16.MinValue && value <= Int16.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.UShort: + if (value >= UInt16.MinValue && value <= UInt16.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.UInt: + if (value >= 0) + return true; + break; + case BuiltinTypeSpec.Type.ULong: + // + // we can optimize this case: a positive int32 + // always fits on a uint64. But we need an opcode + // to do it. + // + if (value >= 0) + return true; + + break; + } + } + + if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){ + // + // Try the implicit constant expression conversion + // from long to ulong, instead of a nice routine, + // we just inline it + // + long v = ((LongConstant) expr).Value; + if (v >= 0) + return true; + } + + if (expr is IntegralConstant && target_type.IsEnum) { + var i = (IntegralConstant) expr; + // + // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 + // + // An implicit enumeration conversion permits the decimal-integer-literal 0 + // to be converted to any enum-type and to any nullable-type whose underlying + // type is an enum-type + // + return i.IsZeroInteger; + } + + // Implicit dynamic conversion + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + switch (target_type.Kind) { + case MemberKind.ArrayType: + case MemberKind.Class: + case MemberKind.Struct: + case MemberKind.Delegate: + case MemberKind.Enum: + case MemberKind.Interface: + case MemberKind.TypeParameter: + return true; + } + + // dynamic to __arglist + if (target_type == InternalType.Arglist) + return true; + + return false; + } + + // + // In an unsafe context implicit conversions is extended to include + // + // From any pointer-type to the type void* + // From the null literal to any pointer-type. + // + // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but + // in reality implicit standard conversion uses it + // + if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void) + return true; + + // + // Struct identity conversion, including dynamic erasure + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + return false; + } + + /// + /// Finds "most encompassed type" according to the spec (13.4.2) + /// amongst the methods in the MethodGroupExpr + /// + public static TypeSpec FindMostEncompassedType (IEnumerable types) + { + TypeSpec best = null; + EmptyExpression expr; + + foreach (TypeSpec t in types) { + if (best == null) { + best = t; + continue; + } + + expr = new EmptyExpression (t); + if (ImplicitStandardConversionExists (expr, best)) + best = t; + } + + expr = new EmptyExpression (best); + foreach (TypeSpec t in types) { + if (best == t) + continue; + if (!ImplicitStandardConversionExists (expr, t)) { + best = null; + break; + } + } + + return best; + } + + // + // Finds the most encompassing type (type into which all other + // types can convert to) amongst the types in the given set + // + static TypeSpec FindMostEncompassingType (IList types) + { + if (types.Count == 0) + return null; + + if (types.Count == 1) + return types [0]; + + TypeSpec best = null; + for (int i = 0; i < types.Count; ++i) { + int ii = 0; + for (; ii < types.Count; ++ii) { + if (ii == i) + continue; + + var expr = new EmptyExpression (types[ii]); + if (!ImplicitStandardConversionExists (expr, types [i])) { + ii = 0; + break; + } + } + + if (ii == 0) + continue; + + if (best == null) { + best = types[i]; + continue; + } + + // Indicates multiple best types + return InternalType.FakeInternalType; + } + + return best; + } + + // + // Finds the most specific source Sx according to the rules of the spec (13.4.4) + // by making use of FindMostEncomp* methods. Applies the correct rules separately + // for explicit and implicit conversion operators. + // + static TypeSpec FindMostSpecificSource (List list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules) + { + var src_types_set = new TypeSpec [list.Count]; + + // + // Try exact match first, if any operator converts from S then Sx = S + // + for (int i = 0; i < src_types_set.Length; ++i) { + TypeSpec param_type = list [i].Parameters.Types [0]; + + if (param_type == sourceType) + return param_type; + + src_types_set [i] = param_type; + } + + // + // Explicit Conv rules + // + if (apply_explicit_conv_rules) { + var candidate_set = new List (); + + foreach (TypeSpec param_type in src_types_set){ + if (ImplicitStandardConversionExists (source, param_type)) + candidate_set.Add (param_type); + } + + if (candidate_set.Count != 0) + return FindMostEncompassedType (candidate_set); + } + + // + // Final case + // + if (apply_explicit_conv_rules) + return FindMostEncompassingType (src_types_set); + else + return FindMostEncompassedType (src_types_set); + } + + /// + /// Finds the most specific target Tx according to section 13.4.4 + /// + static public TypeSpec FindMostSpecificTarget (IList list, + TypeSpec target, bool apply_explicit_conv_rules) + { + var tgt_types_set = new List (); + + // + // If any operator converts to T then Tx = T + // + foreach (var mi in list){ + TypeSpec ret_type = mi.ReturnType; + if (ret_type == target) + return ret_type; + + tgt_types_set.Add (ret_type); + } + + // + // Explicit conv rules + // + if (apply_explicit_conv_rules) { + var candidate_set = new List (); + + foreach (TypeSpec ret_type in tgt_types_set) { + var expr = new EmptyExpression (ret_type); + + if (ImplicitStandardConversionExists (expr, target)) + candidate_set.Add (ret_type); + } + + if (candidate_set.Count != 0) + return FindMostEncompassingType (candidate_set); + } + + // + // Okay, final case ! + // + if (apply_explicit_conv_rules) + return FindMostEncompassedType (tgt_types_set); + else + return FindMostEncompassingType (tgt_types_set); + } + + /// + /// User-defined Implicit conversions + /// + static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc) + { + return UserDefinedConversion (ec, source, target, true, loc); + } + + /// + /// User-defined Explicit conversions + /// + static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc) + { + return UserDefinedConversion (ec, source, target, false, loc); + } + + static void FindApplicableUserDefinedConversionOperators (IList operators, Expression source, TypeSpec target, bool implicitOnly, ref List candidates) + { + if (source.Type.IsInterface) { + // Neither A nor B are interface-types + return; + } + + // For a conversion operator to be applicable, it must be possible + // to perform a standard conversion from the source type to + // the operand type of the operator, and it must be possible + // to perform a standard conversion from the result type of + // the operator to the target type. + + Expression texpr = null; + + foreach (MethodSpec op in operators) { + + // Can be null because MemberCache.GetUserOperator does not resize the array + if (op == null) + continue; + + var t = op.Parameters.Types[0]; + if (source.Type != t && !ImplicitStandardConversionExists (source, t)) { + if (implicitOnly) + continue; + + if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type)) + continue; + } + + t = op.ReturnType; + + if (t.IsInterface) + continue; + + if (target != t) { + if (t.IsNullableType) + t = Nullable.NullableInfo.GetUnderlyingType (t); + + if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) { + if (implicitOnly) + continue; + + if (texpr == null) + texpr = new EmptyExpression (target); + + if (!ImplicitStandardConversionExists (texpr, t)) + continue; + } + } + + if (candidates == null) + candidates = new List (); + + candidates.Add (op); + } + } + + // + // User-defined conversions + // + static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc) + { + List candidates = null; + + // + // If S or T are nullable types, source_type and target_type are their underlying types + // otherwise source_type and target_type are equal to S and T respectively. + // + TypeSpec source_type = source.Type; + TypeSpec target_type = target; + Expression source_type_expr; + + if (source_type.IsNullableType) { + // No implicit conversion S? -> T for non-reference types + if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) + return null; + + source_type_expr = Nullable.Unwrap.Create (source); + source_type = source_type_expr.Type; + } else { + source_type_expr = source; + } + + if (target_type.IsNullableType) + target_type = Nullable.NullableInfo.GetUnderlyingType (target_type); + + // Only these containers can contain a user defined implicit or explicit operators + const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter; + + if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + bool declared_only = source_type.IsStruct; + + var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); + } + + if (!implicitOnly) { + operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); + } + } + } + + if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + bool declared_only = target.IsStruct || implicitOnly; + + var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); + } + + if (!implicitOnly) { + operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); + } + } + } + + if (candidates == null) + return null; + + // + // Find the most specific conversion operator + // + MethodSpec most_specific_operator; + TypeSpec s_x, t_x; + if (candidates.Count == 1) { + most_specific_operator = candidates[0]; + s_x = most_specific_operator.Parameters.Types[0]; + t_x = most_specific_operator.ReturnType; + } else { + // + // Pass original source type to find the best match against input type and + // not the unwrapped expression + // + s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly); + if (s_x == null) + return null; + + t_x = FindMostSpecificTarget (candidates, target, !implicitOnly); + if (t_x == null) + return null; + + most_specific_operator = null; + for (int i = 0; i < candidates.Count; ++i) { + if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) { + most_specific_operator = candidates[i]; + break; + } + } + + if (most_specific_operator == null) { + MethodSpec ambig_arg = null; + foreach (var candidate in candidates) { + if (candidate.ReturnType == t_x) + most_specific_operator = candidate; + else if (candidate.Parameters.Types[0] == s_x) + ambig_arg = candidate; + } + + ec.Report.Error (457, loc, + "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'", + ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (), + source.Type.GetSignatureForError (), target.GetSignatureForError ()); + + return ErrorExpression.Instance; + } + } + + // + // Convert input type when it's different to best operator argument + // + if (s_x != source_type) { + var c = source as Constant; + if (c != null) { + source = c.TryReduce (ec, s_x, loc); + } else { + source = implicitOnly ? + ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : + ExplicitConversionStandard (ec, source_type_expr, s_x, loc); + } + } else { + source = source_type_expr; + } + + source = new UserCast (most_specific_operator, source, loc).Resolve (ec); + + // + // Convert result type when it's different to best operator return type + // + if (t_x != target_type) { + // + // User operator is of T?, no need to lift it + // + if (t_x == target && t_x.IsNullableType) + return source; + + source = implicitOnly ? + ImplicitConversionStandard (ec, source, target_type, loc) : + ExplicitConversionStandard (ec, source, target_type, loc); + + if (source == null) + return null; + } + + // + // Source expression is of nullable type, lift the result in the case it's null and + // not nullable/lifted user operator is used + // + if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target)) + source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec); + else if (target_type != target) + source = Nullable.Wrap.Create (source, target); + + return source; + } + + /// + /// Converts implicitly the resolved expression `expr' into the + /// `target_type'. It returns a new expression that can be used + /// in a context that expects a `target_type'. + /// + static public Expression ImplicitConversion (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + Expression e; + + if (target_type == null) + throw new Exception ("Target type is null"); + + e = ImplicitConversionStandard (ec, expr, target_type, loc); + if (e != null) + return e; + + e = ImplicitUserConversion (ec, expr, target_type, loc); + if (e != null) + return e; + + return null; + } + + + /// + /// Attempts to apply the `Standard Implicit + /// Conversion' rules to the expression `expr' into + /// the `target_type'. It returns a new expression + /// that can be used in a context that expects a + /// `target_type'. + /// + /// This is different from `ImplicitConversion' in that the + /// user defined implicit conversions are excluded. + /// + static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + return ImplicitConversionStandard (ec, expr, target_type, loc, false); + } + + static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast) + { + if (expr.eclass == ExprClass.MethodGroup){ + if (!TypeManager.IsDelegateType (target_type)){ + return null; + } + + // + // Only allow anonymous method conversions on post ISO_1 + // + if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){ + MethodGroupExpr mg = expr as MethodGroupExpr; + if (mg != null) + return ImplicitDelegateCreation.Create ( + ec, mg, target_type, loc); + } + } + + TypeSpec expr_type = expr.Type; + Expression e; + + if (expr_type == target_type) { + if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod) + return expr; + return null; + } + + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + switch (target_type.Kind) { + case MemberKind.ArrayType: + case MemberKind.Class: + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object) + return EmptyCast.Create (expr, target_type); + + goto case MemberKind.Struct; + case MemberKind.Struct: + case MemberKind.Delegate: + case MemberKind.Enum: + case MemberKind.Interface: + case MemberKind.TypeParameter: + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec); + } + + return null; + } + + if (target_type.IsNullableType) + return ImplicitNulableConversion (ec, expr, target_type); + + // + // Attempt to do the implicit constant expression conversions + // + Constant c = expr as Constant; + if (c != null) { + try { + c = c.ConvertImplicitly (target_type); + } catch { + Console.WriteLine ("Conversion error happened in line {0}", loc); + throw; + } + if (c != null) + return c; + } + + e = ImplicitNumericConversion (expr, expr_type, target_type); + if (e != null) + return e; + + e = ImplicitReferenceConversion (expr, target_type, explicit_cast); + if (e != null) + return e; + + e = ImplicitBoxingConversion (expr, expr_type, target_type); + if (e != null) + return e; + + if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){ + var i = (IntegralConstant) expr; + // + // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 + // + // An implicit enumeration conversion permits the decimal-integer-literal 0 + // to be converted to any enum-type and to any nullable-type whose underlying + // type is an enum-type + // + if (i.IsZeroInteger) { + // Recreate 0 literal to remove any collected conversions + return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type); + } + } + + if (ec.IsUnsafe) { + var target_pc = target_type as PointerContainer; + if (target_pc != null) { + if (expr_type.IsPointer) { + // + // Pointer types are same when they have same element types + // + if (expr_type == target_pc) + return expr; + + if (target_pc.Element.Kind == MemberKind.Void) + return EmptyCast.Create (expr, target_type); + + //return null; + } + + if (expr_type == InternalType.NullLiteral) + return new NullPointer (target_type, loc); + } + } + + if (expr_type == InternalType.AnonymousMethod){ + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; + Expression am = ame.Compatible (ec, target_type); + if (am != null) + return am.Resolve (ec); + } + + if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec) + return expr; + + // + // dynamic erasure conversion on value types + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) + return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type); + + return null; + } + + /// + /// Attempts to implicitly convert `source' into `target_type', using + /// ImplicitConversion. If there is no implicit conversion, then + /// an error is signaled + /// + static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source, + TypeSpec target_type, Location loc) + { + Expression e = ImplicitConversion (ec, source, target_type, loc); + if (e != null) + return e; + + source.Error_ValueCannotBeConverted (ec, loc, target_type, false); + return null; + } + + /// + /// Performs the explicit numeric conversions + /// + /// There are a few conversions that are not part of the C# standard, + /// they were interim hacks in the C# compiler that were supposed to + /// become explicit operators in the UIntPtr class and IntPtr class, + /// but for historical reasons it did not happen, so the C# compiler + /// ended up with these special hacks. + /// + /// See bug 59800 for details. + /// + /// The conversion are: + /// UIntPtr->SByte + /// UIntPtr->Int16 + /// UIntPtr->Int32 + /// IntPtr->UInt64 + /// UInt64->IntPtr + /// SByte->UIntPtr + /// Int16->UIntPtr + /// + /// + public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type) + { + // Not all predefined explicit numeric conversion are + // defined here, for some of them (mostly IntPtr/UIntPtr) we + // defer to user-operator handling which is now perfect but + // works for now + // + // LAMESPEC: Undocumented IntPtr/UIntPtr conversions + // IntPtr -> uint uses int + // UIntPtr -> long uses ulong + // + + switch (expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + // + // From sbyte to byte, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.Byte: + // + // From byte to sbyte and char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH); + } + break; + case BuiltinTypeSpec.Type.Short: + // + // From short to sbyte, byte, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UShort: + // + // From ushort to sbyte, byte, short, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH); + } + break; + case BuiltinTypeSpec.Type.Int: + // + // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UInt: + // + // From uint to sbyte, byte, short, ushort, int, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH); + } + break; + case BuiltinTypeSpec.Type.Long: + // + // From long to sbyte, byte, short, ushort, int, uint, ulong, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH); + } + break; + case BuiltinTypeSpec.Type.ULong: + // + // From ulong to sbyte, byte, short, ushort, int, uint, long, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.IntPtr: + return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true); + } + break; + case BuiltinTypeSpec.Type.Char: + // + // From char to sbyte, byte, short + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2); + } + break; + case BuiltinTypeSpec.Type.Float: + // + // From float to sbyte, byte, short, + // ushort, int, uint, long, ulong, char + // or decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH); + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.Double: + // + // From double to sbyte, byte, short, + // ushort, int, uint, long, ulong, + // char, float or decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH); + case BuiltinTypeSpec.Type.Float: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4); + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UIntPtr: + // + // Various built-in conversions that belonged in the class library + // + // from uintptr to sbyte, short, int32 + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2); + case BuiltinTypeSpec.Type.Int: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type); + case BuiltinTypeSpec.Type.UInt: + return new OperatorCast (expr, expr.Type, target_type, true); + case BuiltinTypeSpec.Type.Long: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type); + } + break; + case BuiltinTypeSpec.Type.IntPtr: + if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type); + if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type); + + break; + case BuiltinTypeSpec.Type.Decimal: + // From decimal to sbyte, byte, short, + // ushort, int, uint, long, ulong, char, + // float, or double + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + return new OperatorCast (expr, expr.Type, target_type, true); + } + + break; + } + + return null; + } + + /// + /// Returns whether an explicit reference conversion can be performed + /// from source_type to target_type + /// + public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type) + { + Expression e = ExplicitReferenceConversion (null, source_type, target_type); + if (e == null) + return false; + + if (e == EmptyExpression.Null) + return true; + + throw new InternalErrorException ("Invalid probing conversion result"); + } + + /// + /// Implements Explicit Reference conversions + /// + static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type) + { + // + // From object to a generic parameter + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type)) + return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); + + // + // Explicit type parameter conversion. + // + if (source_type.Kind == MemberKind.TypeParameter) + return ExplicitTypeParameterConversion (source, source_type, target_type); + + bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum; + + // + // Unboxing conversion from System.ValueType to any non-nullable-value-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type) + return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); + + // + // From object or dynamic to any reference type or value type (unboxing) + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + if (target_type.IsPointer) + return null; + + return + source == null ? EmptyExpression.Null : + target_is_value_type ? new UnboxCast (source, target_type) : + source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) : + new ClassCast (source, target_type); + } + + // + // From any class S to any class-type T, provided S is a base class of T + // + if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From any interface-type S to to any class type T, provided T is not + // sealed, or provided T implements S. + // + if (source_type.Kind == MemberKind.Interface) { + if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) { + if (source == null) + return EmptyExpression.Null; + + // + // Unboxing conversion from any interface-type to any non-nullable-value-type that + // implements the interface-type + // + return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type); + } + + // + // From System.Collections.Generic.IList and its base interfaces to a one-dimensional + // array type S[], provided there is an implicit or explicit reference conversion from S to T. + // + var target_array = target_type as ArrayContainer; + if (target_array != null && IList_To_Array (source_type, target_array)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + + var source_array = source_type as ArrayContainer; + if (source_array != null) { + var target_array = target_type as ArrayContainer; + if (target_array != null) { + // + // From System.Array to any array-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From an array type S with an element type Se to an array type T with an + // element type Te provided all the following are true: + // * S and T differe only in element type, in other words, S and T + // have the same number of dimensions. + // * Both Se and Te are reference types + // * An explicit reference conversions exist from Se to Te + // + if (source_array.Rank == target_array.Rank) { + + source_type = source_array.Element; + if (!TypeSpec.IsReferenceType (source_type)) + return null; + + var target_element = target_array.Element; + if (!TypeSpec.IsReferenceType (target_element)) + return null; + + if (ExplicitReferenceConversionExists (source_type, target_element)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + } + + // + // From a single-dimensional array type S[] to System.Collections.Generic.IList and its base interfaces, + // provided that there is an explicit reference conversion from S to T + // + if (ArrayToIList (source_array, target_type, true)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + + // + // From any class type S to any interface T, provides S is not sealed + // and provided S does not implement T. + // + if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) { + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + + // + // From System delegate to any delegate-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && TypeManager.IsDelegateType (target_type)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From variant generic delegate to same variant generic delegate type + // + if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) { + var tparams = source_type.MemberDefinition.TypeParameters; + var targs_src = source_type.TypeArguments; + var targs_dst = target_type.TypeArguments; + int i; + for (i = 0; i < tparams.Length; ++i) { + // + // If TP is invariant, types have to be identical + // + if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i])) + continue; + + if (tparams[i].Variance == Variance.Covariant) { + // + //If TP is covariant, an implicit or explicit identity or reference conversion is required + // + if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i])) + continue; + + if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i])) + continue; + + } else if (tparams[i].Variance == Variance.Contravariant) { + // + //If TP is contravariant, both are either identical or reference types + // + if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i])) + continue; + } + + break; + } + + if (i == tparams.Length) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + + return null; + } + + /// + /// Performs an explicit conversion of the expression `expr' whose + /// type is expr.Type to `target_type'. + /// + static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + TypeSpec expr_type = expr.Type; + + // Explicit conversion includes implicit conversion and it used for enum underlying types too + Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true); + if (ne != null) + return ne; + + if (TypeManager.IsEnumType (expr_type)) { + TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type; + Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type)); + if (underlying.Type == real_target) + ne = underlying; + + if (ne == null) + ne = ImplicitNumericConversion (underlying, real_target); + + if (ne == null) + ne = ExplicitNumericConversion (ec, underlying, real_target); + + // + // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed + // + if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr)) + ne = ExplicitUserConversion (ec, underlying, real_target, loc); + + return ne != null ? EmptyCast.Create (ne, target_type) : null; + } + + if (TypeManager.IsEnumType (target_type)) { + // + // System.Enum can be unboxed to any enum-type + // + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum) + return new UnboxCast (expr, target_type); + + TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type; + + if (expr_type == real_target) + return EmptyCast.Create (expr, target_type); + + ne = ImplicitNumericConversion (expr, real_target); + if (ne != null) + return EmptyCast.Create (ne, target_type); + + ne = ExplicitNumericConversion (ec, expr, real_target); + if (ne != null) + return EmptyCast.Create (ne, target_type); + + // + // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed + // + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) { + ne = ExplicitUserConversion (ec, expr, real_target, loc); + if (ne != null) + return ExplicitConversionCore (ec, ne, target_type, loc); + } + } else { + ne = ExplicitNumericConversion (ec, expr, target_type); + if (ne != null) + return ne; + } + + // + // Skip the ExplicitReferenceConversion because we can not convert + // from Null to a ValueType, and ExplicitReference wont check against + // null literal explicitly + // + if (expr_type != InternalType.NullLiteral) { + ne = ExplicitReferenceConversion (expr, expr_type, target_type); + if (ne != null) + return ne; + } + + if (ec.IsUnsafe){ + ne = ExplicitUnsafe (expr, target_type); + if (ne != null) + return ne; + } + + return null; + } + + public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type) + { + TypeSpec expr_type = expr.Type; + + if (target_type.IsPointer){ + if (expr_type.IsPointer) + return EmptyCast.Create (expr, target_type); + + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Int: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I); + + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Byte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U); + + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I); + + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I); + } + } + + if (expr_type.IsPointer){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I1); + case BuiltinTypeSpec.Type.Byte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U1); + case BuiltinTypeSpec.Type.Short: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I2); + case BuiltinTypeSpec.Type.UShort: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U2); + case BuiltinTypeSpec.Type.Int: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I4); + case BuiltinTypeSpec.Type.UInt: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.I_I8); + case BuiltinTypeSpec.Type.ULong: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + } + } + return null; + } + + /// + /// Same as ExplicitConversion, only it doesn't include user defined conversions + /// + static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr, + TypeSpec target_type, Location l) + { + int errors = ec.Report.Errors; + Expression ne = ImplicitConversionStandard (ec, expr, target_type, l); + if (ec.Report.Errors > errors) + return null; + + if (ne != null) + return ne; + + ne = ExplicitNumericConversion (ec, expr, target_type); + if (ne != null) + return ne; + + ne = ExplicitReferenceConversion (expr, expr.Type, target_type); + if (ne != null) + return ne; + + if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void) + return EmptyCast.Create (expr, target_type); + + expr.Error_ValueCannotBeConverted (ec, l, target_type, true); + return null; + } + + /// + /// Performs an explicit conversion of the expression `expr' whose + /// type is expr.Type to `target_type'. + /// + static public Expression ExplicitConversion (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + Expression e = ExplicitConversionCore (ec, expr, target_type, loc); + if (e != null) { + // + // Don't eliminate explicit precission casts + // + if (e == expr) { + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + } + + return e; + } + + TypeSpec expr_type = expr.Type; + if (target_type.IsNullableType) { + TypeSpec target; + + if (expr_type.IsNullableType) { + target = Nullable.NullableInfo.GetUnderlyingType (target_type); + Expression unwrap = Nullable.Unwrap.Create (expr); + e = ExplicitConversion (ec, unwrap, target, expr.Location); + if (e == null) + return null; + + return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec); + } + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + return new UnboxCast (expr, target_type); + } + + target = TypeManager.GetTypeArguments (target_type) [0]; + e = ExplicitConversionCore (ec, expr, target, loc); + if (e != null) + return Nullable.Wrap.Create (e, target_type); + } else if (expr_type.IsNullableType) { + e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); + if (e != null) + return e; + + e = Nullable.Unwrap.Create (expr, false); + e = ExplicitConversionCore (ec, e, target_type, loc); + if (e != null) + return EmptyCast.Create (e, target_type); + } + + e = ExplicitUserConversion (ec, expr, target_type, loc); + if (e != null) + return e; + + expr.Error_ValueCannotBeConverted (ec, loc, target_type, true); + return null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs new file mode 100644 index 0000000000..0cee24dd0c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -0,0 +1,13108 @@ +// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de + +#line 2 "cs-parser.jay" +// +// cs-parser.jay: The Parser for the C# compiler +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual Licensed under the terms of the GNU GPL and the MIT X11 license +// +// (C) 2001 Ximian, Inc (http://www.ximian.com) +// (C) 2004 Novell, Inc +// +// TODO: +// (1) Figure out why error productions dont work. `type-declaration' is a +// great spot to put an `error' because you can reproduce it with this input: +// "public X { }" +// + +using System.Text; +using System.IO; +using System; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + /// + /// The C# Parser + /// + public class CSharpParser + { + [Flags] + enum ParameterModifierType + { + Ref = 1 << 1, + Out = 1 << 2, + This = 1 << 3, + Params = 1 << 4, + Arglist = 1 << 5, + DefaultValue = 1 << 6, + + All = Ref | Out | This | Params | Arglist | DefaultValue + } + + static readonly object ModifierNone = 0; + + NamespaceContainer current_namespace; + TypeContainer current_container; + DeclSpace current_class; + PropertyBase current_property; + EventProperty current_event; + EventField current_event_field; + FieldBase current_field; + + /// + /// Current block is used to add statements as we find + /// them. + /// + Block current_block; + + BlockVariableDeclaration current_variable; + + Delegate current_delegate; + + AnonymousMethodExpression current_anonymous_method; + + /// + /// This is used by the unary_expression code to resolve + /// a name against a parameter. + /// + + // FIXME: This is very ugly and it's very hard to reset it correctly + // on all places, especially when some parameters are autogenerated. + ParametersCompiled current_local_parameters; + + bool parsing_anonymous_method; + + /// + /// An out-of-band stack. + /// + static Stack oob_stack; + + /// + /// Controls the verbosity of the errors produced by the parser + /// + static public int yacc_verbose_flag; + + /// + /// Used by the interactive shell, flags whether EOF was reached + /// and an error was produced + /// + public bool UnexpectedEOF; + + /// + /// The current file. + /// + readonly CompilationSourceFile file; + + /// + /// Temporary Xml documentation cache. + /// For enum types, we need one more temporary store. + /// + string tmpComment; + string enumTypeComment; + + /// Current attribute target + string current_attr_target; + + ParameterModifierType valid_param_mod; + + bool default_parameter_used; + + /// When using the interactive parser, this holds the + /// resulting expression + public Class InteractiveResult; + + // + // Keeps track of global data changes to undo on parser error + // + public Undo undo; + + Stack linq_clause_blocks; + + ModuleContainer module; + + readonly CompilerContext compiler; + readonly LanguageVersion lang_version; + readonly bool doc_support; + readonly CompilerSettings settings; + readonly Report report; + + // + // Instead of allocating carrier array everytime we + // share the bucket for very common constructs which can never + // be recursive + // + static List parameters_bucket = new List (6); + + // + // Full AST support members + // + LocationsBag lbag; + UsingsBag ubag; + List> mod_locations; + Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Stack> locationListStack = new Stack> (); // used for type parameters + + object lastYYVal; + + // Can be used for code completion to get the last valid expression before an error. + // needs a hack in yyparse to make it work add + // lastYYVal = yyVal; + // after the big switch/case (somewhere around line 3915) + public object LastYYVal { + get { + return lastYYVal; + } + } + +#line default + + /** error output stream. + It should be changeable. + */ + public System.IO.TextWriter ErrorOutput = System.Console.Out; + + /** simplified error message. + @see yyerror + */ + public void yyerror (string message) { + yyerror(message, null); + } + + /* An EOF token */ + public int eof_token; + + /** (syntax) error message. + Can be overwritten to control message format. + @param message text to be displayed. + @param expected vector of acceptable tokens, if available. + */ + public void yyerror (string message, string[] expected) { + if ((yacc_verbose_flag > 0) && (expected != null) && (expected.Length > 0)) { + ErrorOutput.Write (message+", expecting"); + for (int n = 0; n < expected.Length; ++ n) + ErrorOutput.Write (" "+expected[n]); + ErrorOutput.WriteLine (); + } else + ErrorOutput.WriteLine (message); + } + + /** debugging support, requires the package jay.yydebug. + Set to null to suppress debugging messages. + */ +//t internal yydebug.yyDebug debug; + + protected const int yyFinal = 7; +//t // Put this array into a separate class so it is only initialized if debugging is actually used +//t // Use MarshalByRefObject to disable inlining +//t class YYRules : MarshalByRefObject { +//t public static readonly string [] yyRule = { +//t "$accept : compilation_unit", +//t "compilation_unit : outer_declaration opt_EOF", +//t "$$1 :", +//t "compilation_unit : interactive_parsing $$1 opt_EOF", +//t "compilation_unit : documentation_parsing", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives attribute_sections", +//t "outer_declaration : error", +//t "opt_EOF :", +//t "opt_EOF : EOF", +//t "extern_alias_directives : extern_alias_directive", +//t "extern_alias_directives : extern_alias_directives extern_alias_directive", +//t "extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON", +//t "extern_alias_directive : EXTERN_ALIAS error", +//t "using_directives : using_directive", +//t "using_directives : using_directives using_directive", +//t "using_directive : using_alias_directive", +//t "using_directive : using_namespace_directive", +//t "using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON", +//t "using_alias_directive : USING error", +//t "using_namespace_directive : USING namespace_name SEMICOLON", +//t "$$2 :", +//t "$$3 :", +//t "namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 OPEN_BRACE $$3 opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon", +//t "qualified_identifier : IDENTIFIER", +//t "qualified_identifier : qualified_identifier DOT IDENTIFIER", +//t "qualified_identifier : error", +//t "opt_semicolon :", +//t "opt_semicolon : SEMICOLON", +//t "opt_comma :", +//t "opt_comma : COMMA", +//t "namespace_name : namespace_or_type_name", +//t "opt_using_directives :", +//t "opt_using_directives : using_directives", +//t "opt_extern_alias_directives :", +//t "opt_extern_alias_directives : extern_alias_directives", +//t "opt_namespace_or_type_declarations :", +//t "opt_namespace_or_type_declarations : namespace_or_type_declarations", +//t "namespace_or_type_declarations : namespace_or_type_declaration", +//t "namespace_or_type_declarations : namespace_or_type_declarations namespace_or_type_declaration", +//t "namespace_or_type_declaration : type_declaration", +//t "namespace_or_type_declaration : namespace_declaration", +//t "type_declaration : class_declaration", +//t "type_declaration : struct_declaration", +//t "type_declaration : interface_declaration", +//t "type_declaration : enum_declaration", +//t "type_declaration : delegate_declaration", +//t "opt_attributes :", +//t "opt_attributes : attribute_sections", +//t "attribute_sections : attribute_section", +//t "attribute_sections : attribute_sections attribute_section", +//t "$$4 :", +//t "attribute_section : OPEN_BRACKET $$4 attribute_section_cont", +//t "$$5 :", +//t "attribute_section_cont : attribute_target COLON $$5 attribute_list opt_comma CLOSE_BRACKET", +//t "attribute_section_cont : attribute_list opt_comma CLOSE_BRACKET", +//t "attribute_target : IDENTIFIER", +//t "attribute_target : EVENT", +//t "attribute_target : RETURN", +//t "attribute_target : error", +//t "attribute_list : attribute", +//t "attribute_list : attribute_list COMMA attribute", +//t "$$6 :", +//t "attribute : attribute_name $$6 opt_attribute_arguments", +//t "attribute_name : namespace_or_type_name", +//t "opt_attribute_arguments :", +//t "opt_attribute_arguments : OPEN_PARENS attribute_arguments CLOSE_PARENS", +//t "attribute_arguments :", +//t "attribute_arguments : positional_or_named_argument", +//t "attribute_arguments : named_attribute_argument", +//t "attribute_arguments : attribute_arguments COMMA positional_or_named_argument", +//t "attribute_arguments : attribute_arguments COMMA named_attribute_argument", +//t "positional_or_named_argument : expression", +//t "positional_or_named_argument : named_argument", +//t "$$7 :", +//t "named_attribute_argument : IDENTIFIER ASSIGN $$7 expression", +//t "named_argument : IDENTIFIER COLON opt_named_modifier expression", +//t "opt_named_modifier :", +//t "opt_named_modifier : REF", +//t "opt_named_modifier : OUT", +//t "opt_class_member_declarations :", +//t "opt_class_member_declarations : class_member_declarations", +//t "class_member_declarations : class_member_declaration", +//t "class_member_declarations : class_member_declarations class_member_declaration", +//t "class_member_declaration : constant_declaration", +//t "class_member_declaration : field_declaration", +//t "class_member_declaration : method_declaration", +//t "class_member_declaration : property_declaration", +//t "class_member_declaration : event_declaration", +//t "class_member_declaration : indexer_declaration", +//t "class_member_declaration : operator_declaration", +//t "class_member_declaration : constructor_declaration", +//t "class_member_declaration : destructor_declaration", +//t "class_member_declaration : type_declaration", +//t "class_member_declaration : error", +//t "$$8 :", +//t "$$9 :", +//t "$$10 :", +//t "$$11 :", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$8 type_declaration_name $$9 opt_class_base opt_type_parameter_constraints_clauses $$10 struct_body $$11 opt_semicolon", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error", +//t "$$12 :", +//t "struct_body : OPEN_BRACE $$12 opt_struct_member_declarations CLOSE_BRACE", +//t "opt_struct_member_declarations :", +//t "opt_struct_member_declarations : struct_member_declarations", +//t "struct_member_declarations : struct_member_declaration", +//t "struct_member_declarations : struct_member_declarations struct_member_declaration", +//t "struct_member_declaration : constant_declaration", +//t "struct_member_declaration : field_declaration", +//t "struct_member_declaration : method_declaration", +//t "struct_member_declaration : property_declaration", +//t "struct_member_declaration : event_declaration", +//t "struct_member_declaration : indexer_declaration", +//t "struct_member_declaration : operator_declaration", +//t "struct_member_declaration : constructor_declaration", +//t "struct_member_declaration : type_declaration", +//t "struct_member_declaration : destructor_declaration", +//t "$$13 :", +//t "constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$13 constant_initializer opt_constant_declarators SEMICOLON", +//t "opt_constant_declarators :", +//t "opt_constant_declarators : constant_declarators", +//t "constant_declarators : constant_declarator", +//t "constant_declarators : constant_declarators constant_declarator", +//t "constant_declarator : COMMA IDENTIFIER constant_initializer", +//t "$$14 :", +//t "constant_initializer : ASSIGN $$14 constant_initializer_expr", +//t "constant_initializer : error", +//t "constant_initializer_expr : constant_expression", +//t "constant_initializer_expr : array_initializer", +//t "$$15 :", +//t "field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$15 opt_field_initializer opt_field_declarators SEMICOLON", +//t "$$16 :", +//t "field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$16 fixed_field_size opt_fixed_field_declarators SEMICOLON", +//t "field_declaration : opt_attributes opt_modifiers FIXED simple_type error SEMICOLON", +//t "opt_field_initializer :", +//t "$$17 :", +//t "opt_field_initializer : ASSIGN $$17 variable_initializer", +//t "opt_field_declarators :", +//t "opt_field_declarators : field_declarators", +//t "field_declarators : field_declarator", +//t "field_declarators : field_declarators field_declarator", +//t "field_declarator : COMMA IDENTIFIER", +//t "$$18 :", +//t "field_declarator : COMMA IDENTIFIER ASSIGN $$18 variable_initializer", +//t "opt_fixed_field_declarators :", +//t "opt_fixed_field_declarators : fixed_field_declarators", +//t "fixed_field_declarators : fixed_field_declarator", +//t "fixed_field_declarators : fixed_field_declarators fixed_field_declarator", +//t "fixed_field_declarator : COMMA IDENTIFIER fixed_field_size", +//t "$$19 :", +//t "fixed_field_size : OPEN_BRACKET $$19 expression CLOSE_BRACKET", +//t "fixed_field_size : OPEN_BRACKET error", +//t "variable_initializer : expression", +//t "variable_initializer : array_initializer", +//t "variable_initializer : error", +//t "$$20 :", +//t "method_declaration : method_header $$20 method_body", +//t "$$21 :", +//t "$$22 :", +//t "method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$21 opt_formal_parameter_list CLOSE_PARENS $$22 opt_type_parameter_constraints_clauses", +//t "$$23 :", +//t "$$24 :", +//t "$$25 :", +//t "method_header : opt_attributes opt_modifiers PARTIAL VOID $$23 method_declaration_name OPEN_PARENS $$24 opt_formal_parameter_list CLOSE_PARENS $$25 opt_type_parameter_constraints_clauses", +//t "method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS", +//t "method_body : block", +//t "method_body : SEMICOLON", +//t "opt_formal_parameter_list :", +//t "opt_formal_parameter_list : formal_parameter_list", +//t "formal_parameter_list : fixed_parameters", +//t "formal_parameter_list : fixed_parameters COMMA parameter_array", +//t "formal_parameter_list : fixed_parameters COMMA arglist_modifier", +//t "formal_parameter_list : parameter_array COMMA error", +//t "formal_parameter_list : fixed_parameters COMMA parameter_array COMMA error", +//t "formal_parameter_list : arglist_modifier COMMA error", +//t "formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA error", +//t "formal_parameter_list : parameter_array", +//t "formal_parameter_list : arglist_modifier", +//t "formal_parameter_list : error", +//t "fixed_parameters : fixed_parameter", +//t "fixed_parameters : fixed_parameters COMMA fixed_parameter", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type error", +//t "$$26 :", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$26 constant_expression", +//t "opt_parameter_modifier :", +//t "opt_parameter_modifier : parameter_modifiers", +//t "parameter_modifiers : parameter_modifier", +//t "parameter_modifiers : parameter_modifiers parameter_modifier", +//t "parameter_modifier : REF", +//t "parameter_modifier : OUT", +//t "parameter_modifier : THIS", +//t "parameter_array : opt_attributes params_modifier type IDENTIFIER", +//t "parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression", +//t "parameter_array : opt_attributes params_modifier type error", +//t "params_modifier : PARAMS", +//t "params_modifier : PARAMS parameter_modifier", +//t "params_modifier : PARAMS params_modifier", +//t "arglist_modifier : ARGLIST", +//t "$$27 :", +//t "$$28 :", +//t "$$29 :", +//t "property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$27 OPEN_BRACE $$28 accessor_declarations $$29 CLOSE_BRACE", +//t "$$30 :", +//t "$$31 :", +//t "$$32 :", +//t "indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$30 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$31 accessor_declarations $$32 CLOSE_BRACE", +//t "accessor_declarations : get_accessor_declaration", +//t "accessor_declarations : get_accessor_declaration accessor_declarations", +//t "accessor_declarations : set_accessor_declaration", +//t "accessor_declarations : set_accessor_declaration accessor_declarations", +//t "accessor_declarations : error", +//t "$$33 :", +//t "get_accessor_declaration : opt_attributes opt_modifiers GET $$33 accessor_body", +//t "$$34 :", +//t "set_accessor_declaration : opt_attributes opt_modifiers SET $$34 accessor_body", +//t "accessor_body : block", +//t "accessor_body : SEMICOLON", +//t "accessor_body : error", +//t "$$35 :", +//t "$$36 :", +//t "$$37 :", +//t "$$38 :", +//t "interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$35 type_declaration_name $$36 opt_class_base opt_type_parameter_constraints_clauses $$37 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$38 opt_semicolon", +//t "interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE error", +//t "opt_interface_member_declarations :", +//t "opt_interface_member_declarations : interface_member_declarations", +//t "interface_member_declarations : interface_member_declaration", +//t "interface_member_declarations : interface_member_declarations interface_member_declaration", +//t "interface_member_declaration : constant_declaration", +//t "interface_member_declaration : field_declaration", +//t "interface_member_declaration : method_declaration", +//t "interface_member_declaration : property_declaration", +//t "interface_member_declaration : event_declaration", +//t "interface_member_declaration : indexer_declaration", +//t "interface_member_declaration : operator_declaration", +//t "interface_member_declaration : constructor_declaration", +//t "interface_member_declaration : type_declaration", +//t "$$39 :", +//t "operator_declaration : opt_attributes opt_modifiers operator_declarator $$39 operator_body", +//t "operator_body : block", +//t "operator_body : SEMICOLON", +//t "operator_type : type_expression_or_array", +//t "operator_type : VOID", +//t "$$40 :", +//t "operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS", +//t "operator_declarator : conversion_operator_declarator", +//t "overloadable_operator : BANG", +//t "overloadable_operator : TILDE", +//t "overloadable_operator : OP_INC", +//t "overloadable_operator : OP_DEC", +//t "overloadable_operator : TRUE", +//t "overloadable_operator : FALSE", +//t "overloadable_operator : PLUS", +//t "overloadable_operator : MINUS", +//t "overloadable_operator : STAR", +//t "overloadable_operator : DIV", +//t "overloadable_operator : PERCENT", +//t "overloadable_operator : BITWISE_AND", +//t "overloadable_operator : BITWISE_OR", +//t "overloadable_operator : CARRET", +//t "overloadable_operator : OP_SHIFT_LEFT", +//t "overloadable_operator : OP_SHIFT_RIGHT", +//t "overloadable_operator : OP_EQ", +//t "overloadable_operator : OP_NE", +//t "overloadable_operator : OP_GT", +//t "overloadable_operator : OP_LT", +//t "overloadable_operator : OP_GE", +//t "overloadable_operator : OP_LE", +//t "$$41 :", +//t "conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$41 opt_formal_parameter_list CLOSE_PARENS", +//t "$$42 :", +//t "conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$42 opt_formal_parameter_list CLOSE_PARENS", +//t "conversion_operator_declarator : IMPLICIT error", +//t "conversion_operator_declarator : EXPLICIT error", +//t "constructor_declaration : constructor_declarator constructor_body", +//t "$$43 :", +//t "$$44 :", +//t "constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$43 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$44 opt_constructor_initializer", +//t "constructor_body : block_prepared", +//t "constructor_body : SEMICOLON", +//t "opt_constructor_initializer :", +//t "opt_constructor_initializer : constructor_initializer", +//t "$$45 :", +//t "constructor_initializer : COLON BASE OPEN_PARENS $$45 opt_argument_list CLOSE_PARENS", +//t "$$46 :", +//t "constructor_initializer : COLON THIS OPEN_PARENS $$46 opt_argument_list CLOSE_PARENS", +//t "constructor_initializer : error", +//t "$$47 :", +//t "destructor_declaration : opt_attributes opt_modifiers TILDE $$47 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body", +//t "$$48 :", +//t "event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$48 opt_event_initializer opt_event_declarators SEMICOLON", +//t "$$49 :", +//t "$$50 :", +//t "event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$49 event_accessor_declarations $$50 CLOSE_BRACE", +//t "opt_event_initializer :", +//t "$$51 :", +//t "opt_event_initializer : ASSIGN $$51 event_variable_initializer", +//t "opt_event_declarators :", +//t "opt_event_declarators : event_declarators", +//t "event_declarators : event_declarator", +//t "event_declarators : event_declarators event_declarator", +//t "event_declarator : COMMA IDENTIFIER", +//t "$$52 :", +//t "event_declarator : COMMA IDENTIFIER ASSIGN $$52 event_variable_initializer", +//t "$$53 :", +//t "event_variable_initializer : $$53 variable_initializer", +//t "event_accessor_declarations : add_accessor_declaration remove_accessor_declaration", +//t "event_accessor_declarations : remove_accessor_declaration add_accessor_declaration", +//t "event_accessor_declarations : add_accessor_declaration", +//t "event_accessor_declarations : remove_accessor_declaration", +//t "event_accessor_declarations : error", +//t "$$54 :", +//t "add_accessor_declaration : opt_attributes opt_modifiers ADD $$54 event_accessor_block", +//t "$$55 :", +//t "remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$55 event_accessor_block", +//t "event_accessor_block : opt_semicolon", +//t "event_accessor_block : block", +//t "$$56 :", +//t "$$57 :", +//t "$$58 :", +//t "enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$56 OPEN_BRACE $$57 opt_enum_member_declarations $$58 CLOSE_BRACE opt_semicolon", +//t "opt_enum_base :", +//t "opt_enum_base : COLON type", +//t "opt_enum_base : COLON error", +//t "opt_enum_member_declarations :", +//t "opt_enum_member_declarations : enum_member_declarations", +//t "opt_enum_member_declarations : enum_member_declarations COMMA", +//t "enum_member_declarations : enum_member_declaration", +//t "enum_member_declarations : enum_member_declarations COMMA enum_member_declaration", +//t "enum_member_declaration : opt_attributes IDENTIFIER", +//t "$$59 :", +//t "enum_member_declaration : opt_attributes IDENTIFIER $$59 ASSIGN constant_expression", +//t "$$60 :", +//t "$$61 :", +//t "$$62 :", +//t "delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$60 opt_formal_parameter_list CLOSE_PARENS $$61 opt_type_parameter_constraints_clauses $$62 SEMICOLON", +//t "opt_nullable :", +//t "opt_nullable : INTERR_NULLABLE", +//t "namespace_or_type_name : member_name", +//t "namespace_or_type_name : qualified_alias_member IDENTIFIER opt_type_argument_list", +//t "member_name : type_name", +//t "member_name : namespace_or_type_name DOT IDENTIFIER opt_type_argument_list", +//t "type_name : IDENTIFIER opt_type_argument_list", +//t "opt_type_argument_list :", +//t "opt_type_argument_list : OP_GENERICS_LT type_arguments OP_GENERICS_GT", +//t "opt_type_argument_list : OP_GENERICS_LT error", +//t "type_arguments : type", +//t "type_arguments : type_arguments COMMA type", +//t "$$63 :", +//t "type_declaration_name : IDENTIFIER $$63 opt_type_parameter_list", +//t "member_declaration_name : method_declaration_name", +//t "method_declaration_name : type_declaration_name", +//t "method_declaration_name : explicit_interface IDENTIFIER opt_type_parameter_list", +//t "indexer_declaration_name : THIS", +//t "indexer_declaration_name : explicit_interface THIS", +//t "explicit_interface : IDENTIFIER opt_type_argument_list DOT", +//t "explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list DOT", +//t "explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list DOT", +//t "opt_type_parameter_list :", +//t "opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT", +//t "type_parameters : type_parameter", +//t "type_parameters : type_parameters COMMA type_parameter", +//t "type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER", +//t "type_parameter : error", +//t "type_and_void : type_expression_or_array", +//t "type_and_void : VOID", +//t "member_type : type_and_void", +//t "type : type_expression_or_array", +//t "type : VOID", +//t "simple_type : type_expression", +//t "simple_type : VOID", +//t "parameter_type : type_expression_or_array", +//t "parameter_type : VOID", +//t "type_expression_or_array : type_expression", +//t "type_expression_or_array : type_expression rank_specifiers", +//t "type_expression : namespace_or_type_name opt_nullable", +//t "type_expression : namespace_or_type_name pointer_stars", +//t "type_expression : builtin_types opt_nullable", +//t "type_expression : builtin_types pointer_stars", +//t "type_expression : VOID pointer_stars", +//t "type_list : base_type_name", +//t "type_list : type_list COMMA base_type_name", +//t "base_type_name : type", +//t "base_type_name : error", +//t "builtin_types : OBJECT", +//t "builtin_types : STRING", +//t "builtin_types : BOOL", +//t "builtin_types : DECIMAL", +//t "builtin_types : FLOAT", +//t "builtin_types : DOUBLE", +//t "builtin_types : integral_type", +//t "integral_type : SBYTE", +//t "integral_type : BYTE", +//t "integral_type : SHORT", +//t "integral_type : USHORT", +//t "integral_type : INT", +//t "integral_type : UINT", +//t "integral_type : LONG", +//t "integral_type : ULONG", +//t "integral_type : CHAR", +//t "primary_expression : primary_expression_or_type", +//t "primary_expression : literal", +//t "primary_expression : array_creation_expression", +//t "primary_expression : parenthesized_expression", +//t "primary_expression : default_value_expression", +//t "primary_expression : invocation_expression", +//t "primary_expression : element_access", +//t "primary_expression : this_access", +//t "primary_expression : base_access", +//t "primary_expression : post_increment_expression", +//t "primary_expression : post_decrement_expression", +//t "primary_expression : object_or_delegate_creation_expression", +//t "primary_expression : anonymous_type_expression", +//t "primary_expression : typeof_expression", +//t "primary_expression : sizeof_expression", +//t "primary_expression : checked_expression", +//t "primary_expression : unchecked_expression", +//t "primary_expression : pointer_member_access", +//t "primary_expression : anonymous_method_expression", +//t "primary_expression : undocumented_expressions", +//t "primary_expression_or_type : IDENTIFIER opt_type_argument_list", +//t "primary_expression_or_type : IDENTIFIER GENERATE_COMPLETION", +//t "primary_expression_or_type : member_access", +//t "literal : boolean_literal", +//t "literal : LITERAL", +//t "literal : NULL", +//t "boolean_literal : TRUE", +//t "boolean_literal : FALSE", +//t "open_parens_any : OPEN_PARENS", +//t "open_parens_any : OPEN_PARENS_CAST", +//t "close_parens : CLOSE_PARENS", +//t "close_parens : COMPLETE_COMPLETION", +//t "parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS", +//t "parenthesized_expression : OPEN_PARENS expression COMPLETE_COMPLETION", +//t "member_access : primary_expression DOT IDENTIFIER opt_type_argument_list", +//t "member_access : builtin_types DOT IDENTIFIER opt_type_argument_list", +//t "member_access : BASE DOT IDENTIFIER opt_type_argument_list", +//t "member_access : qualified_alias_member IDENTIFIER opt_type_argument_list", +//t "member_access : primary_expression DOT GENERATE_COMPLETION", +//t "member_access : primary_expression DOT IDENTIFIER GENERATE_COMPLETION", +//t "member_access : builtin_types DOT GENERATE_COMPLETION", +//t "member_access : builtin_types DOT IDENTIFIER GENERATE_COMPLETION", +//t "invocation_expression : primary_expression open_parens_any opt_argument_list close_parens", +//t "opt_object_or_collection_initializer :", +//t "opt_object_or_collection_initializer : object_or_collection_initializer", +//t "object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion", +//t "object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE", +//t "opt_member_initializer_list :", +//t "opt_member_initializer_list : member_initializer_list", +//t "member_initializer_list : member_initializer", +//t "member_initializer_list : member_initializer_list COMMA member_initializer", +//t "member_initializer_list : member_initializer_list error", +//t "member_initializer : IDENTIFIER ASSIGN initializer_value", +//t "member_initializer : GENERATE_COMPLETION", +//t "member_initializer : non_assignment_expression opt_COMPLETE_COMPLETION", +//t "member_initializer : OPEN_BRACE expression_list CLOSE_BRACE", +//t "member_initializer : OPEN_BRACE CLOSE_BRACE", +//t "initializer_value : expression", +//t "initializer_value : object_or_collection_initializer", +//t "opt_argument_list :", +//t "opt_argument_list : argument_list", +//t "argument_list : argument_or_named_argument", +//t "argument_list : argument_list COMMA argument", +//t "argument_list : argument_list COMMA named_argument", +//t "argument_list : argument_list COMMA", +//t "argument_list : COMMA error", +//t "argument : expression", +//t "argument : non_simple_argument", +//t "argument_or_named_argument : argument", +//t "argument_or_named_argument : named_argument", +//t "non_simple_argument : REF variable_reference", +//t "non_simple_argument : OUT variable_reference", +//t "non_simple_argument : ARGLIST OPEN_PARENS argument_list CLOSE_PARENS", +//t "non_simple_argument : ARGLIST OPEN_PARENS CLOSE_PARENS", +//t "variable_reference : expression", +//t "element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET", +//t "expression_list : expression", +//t "expression_list : expression_list COMMA expression", +//t "expression_list : expression_list error", +//t "expression_list_arguments : expression_list_argument", +//t "expression_list_arguments : expression_list_arguments COMMA expression_list_argument", +//t "expression_list_argument : expression", +//t "expression_list_argument : named_argument", +//t "this_access : THIS", +//t "base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET", +//t "base_access : BASE OPEN_BRACKET error", +//t "post_increment_expression : primary_expression OP_INC", +//t "post_decrement_expression : primary_expression OP_DEC", +//t "object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer", +//t "object_or_delegate_creation_expression : NEW new_expr_type object_or_collection_initializer", +//t "array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer", +//t "array_creation_expression : NEW new_expr_type rank_specifiers opt_array_initializer", +//t "array_creation_expression : NEW rank_specifier array_initializer", +//t "array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET", +//t "array_creation_expression : NEW new_expr_type error", +//t "$$64 :", +//t "new_expr_type : $$64 simple_type", +//t "anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE", +//t "anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt", +//t "anonymous_type_parameters_opt_comma : anonymous_type_parameters COMMA", +//t "anonymous_type_parameters_opt :", +//t "anonymous_type_parameters_opt : anonymous_type_parameters", +//t "anonymous_type_parameters : anonymous_type_parameter", +//t "anonymous_type_parameters : anonymous_type_parameters COMMA anonymous_type_parameter", +//t "anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer", +//t "anonymous_type_parameter : IDENTIFIER", +//t "anonymous_type_parameter : member_access", +//t "anonymous_type_parameter : error", +//t "opt_rank_specifier :", +//t "opt_rank_specifier : rank_specifiers", +//t "rank_specifiers : rank_specifier", +//t "rank_specifiers : rank_specifier rank_specifiers", +//t "rank_specifier : OPEN_BRACKET CLOSE_BRACKET", +//t "rank_specifier : OPEN_BRACKET dim_separators CLOSE_BRACKET", +//t "dim_separators : COMMA", +//t "dim_separators : dim_separators COMMA", +//t "opt_array_initializer :", +//t "opt_array_initializer : array_initializer", +//t "array_initializer : OPEN_BRACE CLOSE_BRACE", +//t "array_initializer : OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE", +//t "variable_initializer_list : variable_initializer", +//t "variable_initializer_list : variable_initializer_list COMMA variable_initializer", +//t "$$65 :", +//t "typeof_expression : TYPEOF $$65 open_parens_any typeof_type_expression CLOSE_PARENS", +//t "typeof_type_expression : type_and_void", +//t "typeof_type_expression : unbound_type_name", +//t "typeof_type_expression : error", +//t "unbound_type_name : IDENTIFIER generic_dimension", +//t "unbound_type_name : qualified_alias_member IDENTIFIER generic_dimension", +//t "unbound_type_name : unbound_type_name DOT IDENTIFIER", +//t "unbound_type_name : unbound_type_name DOT IDENTIFIER generic_dimension", +//t "unbound_type_name : namespace_or_type_name DOT IDENTIFIER generic_dimension", +//t "generic_dimension : GENERIC_DIMENSION", +//t "qualified_alias_member : IDENTIFIER DOUBLE_COLON", +//t "sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS", +//t "checked_expression : CHECKED open_parens_any expression CLOSE_PARENS", +//t "unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS", +//t "pointer_member_access : primary_expression OP_PTR IDENTIFIER opt_type_argument_list", +//t "$$66 :", +//t "anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$66 block", +//t "$$67 :", +//t "anonymous_method_expression : ASYNC DELEGATE opt_anonymous_method_signature $$67 block", +//t "opt_anonymous_method_signature :", +//t "opt_anonymous_method_signature : anonymous_method_signature", +//t "$$68 :", +//t "anonymous_method_signature : OPEN_PARENS $$68 opt_formal_parameter_list CLOSE_PARENS", +//t "default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS", +//t "unary_expression : primary_expression", +//t "unary_expression : BANG prefixed_unary_expression", +//t "unary_expression : TILDE prefixed_unary_expression", +//t "unary_expression : cast_expression", +//t "unary_expression : await_expression", +//t "cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression", +//t "await_expression : AWAIT unary_expression", +//t "prefixed_unary_expression : unary_expression", +//t "prefixed_unary_expression : PLUS prefixed_unary_expression", +//t "prefixed_unary_expression : MINUS prefixed_unary_expression", +//t "prefixed_unary_expression : OP_INC prefixed_unary_expression", +//t "prefixed_unary_expression : OP_DEC prefixed_unary_expression", +//t "prefixed_unary_expression : STAR prefixed_unary_expression", +//t "prefixed_unary_expression : BITWISE_AND prefixed_unary_expression", +//t "multiplicative_expression : prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression STAR prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression DIV prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression PERCENT prefixed_unary_expression", +//t "additive_expression : multiplicative_expression", +//t "additive_expression : additive_expression PLUS multiplicative_expression", +//t "additive_expression : additive_expression MINUS multiplicative_expression", +//t "additive_expression : parenthesized_expression MINUS multiplicative_expression", +//t "additive_expression : additive_expression AS type", +//t "additive_expression : additive_expression IS type", +//t "shift_expression : additive_expression", +//t "shift_expression : shift_expression OP_SHIFT_LEFT additive_expression", +//t "shift_expression : shift_expression OP_SHIFT_RIGHT additive_expression", +//t "relational_expression : shift_expression", +//t "relational_expression : relational_expression OP_LT shift_expression", +//t "relational_expression : relational_expression OP_GT shift_expression", +//t "relational_expression : relational_expression OP_LE shift_expression", +//t "relational_expression : relational_expression OP_GE shift_expression", +//t "equality_expression : relational_expression", +//t "equality_expression : equality_expression OP_EQ relational_expression", +//t "equality_expression : equality_expression OP_NE relational_expression", +//t "and_expression : equality_expression", +//t "and_expression : and_expression BITWISE_AND equality_expression", +//t "exclusive_or_expression : and_expression", +//t "exclusive_or_expression : exclusive_or_expression CARRET and_expression", +//t "inclusive_or_expression : exclusive_or_expression", +//t "inclusive_or_expression : inclusive_or_expression BITWISE_OR exclusive_or_expression", +//t "conditional_and_expression : inclusive_or_expression", +//t "conditional_and_expression : conditional_and_expression OP_AND inclusive_or_expression", +//t "conditional_or_expression : conditional_and_expression", +//t "conditional_or_expression : conditional_or_expression OP_OR conditional_and_expression", +//t "null_coalescing_expression : conditional_or_expression", +//t "null_coalescing_expression : conditional_or_expression OP_COALESCING null_coalescing_expression", +//t "conditional_expression : null_coalescing_expression", +//t "conditional_expression : null_coalescing_expression INTERR expression COLON expression", +//t "assignment_expression : prefixed_unary_expression ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_AND_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_OR_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN expression", +//t "lambda_parameter_list : lambda_parameter", +//t "lambda_parameter_list : lambda_parameter_list COMMA lambda_parameter", +//t "lambda_parameter : parameter_modifier parameter_type IDENTIFIER", +//t "lambda_parameter : parameter_type IDENTIFIER", +//t "lambda_parameter : IDENTIFIER", +//t "opt_lambda_parameter_list :", +//t "opt_lambda_parameter_list : lambda_parameter_list", +//t "lambda_expression_body : lambda_expression_body_simple", +//t "lambda_expression_body : block", +//t "$$69 :", +//t "lambda_expression_body_simple : $$69 expression_or_error", +//t "expression_or_error : expression", +//t "expression_or_error : error", +//t "$$70 :", +//t "lambda_expression : IDENTIFIER ARROW $$70 lambda_expression_body", +//t "$$71 :", +//t "lambda_expression : ASYNC IDENTIFIER ARROW $$71 lambda_expression_body", +//t "$$72 :", +//t "$$73 :", +//t "lambda_expression : OPEN_PARENS_LAMBDA $$72 opt_lambda_parameter_list CLOSE_PARENS ARROW $$73 lambda_expression_body", +//t "$$74 :", +//t "$$75 :", +//t "lambda_expression : ASYNC OPEN_PARENS_LAMBDA $$74 opt_lambda_parameter_list CLOSE_PARENS ARROW $$75 lambda_expression_body", +//t "expression : assignment_expression", +//t "expression : non_assignment_expression", +//t "non_assignment_expression : conditional_expression", +//t "non_assignment_expression : lambda_expression", +//t "non_assignment_expression : query_expression", +//t "non_assignment_expression : ARGLIST", +//t "undocumented_expressions : REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS", +//t "undocumented_expressions : REFTYPE open_parens_any expression CLOSE_PARENS", +//t "undocumented_expressions : MAKEREF open_parens_any expression CLOSE_PARENS", +//t "constant_expression : expression", +//t "boolean_expression : expression", +//t "$$76 :", +//t "$$77 :", +//t "$$78 :", +//t "$$79 :", +//t "class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$76 type_declaration_name $$77 opt_class_base opt_type_parameter_constraints_clauses $$78 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$79 opt_semicolon", +//t "opt_partial :", +//t "opt_partial : PARTIAL", +//t "opt_modifiers :", +//t "opt_modifiers : modifiers", +//t "modifiers : modifier", +//t "modifiers : modifiers modifier", +//t "modifier : NEW", +//t "modifier : PUBLIC", +//t "modifier : PROTECTED", +//t "modifier : INTERNAL", +//t "modifier : PRIVATE", +//t "modifier : ABSTRACT", +//t "modifier : SEALED", +//t "modifier : STATIC", +//t "modifier : READONLY", +//t "modifier : VIRTUAL", +//t "modifier : OVERRIDE", +//t "modifier : EXTERN", +//t "modifier : VOLATILE", +//t "modifier : UNSAFE", +//t "modifier : ASYNC", +//t "opt_class_base :", +//t "opt_class_base : COLON type_list", +//t "opt_type_parameter_constraints_clauses :", +//t "opt_type_parameter_constraints_clauses : type_parameter_constraints_clauses", +//t "opt_type_parameter_constraints_clauses : error", +//t "type_parameter_constraints_clauses : type_parameter_constraints_clause", +//t "type_parameter_constraints_clauses : type_parameter_constraints_clauses type_parameter_constraints_clause", +//t "type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints", +//t "type_parameter_constraints : type_parameter_constraint", +//t "type_parameter_constraints : type_parameter_constraints COMMA type_parameter_constraint", +//t "type_parameter_constraint : type", +//t "type_parameter_constraint : NEW OPEN_PARENS CLOSE_PARENS", +//t "type_parameter_constraint : CLASS", +//t "type_parameter_constraint : STRUCT", +//t "opt_type_parameter_variance :", +//t "opt_type_parameter_variance : type_parameter_variance", +//t "type_parameter_variance : OUT", +//t "type_parameter_variance : IN", +//t "$$80 :", +//t "block : OPEN_BRACE $$80 opt_statement_list block_end", +//t "block_end : CLOSE_BRACE", +//t "block_end : COMPLETE_COMPLETION", +//t "$$81 :", +//t "block_prepared : OPEN_BRACE $$81 opt_statement_list CLOSE_BRACE", +//t "opt_statement_list :", +//t "opt_statement_list : statement_list", +//t "statement_list : statement", +//t "statement_list : statement_list statement", +//t "statement : block_variable_declaration", +//t "statement : valid_declaration_statement", +//t "statement : labeled_statement", +//t "statement : error", +//t "interactive_statement_list : interactive_statement", +//t "interactive_statement_list : interactive_statement_list interactive_statement", +//t "interactive_statement : block_variable_declaration", +//t "interactive_statement : interactive_valid_declaration_statement", +//t "interactive_statement : labeled_statement", +//t "valid_declaration_statement : block", +//t "valid_declaration_statement : empty_statement", +//t "valid_declaration_statement : expression_statement", +//t "valid_declaration_statement : selection_statement", +//t "valid_declaration_statement : iteration_statement", +//t "valid_declaration_statement : jump_statement", +//t "valid_declaration_statement : try_statement", +//t "valid_declaration_statement : checked_statement", +//t "valid_declaration_statement : unchecked_statement", +//t "valid_declaration_statement : lock_statement", +//t "valid_declaration_statement : using_statement", +//t "valid_declaration_statement : unsafe_statement", +//t "valid_declaration_statement : fixed_statement", +//t "interactive_valid_declaration_statement : block", +//t "interactive_valid_declaration_statement : empty_statement", +//t "interactive_valid_declaration_statement : interactive_expression_statement", +//t "interactive_valid_declaration_statement : selection_statement", +//t "interactive_valid_declaration_statement : iteration_statement", +//t "interactive_valid_declaration_statement : jump_statement", +//t "interactive_valid_declaration_statement : try_statement", +//t "interactive_valid_declaration_statement : checked_statement", +//t "interactive_valid_declaration_statement : unchecked_statement", +//t "interactive_valid_declaration_statement : lock_statement", +//t "interactive_valid_declaration_statement : using_statement", +//t "interactive_valid_declaration_statement : unsafe_statement", +//t "interactive_valid_declaration_statement : fixed_statement", +//t "embedded_statement : valid_declaration_statement", +//t "embedded_statement : block_variable_declaration", +//t "embedded_statement : labeled_statement", +//t "embedded_statement : error", +//t "empty_statement : SEMICOLON", +//t "$$82 :", +//t "labeled_statement : IDENTIFIER COLON $$82 statement", +//t "variable_type : variable_type_simple", +//t "variable_type : variable_type_simple rank_specifiers", +//t "variable_type_simple : primary_expression_or_type opt_nullable", +//t "variable_type_simple : primary_expression_or_type pointer_stars", +//t "variable_type_simple : builtin_types opt_nullable", +//t "variable_type_simple : builtin_types pointer_stars", +//t "variable_type_simple : VOID pointer_stars", +//t "variable_type_simple : VOID", +//t "pointer_stars : pointer_star", +//t "pointer_stars : pointer_star pointer_stars", +//t "pointer_star : STAR", +//t "$$83 :", +//t "block_variable_declaration : variable_type IDENTIFIER $$83 opt_local_variable_initializer opt_variable_declarators SEMICOLON", +//t "$$84 :", +//t "block_variable_declaration : CONST variable_type IDENTIFIER $$84 const_variable_initializer opt_const_declarators SEMICOLON", +//t "opt_local_variable_initializer :", +//t "opt_local_variable_initializer : ASSIGN block_variable_initializer", +//t "opt_local_variable_initializer : error", +//t "opt_variable_declarators :", +//t "opt_variable_declarators : variable_declarators", +//t "variable_declarators : variable_declarator", +//t "variable_declarators : variable_declarators variable_declarator", +//t "variable_declarator : COMMA IDENTIFIER", +//t "variable_declarator : COMMA IDENTIFIER ASSIGN block_variable_initializer", +//t "const_variable_initializer :", +//t "const_variable_initializer : ASSIGN constant_initializer_expr", +//t "opt_const_declarators :", +//t "opt_const_declarators : const_declarators", +//t "const_declarators : const_declarator", +//t "const_declarators : const_declarators const_declarator", +//t "const_declarator : COMMA IDENTIFIER ASSIGN constant_initializer_expr", +//t "block_variable_initializer : variable_initializer", +//t "block_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET", +//t "block_variable_initializer : STACKALLOC simple_type", +//t "expression_statement : statement_expression SEMICOLON", +//t "expression_statement : statement_expression COMPLETE_COMPLETION", +//t "interactive_expression_statement : interactive_statement_expression SEMICOLON", +//t "interactive_expression_statement : interactive_statement_expression COMPLETE_COMPLETION", +//t "statement_expression : expression", +//t "interactive_statement_expression : expression", +//t "interactive_statement_expression : error", +//t "selection_statement : if_statement", +//t "selection_statement : switch_statement", +//t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement", +//t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement", +//t "$$85 :", +//t "switch_statement : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE $$85 opt_switch_sections CLOSE_BRACE", +//t "opt_switch_sections :", +//t "opt_switch_sections : switch_sections", +//t "switch_sections : switch_section", +//t "switch_sections : switch_sections switch_section", +//t "switch_sections : error", +//t "$$86 :", +//t "switch_section : switch_labels $$86 statement_list", +//t "switch_labels : switch_label", +//t "switch_labels : switch_labels switch_label", +//t "switch_label : CASE constant_expression COLON", +//t "switch_label : DEFAULT_COLON", +//t "iteration_statement : while_statement", +//t "iteration_statement : do_statement", +//t "iteration_statement : for_statement", +//t "iteration_statement : foreach_statement", +//t "while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement", +//t "do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON", +//t "$$87 :", +//t "for_statement : FOR open_parens_any $$87 for_statement_cont", +//t "for_statement_cont : opt_for_initializer SEMICOLON opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement", +//t "for_statement_cont : error", +//t "opt_for_initializer :", +//t "opt_for_initializer : for_initializer", +//t "$$88 :", +//t "for_initializer : variable_type IDENTIFIER $$88 opt_local_variable_initializer opt_variable_declarators", +//t "for_initializer : statement_expression_list", +//t "opt_for_condition :", +//t "opt_for_condition : boolean_expression", +//t "opt_for_iterator :", +//t "opt_for_iterator : for_iterator", +//t "for_iterator : statement_expression_list", +//t "statement_expression_list : statement_expression", +//t "statement_expression_list : statement_expression_list COMMA statement_expression", +//t "foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS", +//t "$$89 :", +//t "foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$89 embedded_statement", +//t "jump_statement : break_statement", +//t "jump_statement : continue_statement", +//t "jump_statement : goto_statement", +//t "jump_statement : return_statement", +//t "jump_statement : throw_statement", +//t "jump_statement : yield_statement", +//t "break_statement : BREAK SEMICOLON", +//t "continue_statement : CONTINUE SEMICOLON", +//t "goto_statement : GOTO IDENTIFIER SEMICOLON", +//t "goto_statement : GOTO CASE constant_expression SEMICOLON", +//t "goto_statement : GOTO DEFAULT SEMICOLON", +//t "return_statement : RETURN opt_expression SEMICOLON", +//t "throw_statement : THROW opt_expression SEMICOLON", +//t "yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON", +//t "yield_statement : IDENTIFIER BREAK SEMICOLON", +//t "opt_expression :", +//t "opt_expression : expression", +//t "try_statement : TRY block catch_clauses", +//t "try_statement : TRY block FINALLY block", +//t "try_statement : TRY block catch_clauses FINALLY block", +//t "try_statement : TRY block error", +//t "catch_clauses : catch_clause", +//t "catch_clauses : catch_clauses catch_clause", +//t "opt_identifier :", +//t "opt_identifier : IDENTIFIER", +//t "catch_clause : CATCH block", +//t "$$90 :", +//t "catch_clause : CATCH open_parens_any type opt_identifier CLOSE_PARENS $$90 block_prepared", +//t "catch_clause : CATCH open_parens_any error", +//t "checked_statement : CHECKED block", +//t "unchecked_statement : UNCHECKED block", +//t "$$91 :", +//t "unsafe_statement : UNSAFE $$91 block", +//t "lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement", +//t "$$92 :", +//t "$$93 :", +//t "fixed_statement : FIXED open_parens_any variable_type IDENTIFIER $$92 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$93 embedded_statement", +//t "$$94 :", +//t "$$95 :", +//t "using_statement : USING open_parens_any variable_type IDENTIFIER $$94 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$95 embedded_statement", +//t "using_statement : USING open_parens_any expression CLOSE_PARENS embedded_statement", +//t "using_or_fixed_variable_initializer :", +//t "using_or_fixed_variable_initializer : ASSIGN variable_initializer", +//t "query_expression : first_from_clause query_body", +//t "query_expression : nested_from_clause query_body", +//t "query_expression : first_from_clause COMPLETE_COMPLETION", +//t "query_expression : nested_from_clause COMPLETE_COMPLETION", +//t "first_from_clause : FROM_FIRST IDENTIFIER IN expression", +//t "first_from_clause : FROM_FIRST type IDENTIFIER IN expression", +//t "nested_from_clause : FROM IDENTIFIER IN expression", +//t "nested_from_clause : FROM type IDENTIFIER IN expression", +//t "$$96 :", +//t "from_clause : FROM IDENTIFIER IN $$96 expression", +//t "$$97 :", +//t "from_clause : FROM type IDENTIFIER IN $$97 expression", +//t "query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation", +//t "query_body : opt_query_body_clauses COMPLETE_COMPLETION", +//t "query_body : error", +//t "$$98 :", +//t "select_or_group_clause : SELECT $$98 expression", +//t "$$99 :", +//t "$$100 :", +//t "select_or_group_clause : GROUP $$99 expression $$100 BY expression", +//t "opt_query_body_clauses :", +//t "opt_query_body_clauses : query_body_clauses", +//t "query_body_clauses : query_body_clause", +//t "query_body_clauses : query_body_clauses query_body_clause", +//t "query_body_clause : from_clause", +//t "query_body_clause : let_clause", +//t "query_body_clause : where_clause", +//t "query_body_clause : join_clause", +//t "query_body_clause : orderby_clause", +//t "$$101 :", +//t "let_clause : LET IDENTIFIER ASSIGN $$101 expression", +//t "$$102 :", +//t "where_clause : WHERE $$102 expression", +//t "$$103 :", +//t "$$104 :", +//t "$$105 :", +//t "join_clause : JOIN IDENTIFIER IN $$103 expression ON $$104 expression EQUALS $$105 expression opt_join_into", +//t "$$106 :", +//t "$$107 :", +//t "$$108 :", +//t "join_clause : JOIN type IDENTIFIER IN $$106 expression ON $$107 expression EQUALS $$108 expression opt_join_into", +//t "opt_join_into :", +//t "opt_join_into : INTO IDENTIFIER", +//t "$$109 :", +//t "orderby_clause : ORDERBY $$109 orderings", +//t "orderings : order_by", +//t "$$110 :", +//t "orderings : order_by COMMA $$110 orderings_then_by", +//t "orderings_then_by : then_by", +//t "$$111 :", +//t "orderings_then_by : orderings_then_by COMMA $$111 then_by", +//t "order_by : expression", +//t "order_by : expression ASCENDING", +//t "order_by : expression DESCENDING", +//t "then_by : expression", +//t "then_by : expression ASCENDING", +//t "then_by : expression DESCENDING", +//t "opt_query_continuation :", +//t "$$112 :", +//t "opt_query_continuation : INTO IDENTIFIER $$112 query_body", +//t "interactive_parsing : EVAL_STATEMENT_PARSER EOF", +//t "interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION", +//t "$$113 :", +//t "interactive_parsing : EVAL_STATEMENT_PARSER $$113 interactive_statement_list opt_COMPLETE_COMPLETION", +//t "interactive_parsing : EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit", +//t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives", +//t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives namespace_or_type_declarations", +//t "opt_COMPLETE_COMPLETION :", +//t "opt_COMPLETE_COMPLETION : COMPLETE_COMPLETION", +//t "close_brace_or_complete_completion : CLOSE_BRACE", +//t "close_brace_or_complete_completion : COMPLETE_COMPLETION", +//t "documentation_parsing : DOC_SEE doc_cref", +//t "doc_cref : doc_type_declaration_name opt_doc_method_sig", +//t "doc_cref : builtin_types opt_doc_method_sig", +//t "doc_cref : builtin_types DOT IDENTIFIER opt_doc_method_sig", +//t "doc_cref : doc_type_declaration_name DOT THIS", +//t "$$114 :", +//t "doc_cref : doc_type_declaration_name DOT THIS OPEN_BRACKET $$114 opt_doc_parameters CLOSE_BRACKET", +//t "doc_cref : EXPLICIT OPERATOR type opt_doc_method_sig", +//t "doc_cref : IMPLICIT OPERATOR type opt_doc_method_sig", +//t "doc_cref : OPERATOR overloadable_operator opt_doc_method_sig", +//t "doc_type_declaration_name : type_declaration_name", +//t "doc_type_declaration_name : doc_type_declaration_name DOT type_declaration_name", +//t "opt_doc_method_sig :", +//t "$$115 :", +//t "opt_doc_method_sig : OPEN_PARENS $$115 opt_doc_parameters CLOSE_PARENS", +//t "opt_doc_parameters :", +//t "opt_doc_parameters : doc_parameters", +//t "doc_parameters : doc_parameter", +//t "doc_parameters : doc_parameters COMMA doc_parameter", +//t "doc_parameter : opt_parameter_modifier parameter_type", +//t }; +//t public static string getRule (int index) { +//t return yyRule [index]; +//t } +//t} + protected static readonly string [] yyNames = { + "end-of-file",null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,"EOF","NONE","ERROR", + "FIRST_KEYWORD","ABSTRACT","AS","ADD","BASE","BOOL","BREAK","BYTE", + "CASE","CATCH","CHAR","CHECKED","CLASS","CONST","CONTINUE","DECIMAL", + "DEFAULT","DELEGATE","DO","DOUBLE","ELSE","ENUM","EVENT","EXPLICIT", + "EXTERN","FALSE","FINALLY","FIXED","FLOAT","FOR","FOREACH","GOTO", + "IF","IMPLICIT","IN","INT","INTERFACE","INTERNAL","IS","LOCK","LONG", + "NAMESPACE","NEW","NULL","OBJECT","OPERATOR","OUT","OVERRIDE", + "PARAMS","PRIVATE","PROTECTED","PUBLIC","READONLY","REF","RETURN", + "REMOVE","SBYTE","SEALED","SHORT","SIZEOF","STACKALLOC","STATIC", + "STRING","STRUCT","SWITCH","THIS","THROW","TRUE","TRY","TYPEOF", + "UINT","ULONG","UNCHECKED","UNSAFE","USHORT","USING","VIRTUAL","VOID", + "VOLATILE","WHERE","WHILE","ARGLIST","PARTIAL","ARROW","FROM", + "FROM_FIRST","JOIN","ON","EQUALS","SELECT","GROUP","BY","LET", + "ORDERBY","ASCENDING","DESCENDING","INTO","INTERR_NULLABLE", + "EXTERN_ALIAS","REFVALUE","REFTYPE","MAKEREF","ASYNC","AWAIT","GET", + "SET","LAST_KEYWORD","OPEN_BRACE","CLOSE_BRACE","OPEN_BRACKET", + "CLOSE_BRACKET","OPEN_PARENS","CLOSE_PARENS","DOT","COMMA","COLON", + "SEMICOLON","TILDE","PLUS","MINUS","BANG","ASSIGN","OP_LT","OP_GT", + "BITWISE_AND","BITWISE_OR","STAR","PERCENT","DIV","CARRET","INTERR", + "DOUBLE_COLON","OP_INC","OP_DEC","OP_SHIFT_LEFT","OP_SHIFT_RIGHT", + "OP_LE","OP_GE","OP_EQ","OP_NE","OP_AND","OP_OR","OP_MULT_ASSIGN", + "OP_DIV_ASSIGN","OP_MOD_ASSIGN","OP_ADD_ASSIGN","OP_SUB_ASSIGN", + "OP_SHIFT_LEFT_ASSIGN","OP_SHIFT_RIGHT_ASSIGN","OP_AND_ASSIGN", + "OP_XOR_ASSIGN","OP_OR_ASSIGN","OP_PTR","OP_COALESCING", + "OP_GENERICS_LT","OP_GENERICS_LT_DECL","OP_GENERICS_GT","LITERAL", + "IDENTIFIER","OPEN_PARENS_LAMBDA","OPEN_PARENS_CAST", + "GENERIC_DIMENSION","DEFAULT_COLON","OPEN_BRACKET_EXPR", + "EVAL_STATEMENT_PARSER","EVAL_COMPILATION_UNIT_PARSER", + "EVAL_USING_DECLARATIONS_UNIT_PARSER","DOC_SEE","GENERATE_COMPLETION", + "COMPLETE_COMPLETION","UMINUS", + }; + + /** index-checked interface to yyNames[]. + @param token single character or %token value. + @return token name or [illegal] or [unknown]. + */ +//t public static string yyname (int token) { +//t if ((token < 0) || (token > yyNames.Length)) return "[illegal]"; +//t string name; +//t if ((name = yyNames[token]) != null) return name; +//t return "[unknown]"; +//t } + + int yyExpectingState; + /** computes list of expected tokens on error by tracing the tables. + @param state for which to compute the list. + @return list of token names. + */ + protected int [] yyExpectingTokens (int state){ + int token, n, len = 0; + bool[] ok = new bool[yyNames.Length]; + if ((n = yySindex[state]) != 0) + for (token = n < 0 ? -n : 0; + (token < yyNames.Length) && (n+token < yyTable.Length); ++ token) + if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { + ++ len; + ok[token] = true; + } + if ((n = yyRindex[state]) != 0) + for (token = n < 0 ? -n : 0; + (token < yyNames.Length) && (n+token < yyTable.Length); ++ token) + if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { + ++ len; + ok[token] = true; + } + int [] result = new int [len]; + for (n = token = 0; n < len; ++ token) + if (ok[token]) result[n++] = token; + return result; + } + protected string[] yyExpecting (int state) { + int [] tokens = yyExpectingTokens (state); + string [] result = new string[tokens.Length]; + for (int n = 0; n < tokens.Length; n++) + result[n++] = yyNames[tokens [n]]; + return result; + } + + /** the generated parser, with debugging messages. + Maintains a state and a value stack, currently with fixed maximum size. + @param yyLex scanner. + @param yydebug debug message writer implementing yyDebug, or null. + @return result of the last reduction, if any. + @throws yyException on irrecoverable parse error. + */ + internal Object yyparse (yyParser.yyInput yyLex, Object yyd) + { +//t this.debug = (yydebug.yyDebug)yyd; + return yyparse(yyLex); + } + + /** initial size and increment of the state/value stack [default 256]. + This is not final so that it can be overwritten outside of invocations + of yyparse(). + */ + protected int yyMax; + + /** executed at the beginning of a reduce action. + Used as $$ = yyDefault($1), prior to the user-specified action, if any. + Can be overwritten to provide deep copy, etc. + @param first value for $1, or null. + @return first. + */ + protected Object yyDefault (Object first) { + return first; + } + + static int[] global_yyStates; + static object[] global_yyVals; + protected bool use_global_stacks; + object[] yyVals; // value stack + object yyVal; // value stack ptr + int yyToken; // current input + int yyTop; + + /** the generated parser. + Maintains a state and a value stack, currently with fixed maximum size. + @param yyLex scanner. + @return result of the last reduction, if any. + @throws yyException on irrecoverable parse error. + */ + internal Object yyparse (yyParser.yyInput yyLex) + { + if (yyMax <= 0) yyMax = 256; // initial size + int yyState = 0; // state stack ptr + int [] yyStates; // state stack + yyVal = null; + yyToken = -1; + int yyErrorFlag = 0; // #tks to shift + if (use_global_stacks && global_yyStates != null) { + yyVals = global_yyVals; + yyStates = global_yyStates; + } else { + yyVals = new object [yyMax]; + yyStates = new int [yyMax]; + if (use_global_stacks) { + global_yyVals = yyVals; + global_yyStates = yyStates; + } + } + + /*yyLoop:*/ for (yyTop = 0;; ++ yyTop) { + if (yyTop >= yyStates.Length) { // dynamically increase + global::System.Array.Resize (ref yyStates, yyStates.Length+yyMax); + global::System.Array.Resize (ref yyVals, yyVals.Length+yyMax); + } + yyStates[yyTop] = yyState; + yyVals[yyTop] = yyVal; +//t if (debug != null) debug.push(yyState, yyVal); + + /*yyDiscarded:*/ while (true) { // discarding a token does not change stack + int yyN; + if ((yyN = yyDefRed[yyState]) == 0) { // else [default] reduce (yyN) + if (yyToken < 0) { + yyToken = yyLex.advance() ? yyLex.token() : 0; +//t if (debug != null) +//t debug.lex(yyState, yyToken, yyname(yyToken), yyLex.value()); + } + if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0) + && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) { +//t if (debug != null) +//t debug.shift(yyState, yyTable[yyN], yyErrorFlag-1); + yyState = yyTable[yyN]; // shift to yyN + yyVal = yyLex.value(); + yyToken = -1; + if (yyErrorFlag > 0) -- yyErrorFlag; + goto continue_yyLoop; + } + if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0 + && yyN < yyTable.Length && yyCheck[yyN] == yyToken) + yyN = yyTable[yyN]; // reduce (yyN) + else + switch (yyErrorFlag) { + + case 0: + yyExpectingState = yyState; + // yyerror(String.Format ("syntax error, got token `{0}'", yyname (yyToken)), yyExpecting(yyState)); +//t if (debug != null) debug.error("syntax error"); + if (yyToken == 0 /*eof*/ || yyToken == eof_token) throw new yyParser.yyUnexpectedEof (); + goto case 1; + case 1: case 2: + yyErrorFlag = 3; + do { + if ((yyN = yySindex[yyStates[yyTop]]) != 0 + && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length + && yyCheck[yyN] == Token.yyErrorCode) { +//t if (debug != null) +//t debug.shift(yyStates[yyTop], yyTable[yyN], 3); + yyState = yyTable[yyN]; + yyVal = yyLex.value(); + goto continue_yyLoop; + } +//t if (debug != null) debug.pop(yyStates[yyTop]); + } while (-- yyTop >= 0); +//t if (debug != null) debug.reject(); + throw new yyParser.yyException("irrecoverable syntax error"); + + case 3: + if (yyToken == 0) { +//t if (debug != null) debug.reject(); + throw new yyParser.yyException("irrecoverable syntax error at end-of-file"); + } +//t if (debug != null) +//t debug.discard(yyState, yyToken, yyname(yyToken), +//t yyLex.value()); + yyToken = -1; + goto continue_yyDiscarded; // leave stack alone + } + } + int yyV = yyTop + 1-yyLen[yyN]; +//t if (debug != null) +//t debug.reduce(yyState, yyStates[yyV-1], yyN, YYRules.getRule (yyN), yyLen[yyN]); + yyVal = yyV > yyTop ? null : yyVals[yyV]; // yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]); + switch (yyN) { +case 1: +#line 395 "cs-parser.jay" + { + Lexer.check_incorrect_doc_comment (); + } + break; +case 2: +#line 396 "cs-parser.jay" + { Lexer.CompleteOnEOF = false; } + break; +case 6: + case_6(); + break; +case 7: +#line 413 "cs-parser.jay" + { + module.AddAttributes ((Attributes) yyVals[0+yyTop], current_namespace); + } + break; +case 8: + case_8(); + break; +case 13: + case_13(); + break; +case 14: +#line 451 "cs-parser.jay" + { + syntax_error (GetLocation (yyVals[-1+yyTop]), "`alias' expected"); /* TODO: better*/ + } + break; +case 17: + case_17(); + break; +case 18: + case_18(); + break; +case 19: + case_19(); + break; +case 20: + case_20(); + break; +case 21: + case_21(); + break; +case 22: + case_22(); + break; +case 23: + case_23(); + break; +case 24: + case_24(); + break; +case 25: + case_25(); + break; +case 26: + case_26(); + break; +case 27: + case_27(); + break; +case 32: + case_32(); + break; +case 41: + case_41(); + break; +case 42: +#line 640 "cs-parser.jay" + { + current_namespace.DeclarationFound = true; + } + break; +case 50: + case_50(); + break; +case 51: + case_51(); + break; +case 52: + case_52(); + break; +case 53: + case_53(); + break; +case 54: + case_54(); + break; +case 55: + case_55(); + break; +case 56: + case_56(); + break; +case 57: + case_57(); + break; +case 58: +#line 733 "cs-parser.jay" + { yyVal = "event"; } + break; +case 59: +#line 734 "cs-parser.jay" + { yyVal = "return"; } + break; +case 60: + case_60(); + break; +case 61: +#line 751 "cs-parser.jay" + { + yyVal = new List (4) { (Attribute) yyVals[0+yyTop] }; + } + break; +case 62: + case_62(); + break; +case 63: +#line 765 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 64: + case_64(); + break; +case 66: +#line 789 "cs-parser.jay" + { yyVal = null; } + break; +case 67: + case_67(); + break; +case 68: +#line 800 "cs-parser.jay" + { yyVal = null; } + break; +case 69: + case_69(); + break; +case 70: + case_70(); + break; +case 71: + case_71(); + break; +case 72: + case_72(); + break; +case 73: +#line 844 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 75: +#line 852 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 76: + case_76(); + break; +case 77: + case_77(); + break; +case 78: +#line 877 "cs-parser.jay" + { yyVal = null; } + break; +case 79: +#line 881 "cs-parser.jay" + { + yyVal = Argument.AType.Ref; + } + break; +case 80: +#line 885 "cs-parser.jay" + { + yyVal = Argument.AType.Out; + } + break; +case 95: + case_95(); + break; +case 96: +#line 926 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 97: + case_97(); + break; +case 98: + case_98(); + break; +case 99: + case_99(); + break; +case 100: + case_100(); + break; +case 101: +#line 958 "cs-parser.jay" + { + Error_SyntaxError (yyToken); + } + break; +case 102: + case_102(); + break; +case 103: +#line 970 "cs-parser.jay" + { + lbag.AppendToMember (current_class, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + break; +case 118: + case_118(); + break; +case 119: + case_119(); + break; +case 122: +#line 1039 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 123: +#line 1043 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 124: + case_124(); + break; +case 125: +#line 1059 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 126: + case_126(); + break; +case 127: + case_127(); + break; +case 130: + case_130(); + break; +case 131: + case_131(); + break; +case 132: + case_132(); + break; +case 133: + case_133(); + break; +case 134: +#line 1138 "cs-parser.jay" + { + report.Error (1641, GetLocation (yyVals[-1+yyTop]), "A fixed size buffer field must have the array size specifier after the field name"); + } + break; +case 136: + case_136(); + break; +case 137: + case_137(); + break; +case 140: +#line 1168 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 141: +#line 1172 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 142: + case_142(); + break; +case 143: +#line 1185 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 144: + case_144(); + break; +case 147: +#line 1204 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 148: +#line 1208 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 149: + case_149(); + break; +case 150: +#line 1224 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 151: + case_151(); + break; +case 152: + case_152(); + break; +case 155: + case_155(); + break; +case 156: + case_156(); + break; +case 157: + case_157(); + break; +case 158: +#line 1291 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.All; + } + break; +case 159: +#line 1295 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 160: + case_160(); + break; +case 161: +#line 1335 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 162: + case_162(); + break; +case 163: +#line 1345 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 164: + case_164(); + break; +case 165: + case_165(); + break; +case 167: +#line 1419 "cs-parser.jay" + { yyVal = null; } + break; +case 168: +#line 1423 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + break; +case 170: + case_170(); + break; +case 171: + case_171(); + break; +case 172: + case_172(); + break; +case 173: + case_173(); + break; +case 174: + case_174(); + break; +case 175: + case_175(); + break; +case 176: + case_176(); + break; +case 177: +#line 1482 "cs-parser.jay" + { + yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[0+yyTop] } ); + } + break; +case 178: +#line 1486 "cs-parser.jay" + { + yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[0+yyTop])) }, true); + } + break; +case 179: + case_179(); + break; +case 180: + case_180(); + break; +case 181: + case_181(); + break; +case 182: + case_182(); + break; +case 183: + case_183(); + break; +case 184: + case_184(); + break; +case 185: +#line 1561 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 186: + case_186(); + break; +case 187: +#line 1602 "cs-parser.jay" + { yyVal = Parameter.Modifier.NONE; } + break; +case 189: + case_189(); + break; +case 190: + case_190(); + break; +case 191: + case_191(); + break; +case 192: + case_192(); + break; +case 193: + case_193(); + break; +case 194: + case_194(); + break; +case 195: + case_195(); + break; +case 196: + case_196(); + break; +case 197: + case_197(); + break; +case 198: + case_198(); + break; +case 199: +#line 1700 "cs-parser.jay" + { + Error_DuplicateParameterModifier (GetLocation (yyVals[-1+yyTop]), Parameter.Modifier.PARAMS); + } + break; +case 200: + case_200(); + break; +case 201: + case_201(); + break; +case 202: + case_202(); + break; +case 203: + case_203(); + break; +case 204: + case_204(); + break; +case 205: +#line 1754 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + break; +case 206: + case_206(); + break; +case 207: +#line 1783 "cs-parser.jay" + { + lexer.PropertyParsing = false; + } + break; +case 208: + case_208(); + break; +case 213: + case_213(); + break; +case 214: + case_214(); + break; +case 215: + case_215(); + break; +case 216: + case_216(); + break; +case 217: + case_217(); + break; +case 219: + case_219(); + break; +case 220: + case_220(); + break; +case 221: +#line 1928 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 222: + case_222(); + break; +case 223: + case_223(); + break; +case 224: + case_224(); + break; +case 225: + case_225(); + break; +case 226: +#line 1961 "cs-parser.jay" + { + Error_SyntaxError (yyToken); + } + break; +case 231: +#line 1978 "cs-parser.jay" + { + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + } + break; +case 232: +#line 1982 "cs-parser.jay" + { + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + } + break; +case 237: +#line 1990 "cs-parser.jay" + { + report.Error (567, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain operators"); + } + break; +case 238: +#line 1994 "cs-parser.jay" + { + report.Error (526, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain contructors"); + } + break; +case 239: +#line 1998 "cs-parser.jay" + { + report.Error (524, GetLocation (yyVals[0+yyTop]), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); + } + break; +case 240: +#line 2004 "cs-parser.jay" + { + } + break; +case 241: + case_241(); + break; +case 243: +#line 2034 "cs-parser.jay" + { yyVal = null; } + break; +case 245: + case_245(); + break; +case 246: +#line 2050 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 247: + case_247(); + break; +case 249: +#line 2096 "cs-parser.jay" + { yyVal = Operator.OpType.LogicalNot; } + break; +case 250: +#line 2097 "cs-parser.jay" + { yyVal = Operator.OpType.OnesComplement; } + break; +case 251: +#line 2098 "cs-parser.jay" + { yyVal = Operator.OpType.Increment; } + break; +case 252: +#line 2099 "cs-parser.jay" + { yyVal = Operator.OpType.Decrement; } + break; +case 253: +#line 2100 "cs-parser.jay" + { yyVal = Operator.OpType.True; } + break; +case 254: +#line 2101 "cs-parser.jay" + { yyVal = Operator.OpType.False; } + break; +case 255: +#line 2103 "cs-parser.jay" + { yyVal = Operator.OpType.Addition; } + break; +case 256: +#line 2104 "cs-parser.jay" + { yyVal = Operator.OpType.Subtraction; } + break; +case 257: +#line 2106 "cs-parser.jay" + { yyVal = Operator.OpType.Multiply; } + break; +case 258: +#line 2107 "cs-parser.jay" + { yyVal = Operator.OpType.Division; } + break; +case 259: +#line 2108 "cs-parser.jay" + { yyVal = Operator.OpType.Modulus; } + break; +case 260: +#line 2109 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseAnd; } + break; +case 261: +#line 2110 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseOr; } + break; +case 262: +#line 2111 "cs-parser.jay" + { yyVal = Operator.OpType.ExclusiveOr; } + break; +case 263: +#line 2112 "cs-parser.jay" + { yyVal = Operator.OpType.LeftShift; } + break; +case 264: +#line 2113 "cs-parser.jay" + { yyVal = Operator.OpType.RightShift; } + break; +case 265: +#line 2114 "cs-parser.jay" + { yyVal = Operator.OpType.Equality; } + break; +case 266: +#line 2115 "cs-parser.jay" + { yyVal = Operator.OpType.Inequality; } + break; +case 267: +#line 2116 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThan; } + break; +case 268: +#line 2117 "cs-parser.jay" + { yyVal = Operator.OpType.LessThan; } + break; +case 269: +#line 2118 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThanOrEqual; } + break; +case 270: +#line 2119 "cs-parser.jay" + { yyVal = Operator.OpType.LessThanOrEqual; } + break; +case 271: +#line 2126 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 272: + case_272(); + break; +case 273: +#line 2145 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 274: + case_274(); + break; +case 275: + case_275(); + break; +case 276: + case_276(); + break; +case 277: + case_277(); + break; +case 278: + case_278(); + break; +case 279: + case_279(); + break; +case 280: + case_280(); + break; +case 282: +#line 2248 "cs-parser.jay" + { current_block = null; yyVal = null; } + break; +case 285: +#line 2260 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 286: + case_286(); + break; +case 287: +#line 2270 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 288: + case_288(); + break; +case 289: + case_289(); + break; +case 290: + case_290(); + break; +case 291: + case_291(); + break; +case 292: + case_292(); + break; +case 293: + case_293(); + break; +case 294: + case_294(); + break; +case 295: + case_295(); + break; +case 296: + case_296(); + break; +case 298: +#line 2379 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 299: + case_299(); + break; +case 302: +#line 2396 "cs-parser.jay" + { + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 303: +#line 2400 "cs-parser.jay" + { + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 304: + case_304(); + break; +case 305: +#line 2413 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 306: + case_306(); + break; +case 307: + case_307(); + break; +case 308: +#line 2438 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 311: + case_311(); + break; +case 312: + case_312(); + break; +case 313: + case_313(); + break; +case 314: + case_314(); + break; +case 315: + case_315(); + break; +case 316: + case_316(); + break; +case 317: + case_317(); + break; +case 318: + case_318(); + break; +case 320: + case_320(); + break; +case 321: + case_321(); + break; +case 322: + case_322(); + break; +case 323: + case_323(); + break; +case 325: + case_325(); + break; +case 326: + case_326(); + break; +case 329: +#line 2593 "cs-parser.jay" + { + lbag.AddLocation (yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 331: + case_331(); + break; +case 332: + case_332(); + break; +case 333: + case_333(); + break; +case 334: + case_334(); + break; +case 335: +#line 2651 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + break; +case 336: + case_336(); + break; +case 337: +#line 2673 "cs-parser.jay" + { + lexer.ConstraintsParsing = false; + } + break; +case 338: + case_338(); + break; +case 340: + case_340(); + break; +case 342: + case_342(); + break; +case 344: + case_344(); + break; +case 345: + case_345(); + break; +case 347: + case_347(); + break; +case 348: + case_348(); + break; +case 349: + case_349(); + break; +case 350: + case_350(); + break; +case 351: +#line 2777 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 352: + case_352(); + break; +case 353: + case_353(); + break; +case 355: + case_355(); + break; +case 356: + case_356(); + break; +case 357: + case_357(); + break; +case 358: + case_358(); + break; +case 359: + case_359(); + break; +case 360: + case_360(); + break; +case 362: + case_362(); + break; +case 363: + case_363(); + break; +case 364: + case_364(); + break; +case 365: + case_365(); + break; +case 366: + case_366(); + break; +case 368: +#line 2895 "cs-parser.jay" + { + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + break; +case 369: +#line 2902 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 371: + case_371(); + break; +case 373: + case_373(); + break; +case 375: + case_375(); + break; +case 377: +#line 2940 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 378: + case_378(); + break; +case 379: +#line 2960 "cs-parser.jay" + { + yyVal = new ComposedCast (((MemberName) yyVals[-1+yyTop]).GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 380: + case_380(); + break; +case 381: +#line 2969 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 382: +#line 2973 "cs-parser.jay" + { + yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 383: + case_383(); + break; +case 384: + case_384(); + break; +case 385: + case_385(); + break; +case 386: + case_386(); + break; +case 387: +#line 3011 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation (yyVals[0+yyTop])); } + break; +case 388: +#line 3012 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.String, GetLocation (yyVals[0+yyTop])); } + break; +case 389: +#line 3013 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation (yyVals[0+yyTop])); } + break; +case 390: +#line 3014 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation (yyVals[0+yyTop])); } + break; +case 391: +#line 3015 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation (yyVals[0+yyTop])); } + break; +case 392: +#line 3016 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation (yyVals[0+yyTop])); } + break; +case 394: +#line 3021 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation (yyVals[0+yyTop])); } + break; +case 395: +#line 3022 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation (yyVals[0+yyTop])); } + break; +case 396: +#line 3023 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation (yyVals[0+yyTop])); } + break; +case 397: +#line 3024 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation (yyVals[0+yyTop])); } + break; +case 398: +#line 3025 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation (yyVals[0+yyTop])); } + break; +case 399: +#line 3026 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation (yyVals[0+yyTop])); } + break; +case 400: +#line 3027 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation (yyVals[0+yyTop])); } + break; +case 401: +#line 3028 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation (yyVals[0+yyTop])); } + break; +case 402: +#line 3029 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation (yyVals[0+yyTop])); } + break; +case 423: + case_423(); + break; +case 424: + case_424(); + break; +case 428: +#line 3076 "cs-parser.jay" + { yyVal = new NullLiteral (GetLocation (yyVals[0+yyTop])); } + break; +case 429: +#line 3080 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation (yyVals[0+yyTop])); } + break; +case 430: +#line 3081 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation (yyVals[0+yyTop])); } + break; +case 435: + case_435(); + break; +case 436: +#line 3114 "cs-parser.jay" + { + yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); + } + break; +case 437: + case_437(); + break; +case 438: + case_438(); + break; +case 439: + case_439(); + break; +case 440: + case_440(); + break; +case 441: +#line 3146 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null,GetLocation (yyVals[0+yyTop])); + } + break; +case 442: + case_442(); + break; +case 443: +#line 3154 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null, lexer.Location); + } + break; +case 444: + case_444(); + break; +case 445: + case_445(); + break; +case 446: +#line 3170 "cs-parser.jay" + { yyVal = null; } + break; +case 448: + case_448(); + break; +case 449: + case_449(); + break; +case 450: +#line 3193 "cs-parser.jay" + { yyVal = null; } + break; +case 451: +#line 3197 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 452: + case_452(); + break; +case 453: + case_453(); + break; +case 454: + case_454(); + break; +case 455: + case_455(); + break; +case 456: +#line 3229 "cs-parser.jay" + { + yyVal = new CompletionElementInitializer (null, GetLocation (yyVals[0+yyTop])); + } + break; +case 457: + case_457(); + break; +case 458: + case_458(); + break; +case 459: + case_459(); + break; +case 462: +#line 3257 "cs-parser.jay" + { yyVal = null; } + break; +case 464: + case_464(); + break; +case 465: + case_465(); + break; +case 466: + case_466(); + break; +case 467: + case_467(); + break; +case 468: + case_468(); + break; +case 469: +#line 3309 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 473: + case_473(); + break; +case 474: + case_474(); + break; +case 475: + case_475(); + break; +case 476: + case_476(); + break; +case 478: + case_478(); + break; +case 479: + case_479(); + break; +case 480: + case_480(); + break; +case 481: + case_481(); + break; +case 482: + case_482(); + break; +case 483: + case_483(); + break; +case 484: +#line 3396 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 486: +#line 3404 "cs-parser.jay" + { + yyVal = new This (GetLocation (yyVals[0+yyTop])); + } + break; +case 487: + case_487(); + break; +case 488: + case_488(); + break; +case 489: +#line 3424 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 490: +#line 3431 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 491: + case_491(); + break; +case 492: + case_492(); + break; +case 493: + case_493(); + break; +case 494: + case_494(); + break; +case 495: + case_495(); + break; +case 496: + case_496(); + break; +case 497: + case_497(); + break; +case 498: +#line 3497 "cs-parser.jay" + { + ++lexer.parsing_type; + } + break; +case 499: + case_499(); + break; +case 500: + case_500(); + break; +case 503: +#line 3524 "cs-parser.jay" + { yyVal = null; } + break; +case 505: + case_505(); + break; +case 506: + case_506(); + break; +case 507: + case_507(); + break; +case 508: + case_508(); + break; +case 509: + case_509(); + break; +case 510: + case_510(); + break; +case 514: + case_514(); + break; +case 515: + case_515(); + break; +case 516: + case_516(); + break; +case 517: +#line 3600 "cs-parser.jay" + { + yyVal = 2; + } + break; +case 518: +#line 3604 "cs-parser.jay" + { + yyVal = ((int) yyVals[-1+yyTop]) + 1; + } + break; +case 519: +#line 3611 "cs-parser.jay" + { + yyVal = null; + } + break; +case 520: +#line 3615 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 521: + case_521(); + break; +case 522: + case_522(); + break; +case 523: + case_523(); + break; +case 524: + case_524(); + break; +case 525: +#line 3659 "cs-parser.jay" + { + lexer.TypeOfParsing = true; + } + break; +case 526: + case_526(); + break; +case 529: + case_529(); + break; +case 530: + case_530(); + break; +case 531: + case_531(); + break; +case 532: + case_532(); + break; +case 533: + case_533(); + break; +case 534: + case_534(); + break; +case 535: + case_535(); + break; +case 536: + case_536(); + break; +case 537: + case_537(); + break; +case 538: + case_538(); + break; +case 539: + case_539(); + break; +case 540: + case_540(); + break; +case 541: +#line 3773 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], false, GetLocation (yyVals[-1+yyTop])); + } + break; +case 542: + case_542(); + break; +case 543: +#line 3786 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], true, GetLocation (yyVals[-2+yyTop])); + } + break; +case 544: +#line 3790 "cs-parser.jay" + { + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + } + break; +case 545: +#line 3797 "cs-parser.jay" + { + yyVal = ParametersCompiled.Undefined; + } + break; +case 547: +#line 3805 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 548: + case_548(); + break; +case 549: + case_549(); + break; +case 551: +#line 3831 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 552: +#line 3835 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.OnesComplement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 555: + case_555(); + break; +case 556: + case_556(); + break; +case 558: +#line 3865 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 559: +#line 3869 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryNegation, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 560: +#line 3873 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 561: +#line 3877 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 562: +#line 3881 "cs-parser.jay" + { + yyVal = new Indirection ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 563: +#line 3885 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.AddressOf, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 565: + case_565(); + break; +case 566: + case_566(); + break; +case 567: + case_567(); + break; +case 569: + case_569(); + break; +case 570: +#line 3917 "cs-parser.jay" + { + yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 571: + case_571(); + break; +case 572: +#line 3926 "cs-parser.jay" + { + yyVal = new As ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 573: +#line 3930 "cs-parser.jay" + { + yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 575: + case_575(); + break; +case 576: + case_576(); + break; +case 578: + case_578(); + break; +case 579: + case_579(); + break; +case 580: + case_580(); + break; +case 581: + case_581(); + break; +case 583: + case_583(); + break; +case 584: + case_584(); + break; +case 586: + case_586(); + break; +case 588: + case_588(); + break; +case 590: + case_590(); + break; +case 592: + case_592(); + break; +case 594: + case_594(); + break; +case 596: + case_596(); + break; +case 598: + case_598(); + break; +case 599: +#line 4054 "cs-parser.jay" + { + yyVal = new SimpleAssign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 600: + case_600(); + break; +case 601: + case_601(); + break; +case 602: + case_602(); + break; +case 603: + case_603(); + break; +case 604: + case_604(); + break; +case 605: + case_605(); + break; +case 606: + case_606(); + break; +case 607: + case_607(); + break; +case 608: + case_608(); + break; +case 609: + case_609(); + break; +case 610: + case_610(); + break; +case 611: + case_611(); + break; +case 612: + case_612(); + break; +case 613: + case_613(); + break; +case 614: + case_614(); + break; +case 615: +#line 4149 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + break; +case 616: + case_616(); + break; +case 619: +#line 4164 "cs-parser.jay" + { + start_block (lexer.Location); + } + break; +case 620: + case_620(); + break; +case 622: + case_622(); + break; +case 623: + case_623(); + break; +case 624: + case_624(); + break; +case 625: + case_625(); + break; +case 626: + case_626(); + break; +case 627: +#line 4209 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 628: + case_628(); + break; +case 629: + case_629(); + break; +case 630: +#line 4223 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 631: + case_631(); + break; +case 632: + case_632(); + break; +case 638: +#line 4248 "cs-parser.jay" + { + yyVal = new ArglistAccess (GetLocation (yyVals[0+yyTop])); + } + break; +case 639: + case_639(); + break; +case 640: + case_640(); + break; +case 641: + case_641(); + break; +case 643: +#line 4277 "cs-parser.jay" + { + yyVal = new BooleanExpression ((Expression) yyVals[0+yyTop]); + } + break; +case 644: +#line 4290 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 645: + case_645(); + break; +case 646: + case_646(); + break; +case 647: + case_647(); + break; +case 648: + case_648(); + break; +case 649: +#line 4329 "cs-parser.jay" + { yyVal = null; } + break; +case 650: +#line 4331 "cs-parser.jay" + { yyVal = yyVals[0+yyTop]; StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[0+yyTop])); } + break; +case 651: + case_651(); + break; +case 654: + case_654(); + break; +case 655: + case_655(); + break; +case 656: + case_656(); + break; +case 657: + case_657(); + break; +case 658: + case_658(); + break; +case 659: + case_659(); + break; +case 660: + case_660(); + break; +case 661: + case_661(); + break; +case 662: + case_662(); + break; +case 663: + case_663(); + break; +case 664: + case_664(); + break; +case 665: + case_665(); + break; +case 666: + case_666(); + break; +case 667: + case_667(); + break; +case 668: + case_668(); + break; +case 669: + case_669(); + break; +case 671: +#line 4451 "cs-parser.jay" + { + current_container.AddBasesForPart (current_class, (List) yyVals[0+yyTop]); + } + break; +case 673: +#line 4459 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 674: + case_674(); + break; +case 675: + case_675(); + break; +case 676: + case_676(); + break; +case 677: + case_677(); + break; +case 678: + case_678(); + break; +case 679: + case_679(); + break; +case 680: + case_680(); + break; +case 681: + case_681(); + break; +case 682: +#line 4548 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation (yyVals[0+yyTop])); + } + break; +case 683: +#line 4552 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation (yyVals[0+yyTop])); + } + break; +case 684: +#line 4559 "cs-parser.jay" + { + yyVal = Variance.None; + } + break; +case 685: + case_685(); + break; +case 686: +#line 4573 "cs-parser.jay" + { + yyVal = Variance.Covariant; + } + break; +case 687: +#line 4577 "cs-parser.jay" + { + yyVal = Variance.Contravariant; + } + break; +case 688: + case_688(); + break; +case 689: +#line 4602 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 690: + case_690(); + break; +case 691: + case_691(); + break; +case 692: + case_692(); + break; +case 693: + case_693(); + break; +case 698: +#line 4646 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 699: +#line 4650 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 701: + case_701(); + break; +case 704: +#line 4674 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 705: +#line 4678 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 734: + case_734(); + break; +case 735: + case_735(); + break; +case 736: + case_736(); + break; +case 737: + case_737(); + break; +case 738: + case_738(); + break; +case 741: + case_741(); + break; +case 742: + case_742(); + break; +case 743: + case_743(); + break; +case 744: + case_744(); + break; +case 745: +#line 4822 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 746: +#line 4826 "cs-parser.jay" + { + yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 747: + case_747(); + break; +case 749: + case_749(); + break; +case 750: +#line 4847 "cs-parser.jay" + { + yyVal = ComposedTypeSpecifier.CreatePointer (GetLocation (yyVals[0+yyTop])); + } + break; +case 751: + case_751(); + break; +case 752: + case_752(); + break; +case 753: + case_753(); + break; +case 754: + case_754(); + break; +case 756: + case_756(); + break; +case 757: + case_757(); + break; +case 762: + case_762(); + break; +case 763: + case_763(); + break; +case 764: +#line 4936 "cs-parser.jay" + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + } + break; +case 765: + case_765(); + break; +case 770: + case_770(); + break; +case 772: + case_772(); + break; +case 773: + case_773(); + break; +case 774: + case_774(); + break; +case 775: +#line 4986 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 776: +#line 4990 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 777: +#line 4991 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 778: + case_778(); + break; +case 779: + case_779(); + break; +case 780: + case_780(); + break; +case 783: + case_783(); + break; +case 784: + case_784(); + break; +case 785: +#line 5059 "cs-parser.jay" + { + start_block (GetLocation (yyVals[0+yyTop])); + } + break; +case 786: + case_786(); + break; +case 787: + case_787(); + break; +case 789: + case_789(); + break; +case 790: + case_790(); + break; +case 791: + case_791(); + break; +case 792: +#line 5103 "cs-parser.jay" + { + current_block = current_block.CreateSwitchBlock (lexer.Location); + } + break; +case 793: +#line 5107 "cs-parser.jay" + { + yyVal = new SwitchSection ((List) yyVals[-2+yyTop], current_block); + } + break; +case 794: + case_794(); + break; +case 795: + case_795(); + break; +case 796: + case_796(); + break; +case 797: +#line 5136 "cs-parser.jay" + { + yyVal = new SwitchLabel (null, GetLocation (yyVals[0+yyTop])); + } + break; +case 802: + case_802(); + break; +case 803: + case_803(); + break; +case 804: + case_804(); + break; +case 805: +#line 5175 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 806: + case_806(); + break; +case 807: + case_807(); + break; +case 808: +#line 5203 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } + break; +case 810: + case_810(); + break; +case 811: + case_811(); + break; +case 813: +#line 5224 "cs-parser.jay" + { yyVal = null; } + break; +case 815: +#line 5229 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } + break; +case 819: + case_819(); + break; +case 820: + case_820(); + break; +case 821: + case_821(); + break; +case 822: + case_822(); + break; +case 829: + case_829(); + break; +case 830: + case_830(); + break; +case 831: + case_831(); + break; +case 832: + case_832(); + break; +case 833: + case_833(); + break; +case 834: + case_834(); + break; +case 835: + case_835(); + break; +case 836: + case_836(); + break; +case 837: + case_837(); + break; +case 840: +#line 5384 "cs-parser.jay" + { + yyVal = new TryCatch ((Block) yyVals[-1+yyTop], (List) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop]), false); + } + break; +case 841: + case_841(); + break; +case 842: + case_842(); + break; +case 843: + case_843(); + break; +case 844: + case_844(); + break; +case 845: + case_845(); + break; +case 848: +#line 5437 "cs-parser.jay" + { + yyVal = new Catch ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 849: + case_849(); + break; +case 850: +#line 5456 "cs-parser.jay" + { + yyVal = yyVals[-1+yyTop]; + } + break; +case 851: + case_851(); + break; +case 852: +#line 5474 "cs-parser.jay" + { + yyVal = new Checked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 853: +#line 5481 "cs-parser.jay" + { + yyVal = new Unchecked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 854: + case_854(); + break; +case 855: +#line 5491 "cs-parser.jay" + { + yyVal = new Unsafe ((Block) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + break; +case 856: + case_856(); + break; +case 857: + case_857(); + break; +case 858: + case_858(); + break; +case 859: + case_859(); + break; +case 860: + case_860(); + break; +case 861: + case_861(); + break; +case 862: + case_862(); + break; +case 863: + case_863(); + break; +case 864: +#line 5574 "cs-parser.jay" + { + report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + } + break; +case 865: + case_865(); + break; +case 866: + case_866(); + break; +case 867: + case_867(); + break; +case 868: + case_868(); + break; +case 869: + case_869(); + break; +case 870: + case_870(); + break; +case 871: + case_871(); + break; +case 872: + case_872(); + break; +case 873: + case_873(); + break; +case 874: +#line 5674 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 875: + case_875(); + break; +case 876: +#line 5689 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 877: + case_877(); + break; +case 878: + case_878(); + break; +case 880: + case_880(); + break; +case 881: +#line 5734 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 882: + case_882(); + break; +case 883: + case_883(); + break; +case 884: + case_884(); + break; +case 885: + case_885(); + break; +case 889: + case_889(); + break; +case 895: +#line 5793 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 896: + case_896(); + break; +case 897: +#line 5812 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 898: + case_898(); + break; +case 899: + case_899(); + break; +case 900: + case_900(); + break; +case 901: + case_901(); + break; +case 902: + case_902(); + break; +case 903: + case_903(); + break; +case 904: + case_904(); + break; +case 905: + case_905(); + break; +case 906: + case_906(); + break; +case 908: +#line 5956 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 909: +#line 5963 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 910: + case_910(); + break; +case 912: + case_912(); + break; +case 913: + case_913(); + break; +case 915: + case_915(); + break; +case 916: + case_916(); + break; +case 917: +#line 6009 "cs-parser.jay" + { + yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); + } + break; +case 918: + case_918(); + break; +case 919: + case_919(); + break; +case 920: +#line 6026 "cs-parser.jay" + { + yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); + } + break; +case 921: + case_921(); + break; +case 922: + case_922(); + break; +case 924: + case_924(); + break; +case 925: + case_925(); + break; +case 928: + case_928(); + break; +case 929: + case_929(); + break; +case 937: +#line 6150 "cs-parser.jay" + { + module.DocumentationBuilder.ParsedName = (MemberName) yyVals[0+yyTop]; + } + break; +case 938: +#line 6157 "cs-parser.jay" + { + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + } + break; +case 939: + case_939(); + break; +case 940: + case_940(); + break; +case 941: +#line 6174 "cs-parser.jay" + { + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], new MemberName (MemberCache.IndexerNameAlias)); + } + break; +case 942: +#line 6178 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 943: + case_943(); + break; +case 944: + case_944(); + break; +case 945: + case_945(); + break; +case 946: + case_946(); + break; +case 948: +#line 6214 "cs-parser.jay" + { + yyVal = new MemberName (((MemberName) yyVals[-2+yyTop]), (MemberName) yyVals[0+yyTop]); + } + break; +case 950: +#line 6222 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 951: +#line 6226 "cs-parser.jay" + { + yyVal = yyVals[-1+yyTop]; + } + break; +case 952: +#line 6233 "cs-parser.jay" + { + yyVal = new List (0); + } + break; +case 954: + case_954(); + break; +case 955: + case_955(); + break; +case 956: + case_956(); + break; +#line default + } + yyTop -= yyLen[yyN]; + yyState = yyStates[yyTop]; + int yyM = yyLhs[yyN]; + if (yyState == 0 && yyM == 0) { +//t if (debug != null) debug.shift(0, yyFinal); + yyState = yyFinal; + if (yyToken < 0) { + yyToken = yyLex.advance() ? yyLex.token() : 0; +//t if (debug != null) +//t debug.lex(yyState, yyToken,yyname(yyToken), yyLex.value()); + } + if (yyToken == 0) { +//t if (debug != null) debug.accept(yyVal); + return yyVal; + } + goto continue_yyLoop; + } + if (((yyN = yyGindex[yyM]) != 0) && ((yyN += yyState) >= 0) + && (yyN < yyTable.Length) && (yyCheck[yyN] == yyState)) + yyState = yyTable[yyN]; + else + yyState = yyDgoto[yyM]; +//t if (debug != null) debug.shift(yyStates[yyTop], yyState); + goto continue_yyLoop; + continue_yyDiscarded: ; // implements the named-loop continue: 'continue yyDiscarded' + } + continue_yyLoop: ; // implements the named-loop continue: 'continue yyLoop' + } + } + +/* + All more than 3 lines long rules are wrapped into a method +*/ +void case_6() +#line 403 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + Attributes attrs = (Attributes) yyVals[0+yyTop]; + report.Error (1730, attrs.Attrs [0].Location, + "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); + } + } + +void case_8() +#line 415 "cs-parser.jay" +{ + if (yyToken == Token.EXTERN_ALIAS) + report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); + else + Error_SyntaxError (yyToken); + } + +void case_13() +#line 435 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + string s = lt.Value; + if (s != "alias"){ + syntax_error (lt.Location, "`alias' expected"); + } else if (lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (lt.Location, "external alias"); + } else { + lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + current_namespace.AddUsingExternalAlias (lt.Value, lt.Location, report); + ubag.AddExternAlias (GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop]), lt, GetLocation (yyVals[0+yyTop])); + } + } + +void case_17() +#line 461 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_18() +#line 466 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_19() +#line 474 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { + report.Warning (440, 2, lt.Location, + "An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); + } + + current_namespace.AddUsingAlias (lt.Value, (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + ubag.AddUsingAlias (GetLocation (yyVals[-4+yyTop]), lt, GetLocation (yyVals[-2+yyTop]), (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_20() +#line 485 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_21() +#line 493 "cs-parser.jay" +{ + current_namespace.AddUsing ((MemberName) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + ubag.AddUsing (GetLocation (yyVals[-2+yyTop]), (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_22() +#line 506 "cs-parser.jay" +{ + Attributes attrs = (Attributes) yyVals[-2+yyTop]; + MemberName name = (MemberName) yyVals[0+yyTop]; + if (attrs != null) { + bool valid_global_attrs = true; + if ((current_namespace.DeclarationFound || current_namespace != file.NamespaceContainer)) { + valid_global_attrs = false; + } else { + foreach (var a in attrs.Attrs) { + if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") + continue; + + valid_global_attrs = false; + break; + } + } + + if (!valid_global_attrs) + report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); + } + + module.AddAttributes (attrs, current_namespace); + + current_namespace = new NamespaceContainer (name, module, current_namespace, file); + module.AddTypesContainer (current_namespace); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + + ubag.DeclareNamespace (GetLocation (yyVals[-1+yyTop]), name); + } + +void case_23() +#line 537 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + ubag.OpenNamespace (GetLocation (yyVals[0+yyTop])); + } + +void case_24() +#line 543 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) + lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + else + lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop])); + + current_namespace = current_namespace.Parent; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + ubag.CloseNamespace (GetLocation (yyVals[-1+yyTop])); + ubag.EndNamespace (GetLocation (yyVals[-1+yyTop])); + } + +void case_25() +#line 559 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new MemberName (lt.Value, lt.Location); + } + +void case_26() +#line 564 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, lt.Location); + } + +void case_27() +#line 569 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new MemberName ("", lexer.Location); + } + +void case_32() +#line 587 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[0+yyTop]; + + if (name.TypeArguments != null) + syntax_error (lexer.Location, "namespace name expected"); + + yyVal = name; + } + +void case_41() +#line 619 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + TypeContainer ds = (TypeContainer)yyVals[0+yyTop]; + + if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ + report.Error (1527, ds.Location, + "Namespace elements cannot be explicitly declared as private, protected or protected internal"); + } + + /* Here is a trick, for explicit attributes we don't know where they belong to until*/ + /* we parse succeeding declaration hence we parse them as normal and re-attach them*/ + /* when we know whether they are global (assembly:, module:) or local (type:).*/ + if (ds.OptAttributes != null) { + ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file.NamespaceContainer); + } + } + current_namespace.DeclarationFound = true; + } + +void case_50() +#line 669 "cs-parser.jay" +{ + var sect = (List) yyVals[0+yyTop]; + yyVal = new Attributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + } + +void case_51() +#line 675 "cs-parser.jay" +{ + Attributes attrs = yyVals[-1+yyTop] as Attributes; + var sect = (List) yyVals[0+yyTop]; + if (attrs == null) + attrs = new Attributes (sect); + else + attrs.AddAttributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + yyVal = attrs; + } + +void case_52() +#line 689 "cs-parser.jay" +{ + lexer.parsing_attribute_section = true; + savedOpenLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_53() +#line 694 "cs-parser.jay" +{ + lexer.parsing_attribute_section = false; + yyVal = yyVals[0+yyTop]; + } + +void case_54() +#line 702 "cs-parser.jay" +{ + current_attr_target = (string) yyVals[-1+yyTop]; + if (current_attr_target == "assembly" || current_attr_target == "module") { + Lexer.check_incorrect_doc_comment (); + } + } + +void case_55() +#line 709 "cs-parser.jay" +{ + /* when attribute target is invalid*/ + if (current_attr_target == string.Empty) + yyVal = new List (0); + else + yyVal = yyVals[-2+yyTop]; + + current_attr_target = null; + lexer.parsing_attribute_section = false; + savedCloseLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_56() +#line 721 "cs-parser.jay" +{ + yyVal = yyVals[-2+yyTop]; + savedCloseLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_57() +#line 729 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = CheckAttributeTarget (lt.Value, lt.Location); + } + +void case_60() +#line 736 "cs-parser.jay" +{ + if (yyToken == Token.IDENTIFIER) { + Error_SyntaxError (yyToken); + yyVal = null; + } else { + string name = GetTokenName (yyToken); + yyVal = CheckAttributeTarget (name, GetLocation (yyVals[0+yyTop])); + } + } + +void case_62() +#line 753 "cs-parser.jay" +{ + var attrs = (List) yyVals[-2+yyTop]; + attrs.Add ((Attribute) yyVals[0+yyTop]); + + yyVal = attrs; + } + +void case_64() +#line 767 "cs-parser.jay" +{ + --lexer.parsing_block; + MemberName mname = (MemberName) yyVals[-2+yyTop]; + if (mname.IsGeneric) { + report.Error (404, lexer.Location, + "'<' unexpected: attributes cannot be generic"); + } + + Arguments [] arguments = (Arguments []) yyVals[0+yyTop]; + ATypeNameExpression expr = mname.GetTypeExpression (); + yyVal = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); + if (arguments != null) { + lbag.AddLocation (yyVal, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + } + } + +void case_67() +#line 791 "cs-parser.jay" +{ + savedAttrParenOpenLocation = GetLocation (yyVals[-2+yyTop]); + savedAttrParenCloseLocation = GetLocation (yyVals[0+yyTop]); + yyVal = yyVals[-1+yyTop]; + } + +void case_69() +#line 802 "cs-parser.jay" +{ + Arguments a = new Arguments (4); + a.Add ((Argument) yyVals[0+yyTop]); + yyVal = new Arguments [] { a, null }; + } + +void case_70() +#line 808 "cs-parser.jay" +{ + Arguments a = new Arguments (4); + a.Add ((Argument) yyVals[0+yyTop]); + yyVal = new Arguments [] { null, a }; + } + +void case_71() +#line 814 "cs-parser.jay" +{ + Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; + if (o [1] != null) { + report.Error (1016, ((Argument) yyVals[0+yyTop]).Expr.Location, "Named attribute arguments must appear after the positional arguments"); + o [0] = new Arguments (4); + } + + Arguments args = ((Arguments) o [0]); + if (args.Count > 0 && !(yyVals[0+yyTop] is NamedArgument) && args [args.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (args, GetLocation (yyVals[-1+yyTop])); + } + +void case_72() +#line 829 "cs-parser.jay" +{ + Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; + if (o [1] == null) { + o [1] = new Arguments (4); + } + + ((Arguments) o [1]).Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (o[1], GetLocation (yyVals[-1+yyTop])); + } + +void case_76() +#line 854 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new NamedArgument (lt.Value, lt.Location, (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation(yyVals[-2+yyTop])); + } + +void case_77() +#line 864 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "named argument"); + + /* Avoid boxing in common case (no modifier)*/ + var arg_mod = yyVals[-1+yyTop] == null ? Argument.AType.None : (Argument.AType) yyVals[-1+yyTop]; + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new NamedArgument (lt.Value, lt.Location, (Expression) yyVals[0+yyTop], arg_mod); + } + +void case_95() +#line 911 "cs-parser.jay" +{ + report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", + GetSymbolName (yyToken)); + yyVal = null; + lexer.parsing_generic_declaration = false; + } + +void case_97() +#line 928 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); + } + +void case_98() +#line 934 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + + if (doc_support) + current_container.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); + } + +void case_99() +#line 945 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_100() +#line 951 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[0+yyTop])); + yyVal = pop_current_class (); + } + +void case_102() +#line 963 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_118() +#line 1005 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var mod = (Modifiers) yyVals[-3+yyTop]; + current_field = new Const (current_class, (FullNamedExpression) yyVals[-1+yyTop], mod, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + current_container.AddConstant ((Const) current_field); + + if ((mod & Modifiers.STATIC) != 0) { + report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); + } + + yyVal = current_field; + } + +void case_119() +#line 1018 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) yyVals[-2+yyTop]; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + current_field = null; + } + +void case_124() +#line 1048 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_126() +#line 1061 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstInitializer (current_field, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_127() +#line 1067 "cs-parser.jay" +{ + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + yyVal = null; + } + +void case_130() +#line 1082 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + + FullNamedExpression type = (FullNamedExpression) yyVals[-1+yyTop]; + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (670, GetLocation (yyVals[-1+yyTop]), "Fields cannot have void type"); + + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + current_field = new Field (current_class, type, (Modifiers) yyVals[-2+yyTop], new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-3+yyTop]); + current_container.AddField (current_field); + yyVal = current_field; + } + +void case_131() +#line 1097 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[0+yyTop])); + yyVal = current_field; + current_field = null; + } + +void case_132() +#line 1110 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "fixed size buffers"); + + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + current_field = new FixedField (current_class, (FullNamedExpression) yyVals[-1+yyTop], (Modifiers) yyVals[-3+yyTop], + new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + + current_container.AddField (current_field); + } + +void case_133() +#line 1121 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) yyVals[-2+yyTop]; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = current_field; + current_field = null; + } + +void case_136() +#line 1144 "cs-parser.jay" +{ + ++lexer.parsing_block; + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + start_block (GetLocation (yyVals[0+yyTop])); + } + +void case_137() +#line 1150 "cs-parser.jay" +{ + --lexer.parsing_block; + current_field.Initializer = (Expression) yyVals[0+yyTop]; + lbag.AppendToMember (current_field, GetLocation (yyVals[-2+yyTop])); + end_block (lexer.Location); + current_local_parameters = null; + } + +void case_142() +#line 1177 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_144() +#line 1187 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_149() +#line 1213 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_151() +#line 1226 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstInitializer (current_field, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_152() +#line 1232 "cs-parser.jay" +{ + report.Error (443, lexer.Location, "Value or constant expected"); + yyVal = null; + } + +void case_155() +#line 1242 "cs-parser.jay" +{ + /* It has to be here for the parent to safely restore artificial block*/ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_156() +#line 1251 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.NotAllowed; + + /* Add it early in the case of body being eof for full aot*/ + current_container.AddMethod ((Method) yyVals[0+yyTop]); + } + +void case_157() +#line 1259 "cs-parser.jay" +{ + Method method = (Method) yyVals[-2+yyTop]; + method.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (method.Block == null) { + method.ParameterInfo.CheckParameters (method); + + if ((method.ModFlags & Modifiers.ASYNC) != 0) { + report.Error (1994, method.Location, "`{0}': The async modifier can only be used with methods that have a body", + method.GetSignatureForError ()); + } + } else { + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, method.Location, "`{0}': interface members cannot have a definition", + method.GetSignatureForError ()); + } + } + + current_local_parameters = null; + + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_160() +#line 1297 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + MemberName name = (MemberName) yyVals[-6+yyTop]; + current_local_parameters = (ParametersCompiled) yyVals[-3+yyTop]; + + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + (FullNamedExpression) yyVals[-7+yyTop], current_local_parameters); + + generic.SetParameterInfo ((List) yyVals[0+yyTop]); + } else if (yyVals[0+yyTop] != null) { + report.Error (80, GetLocation (yyVals[0+yyTop]), + "Constraints are not allowed on non-generic declarations"); + } + + Method method = new Method (current_class, generic, (FullNamedExpression) yyVals[-7+yyTop], (Modifiers) yyVals[-8+yyTop], + name, current_local_parameters, (Attributes) yyVals[-9+yyTop]); + + if (yyVals[0+yyTop] != null && ((method.ModFlags & Modifiers.OVERRIDE) != 0 || method.IsExplicitImpl)) { + report.Error (460, method.Location, + "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods", + method.GetSignatureForError ()); + } + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (method, GetModifierLocations (), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = method; + } + +void case_162() +#line 1338 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + valid_param_mod = ParameterModifierType.All; + } + +void case_164() +#line 1347 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + + MemberName name = (MemberName) yyVals[-6+yyTop]; + current_local_parameters = (ParametersCompiled) yyVals[-3+yyTop]; + + if (yyVals[-1+yyTop] != null && name.TypeArguments == null) + report.Error (80, lexer.Location, + "Constraints are not allowed on non-generic declarations"); + + Method method; + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-8+yyTop])), + current_local_parameters); + + generic.SetParameterInfo ((List) yyVals[-1+yyTop]); + } + + var modifiers = (Modifiers) yyVals[-10+yyTop]; + + const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN | + Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL; + + if ((modifiers & invalid_partial_mod) != 0) { + report.Error (750, name.Location, "A partial method cannot define access modifier or " + + "any of abstract, extern, new, override, sealed, or virtual modifiers"); + modifiers &= ~invalid_partial_mod; + } + + if ((current_class.ModFlags & Modifiers.PARTIAL) == 0) { + report.Error (751, name.Location, "A partial method must be declared within a " + + "partial class or partial struct"); + } + + modifiers |= Modifiers.PARTIAL | Modifiers.PRIVATE; + + method = new Method (current_class, generic, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-8+yyTop])), + modifiers, name, current_local_parameters, (Attributes) yyVals[-11+yyTop]); + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[-9+yyTop])); + lbag.AddMember (method, mod_locations, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = method; + } + +void case_165() +#line 1400 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[-3+yyTop]; + report.Error (1585, name.Location, + "Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) yyVals[-4+yyTop])); + + Method method = new Method (current_class, null, (FullNamedExpression) yyVals[-5+yyTop], + 0, name, (ParametersCompiled) yyVals[-1+yyTop], (Attributes) yyVals[-7+yyTop]); + + current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + yyVal = method; + } + +void case_170() +#line 1429 "cs-parser.jay" +{ + var pars_list = (List) yyVals[0+yyTop]; + yyVal = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation (yyVal, lbag.GetLocations (pars_list)); + } + +void case_171() +#line 1435 "cs-parser.jay" +{ + var pars_list = (List) yyVals[-2+yyTop]; + pars_list.Add ((Parameter) yyVals[0+yyTop]); + + yyVal = new ParametersCompiled (pars_list.ToArray ()); + } + +void case_172() +#line 1442 "cs-parser.jay" +{ + var pars_list = (List) yyVals[-2+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[0+yyTop]))); + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_173() +#line 1448 "cs-parser.jay" +{ + if (yyVals[-2+yyTop] != null) + report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); + + yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[-2+yyTop] } ); + } + +void case_174() +#line 1455 "cs-parser.jay" +{ + if (yyVals[-2+yyTop] != null) + report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) yyVals[-4+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); + + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_175() +#line 1465 "cs-parser.jay" +{ + report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); + + yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[-2+yyTop])) }, true); + } + +void case_176() +#line 1471 "cs-parser.jay" +{ + report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) yyVals[-4+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); + + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_179() +#line 1488 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = ParametersCompiled.EmptyReadOnlyParameters; + } + +void case_180() +#line 1496 "cs-parser.jay" +{ + parameters_bucket.Clear (); + Parameter p = (Parameter) yyVals[0+yyTop]; + parameters_bucket.Add (p); + + default_parameter_used = p.HasDefaultValue; + yyVal = parameters_bucket; + } + +void case_181() +#line 1505 "cs-parser.jay" +{ + var pars = (List) yyVals[-2+yyTop]; + Parameter p = (Parameter) yyVals[0+yyTop]; + if (p != null) { + if (p.HasExtensionMethodModifier) + report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); + else if (!p.HasDefaultValue && default_parameter_used) + report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); + + default_parameter_used |= p.HasDefaultValue; + pars.Add (p); + + lbag.AppendTo (pars, GetLocation (yyVals[-1+yyTop])); + } + + yyVal = yyVals[-2+yyTop]; + } + +void case_182() +#line 1529 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], (Attributes) yyVals[-3+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_183() +#line 1538 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); + yyVal = new Parameter ((FullNamedExpression) yyVals[-3+yyTop], lt.Value, (Parameter.Modifier) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_184() +#line 1548 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + Location l = GetLocation (yyVals[0+yyTop]); + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], null, (Parameter.Modifier) yyVals[-2+yyTop], (Attributes) yyVals[-3+yyTop], l); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_186() +#line 1563 "cs-parser.jay" +{ + --lexer.parsing_block; + if (lang_version <= LanguageVersion.V_3) { + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "optional parameter"); + } + + Parameter.Modifier mod = (Parameter.Modifier) yyVals[-5+yyTop]; + if (mod != Parameter.Modifier.NONE) { + switch (mod) { + case Parameter.Modifier.REF: + case Parameter.Modifier.OUT: + report.Error (1741, GetLocation (yyVals[-5+yyTop]), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + + case Parameter.Modifier.This: + report.Error (1743, GetLocation (yyVals[-5+yyTop]), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + default: + throw new NotImplementedException (mod.ToString ()); + } + + mod = Parameter.Modifier.NONE; + } + + if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) + report.Error (1065, GetLocation (yyVals[-2+yyTop]), "Optional parameter is not valid in this context"); + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new Parameter ((FullNamedExpression) yyVals[-4+yyTop], lt.Value, mod, (Attributes) yyVals[-6+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation, GetLocation (yyVals[-2+yyTop])); /* parameterModifierLocation should be ignored when mod == NONE*/ + + if (yyVals[0+yyTop] != null) + ((Parameter) yyVal).DefaultValue = new DefaultParameterValueExpression ((Expression) yyVals[0+yyTop]); + } + +void case_189() +#line 1608 "cs-parser.jay" +{ + yyVal = yyVals[0+yyTop]; + parameterModifierLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_190() +#line 1613 "cs-parser.jay" +{ + Parameter.Modifier p2 = (Parameter.Modifier)yyVals[0+yyTop]; + Parameter.Modifier mod = (Parameter.Modifier)yyVals[-1+yyTop] | p2; + if (((Parameter.Modifier)yyVals[-1+yyTop] & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); + } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); + break; + case Parameter.Modifier.OUT: + report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); + break; + default: + report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); + break; + } + } + yyVal = mod; + } + +void case_191() +#line 1637 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Ref) == 0) + Error_ParameterModifierNotValid ("ref", GetLocation (yyVals[0+yyTop])); + + yyVal = Parameter.Modifier.REF; + } + +void case_192() +#line 1644 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Out) == 0) + Error_ParameterModifierNotValid ("out", GetLocation (yyVals[0+yyTop])); + + yyVal = Parameter.Modifier.OUT; + } + +void case_193() +#line 1651 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.This) == 0) + Error_ParameterModifierNotValid ("this", GetLocation (yyVals[0+yyTop])); + + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "extension methods"); + + yyVal = Parameter.Modifier.This; + } + +void case_194() +#line 1664 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Attributes) yyVals[-3+yyTop], lt.Location); + } + +void case_195() +#line 1669 "cs-parser.jay" +{ + report.Error (1751, GetLocation (yyVals[-4+yyTop]), "Cannot specify a default value for a parameter array"); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-3+yyTop], lt.Value, (Attributes) yyVals[-5+yyTop], lt.Location); + } + +void case_196() +#line 1676 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_197() +#line 1684 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Params) == 0) + report.Error (1670, (GetLocation (yyVals[0+yyTop])), "The `params' modifier is not allowed in current context"); + } + +void case_198() +#line 1689 "cs-parser.jay" +{ + Parameter.Modifier mod = (Parameter.Modifier)yyVals[0+yyTop]; + if ((mod & Parameter.Modifier.This) != 0) { + report.Error (1104, GetLocation (yyVals[-1+yyTop]), "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { + report.Error (1611, GetLocation (yyVals[-1+yyTop]), "The params parameter cannot be declared as ref or out"); + } + } + +void case_200() +#line 1705 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Arglist) == 0) + report.Error (1669, GetLocation (yyVals[0+yyTop]), "__arglist is not valid in this context"); + } + +void case_201() +#line 1716 "cs-parser.jay" +{ + if (doc_support) + tmpComment = Lexer.consume_doc_comment (); + } + +void case_202() +#line 1721 "cs-parser.jay" +{ + var type = (FullNamedExpression) yyVals[-3+yyTop]; + current_property = new Property (current_class, type, (Modifiers) yyVals[-4+yyTop], + (MemberName) yyVals[-2+yyTop], (Attributes) yyVals[-5+yyTop]); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (547, GetLocation (yyVals[-3+yyTop]), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); + + current_container.AddProperty ((Property)current_property); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation (yyVals[0+yyTop])); + + lexer.PropertyParsing = true; + } + +void case_203() +#line 1735 "cs-parser.jay" +{ + lexer.PropertyParsing = false; + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + } + +void case_204() +#line 1742 "cs-parser.jay" +{ + lbag.AppendToMember (current_property, GetLocation (yyVals[0+yyTop])); + current_property = null; + } + +void case_206() +#line 1756 "cs-parser.jay" +{ + valid_param_mod = 0; + var type = (FullNamedExpression) yyVals[-6+yyTop]; + Indexer indexer = new Indexer (current_class, type, (MemberName) yyVals[-5+yyTop], (Modifiers) yyVals[-7+yyTop], (ParametersCompiled) yyVals[-2+yyTop], (Attributes) yyVals[-8+yyTop]); + + current_property = indexer; + + current_container.AddIndexer (indexer); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (620, GetLocation (yyVals[-6+yyTop]), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); + + if (indexer.ParameterInfo.IsEmpty) { + report.Error (1551, GetLocation (yyVals[-4+yyTop]), "Indexers must have at least one parameter"); + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lexer.PropertyParsing = true; + } + +void case_208() +#line 1785 "cs-parser.jay" +{ + if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) + ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + + lbag.AppendToMember (current_property, GetLocation (yyVals[-1+yyTop])); + current_property = null; + } + +void case_213() +#line 1804 "cs-parser.jay" +{ + if (yyToken == Token.CLOSE_BRACE) { + report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); + } else { + if (yyToken == Token.SEMICOLON) + report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); + else + report.Error (1014, GetLocation (yyVals[0+yyTop]), "A get or set accessor expected"); + } + } + +void case_214() +#line 1818 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); + } + + if (current_property.Get != null) { + report.Error (1007, GetLocation (yyVals[0+yyTop]), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) yyVals[-1+yyTop], ((Indexer)current_property).ParameterInfo.Clone (), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } else { + current_property.Get = new Property.GetMethod (current_property, + (Modifiers) yyVals[-1+yyTop], (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } + + current_local_parameters = current_property.Get.ParameterInfo; + lbag.AddMember (current_property.Get, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + +void case_215() +#line 1840 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + current_property.Get.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Get.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support) + if (Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + +void case_216() +#line 1861 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); + } + + if (current_property.Set != null) { + report.Error (1007, GetLocation (yyVals[0+yyTop]), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) yyVals[-1+yyTop], + ParametersCompiled.MergeGenerated (compiler, + ((Indexer)current_property).ParameterInfo, true, new Parameter ( + current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation (yyVals[0+yyTop])), + null), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } else { + current_property.Set = new Property.SetMethod (current_property, (Modifiers) yyVals[-1+yyTop], + ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation (yyVals[0+yyTop])), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } + + current_local_parameters = current_property.Set.ParameterInfo; + lbag.AddMember (current_property.Set, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + +void case_217() +#line 1888 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + current_property.Set.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Set.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support + && Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + +void case_219() +#line 1910 "cs-parser.jay" +{ + lbag.AppendToMember (lbag.LastMember, GetLocation (yyVals[0+yyTop])); + yyVal = null; + } + +void case_220() +#line 1915 "cs-parser.jay" +{ + Error_SyntaxError (1043, yyToken, "Invalid accessor body"); + yyVal = null; + } + +void case_222() +#line 1930 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-2+yyTop])); + } + +void case_223() +#line 1937 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + +void case_224() +#line 1948 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_225() +#line 1954 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = pop_current_class (); + } + +void case_241() +#line 2006 "cs-parser.jay" +{ + OperatorDeclaration decl = (OperatorDeclaration) yyVals[-2+yyTop]; + if (decl != null) { + Operator op = new Operator ( + current_class, decl.optype, decl.ret_type, (Modifiers) yyVals[-3+yyTop], + current_local_parameters, + (ToplevelBlock) yyVals[0+yyTop], (Attributes) yyVals[-4+yyTop], decl.location); + + if (op.Block == null) + op.ParameterInfo.CheckParameters (op); + + if (doc_support) { + op.DocComment = tmpComment; + Lexer.doc_state = XmlCommentState.Allowed; + } + + /* Note again, checking is done in semantic analysis*/ + current_container.AddOperator (op); + + lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + } + + current_local_parameters = null; + } + +void case_245() +#line 2040 "cs-parser.jay" +{ + report.Error (590, GetLocation (yyVals[0+yyTop]), "User-defined operators cannot return void"); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_247() +#line 2052 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + Operator.OpType op = (Operator.OpType) yyVals[-4+yyTop]; + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + int p_count = current_local_parameters.Count; + if (p_count == 1) { + if (op == Operator.OpType.Addition) + op = Operator.OpType.UnaryPlus; + else if (op == Operator.OpType.Subtraction) + op = Operator.OpType.UnaryNegation; + } + + if (IsUnaryOperator (op)) { + if (p_count == 2) { + report.Error (1020, loc, "Overloadable binary operator expected"); + } else if (p_count != 1) { + report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", + Operator.GetName (op)); + } + } else { + if (p_count > 2) { + report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", + Operator.GetName (op)); + } else if (p_count != 2) { + report.Error (1019, loc, "Overloadable unary operator expected"); + } + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (op, (FullNamedExpression) yyVals[-6+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_272() +#line 2128 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) yyVals[-4+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_274() +#line 2147 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) yyVals[-4+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_275() +#line 2162 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + yyVal = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_276() +#line 2168 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + yyVal = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_277() +#line 2178 "cs-parser.jay" +{ + Constructor c = (Constructor) yyVals[-1+yyTop]; + c.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (doc_support) + c.DocComment = ConsumeStoredComment (); + + current_container.AddConstructor (c); + + current_local_parameters = null; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_278() +#line 2197 "cs-parser.jay" +{ + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + valid_param_mod = ParameterModifierType.All; + } + +void case_279() +#line 2206 "cs-parser.jay" +{ + valid_param_mod = 0; + current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; + + /**/ + /* start block here, so possible anonymous methods inside*/ + /* constructor initializer can get correct parent block*/ + /**/ + start_block (lexer.Location); + } + +void case_280() +#line 2217 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-6+yyTop]; + var mods = (Modifiers) yyVals[-7+yyTop]; + ConstructorInitializer ci = (ConstructorInitializer) yyVals[0+yyTop]; + + Constructor c = new Constructor (current_class, lt.Value, mods, + (Attributes) yyVals[-8+yyTop], current_local_parameters, ci, lt.Location); + + if (lt.Value != current_container.MemberName.Name) { + report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); + } else if ((mods & Modifiers.STATIC) != 0) { + if ((mods & Modifiers.AccessibilityMask) != 0){ + report.Error (515, c.Location, + "`{0}': static constructor cannot have an access modifier", + c.GetSignatureForError ()); + } + if (ci != null) { + report.Error (514, c.Location, + "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", + c.GetSignatureForError ()); + + } + } + + lbag.AddMember (c, GetModifierLocations (), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = c; + } + +void case_286() +#line 2262 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstructorBaseInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_288() +#line 2272 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstructorThisInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_289() +#line 2278 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_290() +#line 2286 "cs-parser.jay" +{ + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + +void case_291() +#line 2295 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + if (lt.Value != current_container.MemberName.Name){ + report.Error (574, lt.Location, "Name of destructor must match name of class"); + } else if (current_container.Kind != MemberKind.Class){ + report.Error (575, lt.Location, "Only class types can contain destructor"); + } + + Destructor d = new Destructor (current_class, (Modifiers) yyVals[-6+yyTop], + ParametersCompiled.EmptyReadOnlyParameters, (Attributes) yyVals[-7+yyTop], lt.Location); + if (doc_support) + d.DocComment = ConsumeStoredComment (); + + d.Block = (ToplevelBlock) yyVals[0+yyTop]; + current_container.AddMethod (d); + lbag.AddMember (d, GetModifierLocations (), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[-1+yyTop])); + + current_local_parameters = null; + } + +void case_292() +#line 2320 "cs-parser.jay" +{ + current_event_field = new EventField (current_class, (FullNamedExpression) yyVals[-1+yyTop], (Modifiers) yyVals[-3+yyTop], (MemberName) yyVals[0+yyTop], (Attributes) yyVals[-4+yyTop]); + current_container.AddEvent (current_event_field); + + if (current_event_field.MemberName.Left != null) { + report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", + current_event_field.GetSignatureForError ()); + } + + yyVal = current_event_field; + } + +void case_293() +#line 2334 "cs-parser.jay" +{ + if (doc_support) { + current_event_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_event_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + current_event_field = null; + } + +void case_294() +#line 2347 "cs-parser.jay" +{ + current_event = new EventProperty (current_class, (FullNamedExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-4+yyTop], (MemberName) yyVals[-1+yyTop], (Attributes) yyVals[-5+yyTop]); + current_container.AddEvent (current_event); + lbag.AddMember (current_event, GetModifierLocations (), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + + lexer.EventParsing = true; + } + +void case_295() +#line 2355 "cs-parser.jay" +{ + if (current_container.Kind == MemberKind.Interface) + report.Error (69, GetLocation (yyVals[-2+yyTop]), "Event in interface cannot have add or remove accessors"); + + lexer.EventParsing = false; + } + +void case_296() +#line 2362 "cs-parser.jay" +{ + if (doc_support) { + current_event.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AppendToMember (current_event, GetLocation (yyVals[-1+yyTop])); + current_event = null; + current_local_parameters = null; + } + +void case_299() +#line 2381 "cs-parser.jay" +{ + --lexer.parsing_block; + current_event_field.Initializer = (Expression) yyVals[0+yyTop]; + } + +void case_304() +#line 2405 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_306() +#line 2415 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_307() +#line 2424 "cs-parser.jay" +{ + if (current_container.Kind == MemberKind.Interface) { + report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + + if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { + report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + } + +void case_311() +#line 2445 "cs-parser.jay" +{ + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + +void case_312() +#line 2450 "cs-parser.jay" +{ + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + +void case_313() +#line 2455 "cs-parser.jay" +{ + report.Error (1055, GetLocation (yyVals[0+yyTop]), "An add or remove accessor expected"); + yyVal = null; + } + +void case_314() +#line 2463 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone) { + report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + current_local_parameters = current_event.Add.ParameterInfo; + + lbag.AddMember (current_event.Add, GetModifierLocations ()); + lexer.EventParsing = false; + } + +void case_315() +#line 2475 "cs-parser.jay" +{ + lexer.EventParsing = true; + + current_event.Add.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Add.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); + } + + current_local_parameters = null; + } + +void case_316() +#line 2491 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone) { + report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + current_local_parameters = current_event.Remove.ParameterInfo; + + lbag.AddMember (current_event.Remove, GetModifierLocations ()); + lexer.EventParsing = false; + } + +void case_317() +#line 2503 "cs-parser.jay" +{ + lexer.EventParsing = true; + + current_event.Remove.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Remove.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); + } + + current_local_parameters = null; + } + +void case_318() +#line 2519 "cs-parser.jay" +{ + report.Error (73, lexer.Location, "An add or remove accessor must have a body"); + yyVal = null; + } + +void case_320() +#line 2531 "cs-parser.jay" +{ + if (doc_support) + enumTypeComment = Lexer.consume_doc_comment (); + } + +void case_321() +#line 2536 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + + MemberName name = (MemberName) yyVals[-3+yyTop]; + if (name.IsGeneric) { + report.Error (1675, name.Location, "Enums cannot have type parameters"); + } + + push_current_class (new Enum (current_namespace, current_class, (TypeExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-5+yyTop], MakeName (name), (Attributes) yyVals[-6+yyTop]), null); + } + +void case_322() +#line 2548 "cs-parser.jay" +{ + /* here will be evaluated after CLOSE_BLACE is consumed.*/ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_323() +#line 2554 "cs-parser.jay" +{ + if (doc_support) + current_class.DocComment = enumTypeComment; + + --lexer.parsing_declaration; + +/* if (doc_support)*/ +/* em.DocComment = ev.DocComment;*/ + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-1+yyTop])); + yyVal = pop_current_class (); + } + +void case_325() +#line 2571 "cs-parser.jay" +{ + var te = yyVals[0+yyTop] as TypeExpression; + if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { + Enum.Error_1008 (GetLocation (yyVals[0+yyTop]), report); + yyVal = null; + } else { + yyVal = yyVals[0+yyTop]; + } + } + +void case_326() +#line 2581 "cs-parser.jay" +{ + Error_TypeExpected (GetLocation (yyVals[-1+yyTop])); + yyVal = null; + } + +void case_331() +#line 2599 "cs-parser.jay" +{ + lbag.AddLocation (yyVals[-2+yyTop], GetLocation (yyVals[-1+yyTop])); + yyVal = yyVals[0+yyTop]; + } + +void case_332() +#line 2607 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-1+yyTop]); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) { + em.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + yyVal = em; + } + +void case_333() +#line 2620 "cs-parser.jay" +{ + ++lexer.parsing_block; + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + } + +void case_334() +#line 2628 "cs-parser.jay" +{ + --lexer.parsing_block; + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + em.Initializer = new ConstInitializer (em, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) + em.DocComment = ConsumeStoredComment (); + + yyVal = em; + } + +void case_336() +#line 2653 "cs-parser.jay" +{ + valid_param_mod = 0; + + MemberName name = MakeName ((MemberName) yyVals[-4+yyTop]); + ParametersCompiled p = (ParametersCompiled) yyVals[-1+yyTop]; + + Delegate del = new Delegate (current_namespace, current_class, (FullNamedExpression) yyVals[-5+yyTop], + (Modifiers) yyVals[-7+yyTop], name, p, (Attributes) yyVals[-8+yyTop]); + p.CheckParameters (del); + + ubag.PushTypeDeclaration (del); + ubag.PopTypeDeclaration (); + + current_container.AddDelegate (del); + current_delegate = del; + lexer.ConstraintsParsing = true; + } + +void case_338() +#line 2675 "cs-parser.jay" +{ + if (doc_support) { + current_delegate.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_delegate.SetParameterInfo ((List) yyVals[-2+yyTop]); + lbag.AddMember (current_delegate, GetModifierLocations (), GetLocation (yyVals[-10+yyTop]), GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[0+yyTop])); + + yyVal = current_delegate; + + current_delegate = null; + } + +void case_340() +#line 2693 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "nullable types"); + + yyVal = ComposedTypeSpecifier.CreateNullable (GetLocation (yyVals[0+yyTop])); + } + +void case_342() +#line 2704 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new MemberName (lt1.Value, lt2.Value, (TypeArguments) yyVals[0+yyTop], lt1.Location); + } + +void case_344() +#line 2715 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_345() +#line 2724 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_347() +#line 2736 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); + var list = locationListStack.Pop (); + list.Add (GetLocation (yyVals[-2+yyTop])); + list.Add (GetLocation (yyVals[-1+yyTop])); + lbag.AddLocation (yyVals[-1+yyTop], list); + + yyVal = yyVals[-1+yyTop];; + } + +void case_348() +#line 2747 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = new TypeArguments (); + } + +void case_349() +#line 2755 "cs-parser.jay" +{ + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = type_args; + locationListStack.Push (new List ()); + } + +void case_350() +#line 2762 "cs-parser.jay" +{ + TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; + type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = type_args; + locationListStack.Peek ().Add (GetLocation (yyVals[-1+yyTop])); + } + +void case_352() +#line 2779 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_353() +#line 2788 "cs-parser.jay" +{ + MemberName mn = (MemberName)yyVals[0+yyTop]; + if (mn.TypeArguments != null) + syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", + mn.GetSignatureForError ())); + } + +void case_355() +#line 2799 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + } + +void case_356() +#line 2808 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + yyVal = new MemberName (TypeContainer.DefaultIndexerName, GetLocation (yyVals[0+yyTop])); + } + +void case_357() +#line 2813 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + yyVal = new MemberName ((MemberName) yyVals[-1+yyTop], TypeContainer.DefaultIndexerName, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_358() +#line 2821 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_359() +#line 2827 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + + yyVal = new MemberName (lt1.Value, lt2.Value, (TypeArguments) yyVals[-1+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_360() +#line 2835 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_362() +#line 2845 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); + + yyVal = yyVals[-1+yyTop]; + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_363() +#line 2856 "cs-parser.jay" +{ + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); + yyVal = type_args; + } + +void case_364() +#line 2862 "cs-parser.jay" +{ + TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; + type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); + yyVal = type_args; + lbag.AddLocation (yyVals[0+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_365() +#line 2872 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; + yyVal = new TypeParameterName (lt.Value, (Attributes)yyVals[-2+yyTop], (Variance) yyVals[-1+yyTop], lt.Location); + } + +void case_366() +#line 2877 "cs-parser.jay" +{ + if (GetTokenName (yyToken) == "type") + report.Error (81, GetLocation (yyVals[0+yyTop]), "Type parameter declaration must be an identifier not a type"); + else + Error_SyntaxError (yyToken); + + yyVal = new TypeParameterName ("", null, lexer.Location); + } + +void case_371() +#line 2911 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_373() +#line 2920 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_375() +#line 2929 "cs-parser.jay" +{ + report.Error (1536, GetLocation (yyVals[0+yyTop]), "Invalid parameter type `void'"); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_378() +#line 2945 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[-1+yyTop]; + + if (yyVals[0+yyTop] != null) { + yyVal = new ComposedCast (name.GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + if (name.Left == null && name.Name == "var") + yyVal = new VarExpr (name.Location); + else + yyVal = name.GetTypeExpression (); + } + } + +void case_380() +#line 2962 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_383() +#line 2978 "cs-parser.jay" +{ + var types = new List (2); + types.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = types; + } + +void case_384() +#line 2984 "cs-parser.jay" +{ + var types = (List) yyVals[-2+yyTop]; + types.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = types; + } + +void case_385() +#line 2993 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is ComposedCast) { + report.Error (1521, GetLocation (yyVals[0+yyTop]), "Invalid base type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); + } + yyVal = yyVals[0+yyTop]; + } + +void case_386() +#line 3000 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = null; + } + +void case_423() +#line 3062 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new SimpleName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_424() +#line 3066 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); + } + +void case_435() +#line 3107 "cs-parser.jay" +{ + yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_437() +#line 3119 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_438() +#line 3125 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_439() +#line 3131 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_440() +#line 3137 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) yyVals[0+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_442() +#line 3147 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); + } + +void case_444() +#line 3155 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); + } + +void case_445() +#line 3163 "cs-parser.jay" +{ + yyVal = new Invocation ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_448() +#line 3176 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] == null) { + yyVal = CollectionOrObjectInitializers.Empty; + /* TODO: lbag*/ + } else { + yyVal = new CollectionOrObjectInitializers ((List) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + } + +void case_449() +#line 3186 "cs-parser.jay" +{ + yyVal = new CollectionOrObjectInitializers ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_452() +#line 3202 "cs-parser.jay" +{ + var a = new List (); + a.Add ((Expression) yyVals[0+yyTop]); + yyVal = a; + } + +void case_453() +#line 3208 "cs-parser.jay" +{ + var a = (List)yyVals[-2+yyTop]; + a.Add ((Expression) yyVals[0+yyTop]); + yyVal = a; + } + +void case_454() +#line 3213 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = yyVals[-1+yyTop]; + } + +void case_455() +#line 3221 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new ElementInitializer (lt.Value, (Expression)yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_457() +#line 3230 "cs-parser.jay" +{ + CompletionSimpleName csn = yyVals[-1+yyTop] as CompletionSimpleName; + if (csn == null) + yyVal = new CollectionElementInitializer ((Expression)yyVals[-1+yyTop]); + else + yyVal = new CompletionElementInitializer (csn.Prefix, csn.Location); + } + +void case_458() +#line 3238 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] == null) + yyVal = null; + else + yyVal = new CollectionElementInitializer ((List)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_459() +#line 3245 "cs-parser.jay" +{ + report.Error (1920, GetLocation (yyVals[-1+yyTop]), "An element initializer cannot be empty"); + yyVal = null; + } + +void case_464() +#line 3263 "cs-parser.jay" +{ + Arguments list = new Arguments (4); + list.Add ((Argument) yyVals[0+yyTop]); + yyVal = list; + } + +void case_465() +#line 3269 "cs-parser.jay" +{ + Arguments list = (Arguments) yyVals[-2+yyTop]; + if (list [list.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); + + list.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_466() +#line 3279 "cs-parser.jay" +{ + Arguments list = (Arguments) yyVals[-2+yyTop]; + NamedArgument a = (NamedArgument) yyVals[0+yyTop]; + for (int i = 0; i < list.Count; ++i) { + NamedArgument na = list [i] as NamedArgument; + if (na != null && na.Name == a.Name) + report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", + na.Name); + } + + list.Add (a); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_467() +#line 3294 "cs-parser.jay" +{ + report.Error (839, GetLocation (yyVals[0+yyTop]), "An argument is missing"); + yyVal = yyVals[-1+yyTop]; + } + +void case_468() +#line 3299 "cs-parser.jay" +{ + report.Error (839, GetLocation (yyVals[-1+yyTop]), "An argument is missing"); + yyVal = null; + } + +void case_473() +#line 3320 "cs-parser.jay" +{ + yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Ref); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_474() +#line 3325 "cs-parser.jay" +{ + yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Out); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_475() +#line 3330 "cs-parser.jay" +{ + yyVal = new Argument (new Arglist ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop]))); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_476() +#line 3335 "cs-parser.jay" +{ + yyVal = new Argument (new Arglist (GetLocation (yyVals[-2+yyTop]))); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_478() +#line 3347 "cs-parser.jay" +{ + yyVal = new ElementAccess ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_479() +#line 3355 "cs-parser.jay" +{ + var list = new List (4); + list.Add ((Expression) yyVals[0+yyTop]); + yyVal = list; + } + +void case_480() +#line 3361 "cs-parser.jay" +{ + var list = (List) yyVals[-2+yyTop]; + list.Add ((Expression) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_481() +#line 3367 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = yyVals[-1+yyTop]; + } + +void case_482() +#line 3375 "cs-parser.jay" +{ + Arguments args = new Arguments (4); + args.Add ((Argument) yyVals[0+yyTop]); + yyVal = args; + } + +void case_483() +#line 3381 "cs-parser.jay" +{ + Arguments args = (Arguments) yyVals[-2+yyTop]; + if (args [args.Count - 1] is NamedArgument && !(yyVals[0+yyTop] is NamedArgument)) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (args, GetLocation (yyVals[-1+yyTop])); + yyVal = args; + } + +void case_487() +#line 3409 "cs-parser.jay" +{ + yyVal = new ElementAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_488() +#line 3414 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new ElementAccess (null, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_491() +#line 3436 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-5+yyTop]), "object initializers"); + + yyVal = new NewInitialize ((FullNamedExpression) yyVals[-4+yyTop], (Arguments) yyVals[-2+yyTop], (CollectionOrObjectInitializers) yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])); + } else { + yyVal = new New ((FullNamedExpression) yyVals[-4+yyTop], (Arguments) yyVals[-2+yyTop], GetLocation (yyVals[-5+yyTop])); + } + + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_492() +#line 3449 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "collection initializers"); + + yyVal = new NewInitialize ((FullNamedExpression) yyVals[-1+yyTop], null, (CollectionOrObjectInitializers) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_493() +#line 3461 "cs-parser.jay" +{ + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], (List) yyVals[-3+yyTop], + new ComposedTypeSpecifier (((List) yyVals[-3+yyTop]).Count, GetLocation (yyVals[-4+yyTop])) { + Next = (ComposedTypeSpecifier) yyVals[-1+yyTop] + }, (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_494() +#line 3469 "cs-parser.jay" +{ + if (yyVals[0+yyTop] == null) + report.Error (1586, GetLocation (yyVals[-3+yyTop]), "Array creation must have array size or array initializer"); + + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-2+yyTop], (ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + } + +void case_495() +#line 3476 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "implicitly typed arrays"); + + yyVal = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_496() +#line 3483 "cs-parser.jay" +{ + report.Error (178, GetLocation (yyVals[-1+yyTop]), "Invalid rank specifier, expecting `,' or `]'"); + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], null, GetLocation (yyVals[-6+yyTop])); + } + +void case_497() +#line 3488 "cs-parser.jay" +{ + Error_SyntaxError (1526, yyToken, "Unexpected symbol"); + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-1+yyTop], null, GetLocation (yyVals[-2+yyTop])); + } + +void case_499() +#line 3499 "cs-parser.jay" +{ + --lexer.parsing_type; + yyVal = yyVals[0+yyTop]; + } + +void case_500() +#line 3507 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "anonymous types"); + + yyVal = new NewAnonymousType ((List) yyVals[-1+yyTop], current_container, GetLocation (yyVals[-3+yyTop])); + + /* TODO: lbag comma location*/ + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_505() +#line 3530 "cs-parser.jay" +{ + var a = new List (4); + a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); + yyVal = a; + } + +void case_506() +#line 3536 "cs-parser.jay" +{ + var a = (List) yyVals[-2+yyTop]; + a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); + yyVal = a; + } + +void case_507() +#line 3545 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[-2+yyTop]; + yyVal = new AnonymousTypeParameter ((Expression)yyVals[0+yyTop], lt.Value, lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_508() +#line 3551 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; + yyVal = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), + lt.Value, lt.Location); + } + +void case_509() +#line 3557 "cs-parser.jay" +{ + MemberAccess ma = (MemberAccess) yyVals[0+yyTop]; + yyVal = new AnonymousTypeParameter (ma, ma.Name, ma.Location); + } + +void case_510() +#line 3562 "cs-parser.jay" +{ + report.Error (746, lexer.Location, + "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); + yyVal = null; + } + +void case_514() +#line 3577 "cs-parser.jay" +{ + ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_515() +#line 3585 "cs-parser.jay" +{ + yyVal = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation (yyVals[-1+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_516() +#line 3590 "cs-parser.jay" +{ + yyVal = ComposedTypeSpecifier.CreateArrayDimension ((int)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_521() +#line 3620 "cs-parser.jay" +{ + var ai = new ArrayInitializer (0, GetLocation (yyVals[-1+yyTop])); + ai.VariableDeclaration = current_variable; + lbag.AddLocation (ai, GetLocation (yyVals[0+yyTop])); + yyVal = ai; + } + +void case_522() +#line 3627 "cs-parser.jay" +{ + var ai = new ArrayInitializer ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); + ai.VariableDeclaration = current_variable; + if (yyVals[-1+yyTop] != null) { + lbag.AddLocation (ai, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } else { + lbag.AddLocation (ai, GetLocation (yyVals[0+yyTop])); + } + yyVal = ai; + } + +void case_523() +#line 3641 "cs-parser.jay" +{ + var list = new List (4); + list.Add ((Expression) yyVals[0+yyTop]); + yyVal = list; + } + +void case_524() +#line 3647 "cs-parser.jay" +{ + var list = (List) yyVals[-2+yyTop]; + list.Add ((Expression) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_526() +#line 3661 "cs-parser.jay" +{ + lexer.TypeOfParsing = false; + yyVal = new TypeOf ((FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_529() +#line 3672 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = null; + } + +void case_530() +#line 3680 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new SimpleName (lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_531() +#line 3686 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) yyVals[0+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_532() +#line 3694 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], lt.Value, lt.Location); + } + +void case_533() +#line 3700 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_534() +#line 3706 "cs-parser.jay" +{ + var te = ((MemberName) yyVals[-3+yyTop]).GetTypeExpression (); + if (te.HasTypeArguments) + Error_TypeExpected (GetLocation (yyVals[0+yyTop])); + + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (te, lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_535() +#line 3718 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "generics"); + + yyVal = yyVals[0+yyTop]; + } + +void case_536() +#line 3728 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); + + yyVal = lt; + } + +void case_537() +#line 3739 "cs-parser.jay" +{ + yyVal = new SizeOf ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_538() +#line 3747 "cs-parser.jay" +{ + yyVal = new CheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_539() +#line 3755 "cs-parser.jay" +{ + yyVal = new UnCheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_540() +#line 3763 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (new Indirection ((Expression) yyVals[-3+yyTop], GetLocation (yyVals[-2+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + } + +void case_542() +#line 3775 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + if ((ParametersCompiled) yyVals[-2+yyTop] != ParametersCompiled.Undefined) { + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), savedOpenLocation, savedCloseLocation); + } else { + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop])); + } + } + +void case_548() +#line 3807 "cs-parser.jay" +{ + valid_param_mod = 0; + yyVal = yyVals[-1+yyTop]; + savedOpenLocation = GetLocation (yyVals[-3+yyTop]); + savedCloseLocation = GetLocation (yyVals[-2+yyTop]); + } + +void case_549() +#line 3817 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "default value expression"); + + yyVal = new DefaultValueExpression ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_555() +#line 3842 "cs-parser.jay" +{ + yyVal = new Cast ((FullNamedExpression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_556() +#line 3850 "cs-parser.jay" +{ + current_block.ParametersBlock.IsAsync = true; + yyVal = new Await ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_565() +#line 3891 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Multiply, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_566() +#line 3896 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Division, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_567() +#line 3901 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Modulus, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_569() +#line 3910 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Addition, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_571() +#line 3919 "cs-parser.jay" +{ + /* Shift/Reduce conflict*/ + yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_575() +#line 3936 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LeftShift, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_576() +#line 3941 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.RightShift, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_578() +#line 3950 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LessThan, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_579() +#line 3955 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.GreaterThan, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_580() +#line 3960 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LessThanOrEqual, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_581() +#line 3965 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.GreaterThanOrEqual, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_583() +#line 3974 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Equality, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_584() +#line 3979 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Inequality, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_586() +#line 3988 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.BitwiseAnd, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_588() +#line 3997 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.ExclusiveOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_590() +#line 4006 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.BitwiseOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_592() +#line 4015 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LogicalAnd, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_594() +#line 4024 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LogicalOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_596() +#line 4033 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "null coalescing operator"); + + yyVal = new Nullable.NullCoalescingOperator ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_598() +#line 4044 "cs-parser.jay" +{ + yyVal = new Conditional (new BooleanExpression ((Expression) yyVals[-4+yyTop]), (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_600() +#line 4056 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Multiply, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_601() +#line 4061 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Division, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_602() +#line 4066 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Modulus, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_603() +#line 4071 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Addition, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_604() +#line 4076 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_605() +#line 4081 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.LeftShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_606() +#line 4086 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.RightShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_607() +#line 4091 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.BitwiseAnd, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_608() +#line 4096 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.BitwiseOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_609() +#line 4101 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.ExclusiveOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_610() +#line 4109 "cs-parser.jay" +{ + var pars = new List (4); + pars.Add ((Parameter) yyVals[0+yyTop]); + + yyVal = pars; + } + +void case_611() +#line 4116 "cs-parser.jay" +{ + var pars = (List) yyVals[-2+yyTop]; + Parameter p = (Parameter)yyVals[0+yyTop]; + if (pars[0].GetType () != p.GetType ()) { + report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); + } + + pars.Add (p); + yyVal = pars; + } + +void case_612() +#line 4130 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], null, lt.Location); + } + +void case_613() +#line 4136 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, Parameter.Modifier.NONE, null, lt.Location); + } + +void case_614() +#line 4142 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new ImplicitLambdaParameter (lt.Value, lt.Location); + } + +void case_616() +#line 4150 "cs-parser.jay" +{ + var pars_list = (List) yyVals[0+yyTop]; + yyVal = new ParametersCompiled (pars_list.ToArray ()); + } + +void case_620() +#line 4166 "cs-parser.jay" +{ + Block b = end_block (lexer.Location); + b.IsCompilerGenerated = true; + b.AddStatement (new ContextualReturn ((Expression) yyVals[0+yyTop])); + yyVal = b; + } + +void case_622() +#line 4177 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = EmptyExpression.Null; + } + +void case_623() +#line 4185 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), false, lt.Location); + } + +void case_624() +#line 4191 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_625() +#line 4196 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), true, lt.Location); + } + +void case_626() +#line 4202 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_628() +#line 4211 "cs-parser.jay" +{ + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], false, GetLocation (yyVals[-4+yyTop])); + } + +void case_629() +#line 4216 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_631() +#line 4225 "cs-parser.jay" +{ + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], true, GetLocation (yyVals[-5+yyTop])); + } + +void case_632() +#line 4230 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_639() +#line 4253 "cs-parser.jay" +{ + yyVal = new RefValueExpr ((Expression) yyVals[-3+yyTop], (FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-5+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_640() +#line 4258 "cs-parser.jay" +{ + yyVal = new RefTypeExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_641() +#line 4263 "cs-parser.jay" +{ + yyVal = new MakeRefExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_645() +#line 4292 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + Class c = new Class (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]); + if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (c.Location, "static classes"); + } + + push_current_class (c, yyVals[-3+yyTop]); + } + +void case_646() +#line 4303 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + +void case_647() +#line 4315 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_648() +#line 4321 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = pop_current_class (); + } + +void case_651() +#line 4336 "cs-parser.jay" +{ + mod_locations = null; + yyVal = ModifierNone; + } + +void case_654() +#line 4346 "cs-parser.jay" +{ + var m1 = (Modifiers) yyVals[-1+yyTop]; + var m2 = (Modifiers) yyVals[0+yyTop]; + + if ((m1 & m2) != 0) { + report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, + "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); + } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && + ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { + report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, + "More than one protection modifier specified"); + } + + yyVal = m1 | m2; + } + +void case_655() +#line 4365 "cs-parser.jay" +{ + yyVal = Modifiers.NEW; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + + if (current_container == module) + report.Error (1530, GetLocation (yyVals[0+yyTop]), "Keyword `new' is not allowed on namespace elements"); + } + +void case_656() +#line 4373 "cs-parser.jay" +{ + yyVal = Modifiers.PUBLIC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_657() +#line 4378 "cs-parser.jay" +{ + yyVal = Modifiers.PROTECTED; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_658() +#line 4383 "cs-parser.jay" +{ + yyVal = Modifiers.INTERNAL; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_659() +#line 4388 "cs-parser.jay" +{ + yyVal = Modifiers.PRIVATE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_660() +#line 4393 "cs-parser.jay" +{ + yyVal = Modifiers.ABSTRACT; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_661() +#line 4398 "cs-parser.jay" +{ + yyVal = Modifiers.SEALED; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_662() +#line 4403 "cs-parser.jay" +{ + yyVal = Modifiers.STATIC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_663() +#line 4408 "cs-parser.jay" +{ + yyVal = Modifiers.READONLY; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_664() +#line 4413 "cs-parser.jay" +{ + yyVal = Modifiers.VIRTUAL; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_665() +#line 4418 "cs-parser.jay" +{ + yyVal = Modifiers.OVERRIDE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_666() +#line 4423 "cs-parser.jay" +{ + yyVal = Modifiers.EXTERN; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_667() +#line 4428 "cs-parser.jay" +{ + yyVal = Modifiers.VOLATILE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_668() +#line 4433 "cs-parser.jay" +{ + yyVal = Modifiers.UNSAFE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); + } + +void case_669() +#line 4440 "cs-parser.jay" +{ + yyVal = Modifiers.ASYNC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_674() +#line 4461 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_675() +#line 4469 "cs-parser.jay" +{ + var constraints = new List (1); + constraints.Add ((Constraints) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_676() +#line 4475 "cs-parser.jay" +{ + var constraints = (List) yyVals[-1+yyTop]; + Constraints new_constraint = (Constraints)yyVals[0+yyTop]; + + foreach (Constraints c in constraints) { + if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { + report.Error (409, new_constraint.Location, + "A constraint clause has already been specified for type parameter `{0}'", + new_constraint.TypeParameter.Value); + } + } + + constraints.Add (new_constraint); + yyVal = constraints; + } + +void case_677() +#line 4494 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + } + +void case_678() +#line 4502 "cs-parser.jay" +{ + var constraints = new List (1); + constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_679() +#line 4508 "cs-parser.jay" +{ + var constraints = (List) yyVals[-2+yyTop]; + var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { + report.Error (401, GetLocation (yyVals[-1+yyTop]), "The `new()' constraint must be the last constraint specified"); + } + + prev = yyVals[0+yyTop] as SpecialContraintExpr; + if (prev != null) { + if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { + report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); + } else { + prev = constraints [0] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { + report.Error (451, GetLocation (yyVals[0+yyTop]), "The `new()' constraint cannot be used with the `struct' constraint"); + } + } + } + + constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_680() +#line 4534 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is ComposedCast) + report.Error (706, GetLocation (yyVals[0+yyTop]), "Invalid constraint type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); + + yyVal = yyVals[0+yyTop]; + } + +void case_681() +#line 4541 "cs-parser.jay" +{ + yyVal = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_685() +#line 4561 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (lexer.Location, "generic type variance"); + + yyVal = yyVals[0+yyTop]; + } + +void case_688() +#line 4595 "cs-parser.jay" +{ + ++lexer.parsing_block; + start_block (GetLocation (yyVals[0+yyTop])); + } + +void case_690() +#line 4607 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (GetLocation (yyVals[0+yyTop])); + } + +void case_691() +#line 4612 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (lexer.Location); + } + +void case_692() +#line 4621 "cs-parser.jay" +{ + ++lexer.parsing_block; + current_block.StartLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_693() +#line 4626 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (GetLocation (yyVals[0+yyTop])); + } + +void case_701() +#line 4653 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_734() +#line 4717 "cs-parser.jay" +{ + report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); + yyVal = null; + } + +void case_735() +#line 4722 "cs-parser.jay" +{ + report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); + yyVal = null; + } + +void case_736() +#line 4727 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_737() +#line 4735 "cs-parser.jay" +{ + /* Uses lexer.Location because semicolon location is not kept in quick mode*/ + yyVal = new EmptyStatement (lexer.Location); + } + +void case_738() +#line 4743 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); + + current_block.AddLabel (labeled); + current_block.AddStatement (labeled); + } + +void case_741() +#line 4756 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] is VarExpr) + yyVals[-1+yyTop] = new SimpleName ("var", ((VarExpr) yyVals[-1+yyTop]).Location); + + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_742() +#line 4772 "cs-parser.jay" +{ + /* Ok, the above "primary_expression" is there to get rid of*/ + /* both reduce/reduce and shift/reduces in the grammar, it should*/ + /* really just be "type_name". If you use type_name, a reduce/reduce*/ + /* creeps up. If you use namespace_or_type_name (which is all we need*/ + /* really) two shift/reduces appear.*/ + /* */ + + /* So the super-trick is that primary_expression*/ + /* can only be either a SimpleName or a MemberAccess. */ + /* The MemberAccess case arises when you have a fully qualified type-name like :*/ + /* Foo.Bar.Blah i;*/ + /* SimpleName is when you have*/ + /* Blah i;*/ + + Expression expr = (Expression) yyVals[-1+yyTop]; + if (yyVals[0+yyTop] == null) { + SimpleName sn = expr as SimpleName; + if (sn != null && sn.Name == "var") + yyVal = new VarExpr (sn.Location); + else + yyVal = yyVals[-1+yyTop]; + } else if (expr is ATypeNameExpression) { + yyVal = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + Error_ExpectingTypeName (expr); + yyVal = null; + } + } + +void case_743() +#line 4802 "cs-parser.jay" +{ + ATypeNameExpression expr = yyVals[-1+yyTop] as ATypeNameExpression; + + if (expr != null) { + yyVal = new ComposedCast (expr, (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + Error_ExpectingTypeName ((Expression)yyVals[-1+yyTop]); + yyVal = expr; + } + } + +void case_744() +#line 4813 "cs-parser.jay" +{ + if (yyVals[0+yyTop] == null) + yyVal = yyVals[-1+yyTop]; + else + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_747() +#line 4828 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_749() +#line 4837 "cs-parser.jay" +{ + ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_751() +#line 4852 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_752() +#line 4859 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + lbag.AppendTo (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_753() +#line 4865 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockConstantDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_754() +#line 4872 "cs-parser.jay" +{ + if (current_variable.Initializer != null) { + lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), savedLocation, GetLocation (yyVals[0+yyTop])); + } else { + lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + } + yyVal = current_variable;; + current_variable = null; + } + +void case_756() +#line 4886 "cs-parser.jay" +{ + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + lbag.AppendTo (current_variable, GetLocation (yyVals[-1+yyTop])); + } + +void case_757() +#line 4891 "cs-parser.jay" +{ + if (yyToken == Token.OPEN_BRACKET_EXPR) { + report.Error (650, lexer.Location, + "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); + } else { + Error_SyntaxError (yyToken); + } + } + +void case_762() +#line 4913 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, null); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-1+yyTop])); + } + +void case_763() +#line 4922 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) yyVals[0+yyTop]); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_765() +#line 4938 "cs-parser.jay" +{ + savedLocation = GetLocation (yyVals[-1+yyTop]); + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + } + +void case_770() +#line 4956 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) yyVals[0+yyTop]); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_772() +#line 4969 "cs-parser.jay" +{ + yyVal = new StackAlloc ((Expression) yyVals[-3+yyTop], (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_773() +#line 4974 "cs-parser.jay" +{ + report.Error (1575, GetLocation (yyVals[-1+yyTop]), "A stackalloc expression requires [] after type"); + yyVal = new StackAlloc ((Expression) yyVals[0+yyTop], null, GetLocation (yyVals[-1+yyTop])); + } + +void case_774() +#line 4982 "cs-parser.jay" +{ + yyVal = yyVals[-1+yyTop]; + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_778() +#line 5000 "cs-parser.jay" +{ + ExpressionStatement s = yyVals[0+yyTop] as ExpressionStatement; + if (s == null) { + Expression.Error_InvalidExpressionStatement (report, GetLocation (yyVals[0+yyTop])); + yyVal = new StatementExpression (EmptyExpressionStatement.Instance); + } else { + yyVal = new StatementExpression (s); + } + } + +void case_779() +#line 5013 "cs-parser.jay" +{ + Expression expr = (Expression) yyVals[0+yyTop]; + ExpressionStatement s; + + s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location); + yyVal = new StatementExpression (s); + } + +void case_780() +#line 5021 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_783() +#line 5035 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new If ((BooleanExpression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_784() +#line 5044 "cs-parser.jay" +{ + yyVal = new If ((BooleanExpression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + + if (yyVals[-2+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[-2+yyTop])); + if (yyVals[0+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_786() +#line 5061 "cs-parser.jay" +{ + yyVal = new Switch ((Expression) yyVals[-5+yyTop], (ExplicitBlock) current_block.Explicit, (List) yyVals[-1+yyTop], GetLocation (yyVals[-7+yyTop])); + end_block (GetLocation (yyVals[0+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_787() +#line 5070 "cs-parser.jay" +{ + report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); + yyVal = new List (); + } + +void case_789() +#line 5079 "cs-parser.jay" +{ + var sections = new List (4); + + sections.Add ((SwitchSection) yyVals[0+yyTop]); + yyVal = sections; + } + +void case_790() +#line 5086 "cs-parser.jay" +{ + var sections = (List) yyVals[-1+yyTop]; + + sections.Add ((SwitchSection) yyVals[0+yyTop]); + yyVal = sections; + } + +void case_791() +#line 5093 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new List (); + } + +void case_794() +#line 5112 "cs-parser.jay" +{ + var labels = new List (2); + + labels.Add ((SwitchLabel) yyVals[0+yyTop]); + yyVal = labels; + } + +void case_795() +#line 5119 "cs-parser.jay" +{ + var labels = (List) (yyVals[-1+yyTop]); + labels.Add ((SwitchLabel) yyVals[0+yyTop]); + + yyVal = labels; + } + +void case_796() +#line 5129 "cs-parser.jay" +{ + yyVal = new SwitchLabel ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_802() +#line 5148 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new While ((BooleanExpression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_803() +#line 5160 "cs-parser.jay" +{ + yyVal = new Do ((Statement) yyVals[-5+yyTop], (BooleanExpression) yyVals[-2+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_804() +#line 5168 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[0+yyTop])); + current_block.IsCompilerGenerated = true; + } + +void case_806() +#line 5184 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + For f = new For ((Statement) yyVals[-6+yyTop], (BooleanExpression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + current_block.AddStatement (f); + + lbag.AddStatement (f, current_block.StartLocation, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + + yyVal = end_block (GetLocation (yyVals[-5+yyTop])); + } + +void case_807() +#line 5196 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = end_block (current_block.StartLocation); + } + +void case_810() +#line 5209 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_811() +#line 5216 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_819() +#line 5240 "cs-parser.jay" +{ + var sl = yyVals[-2+yyTop] as StatementList; + if (sl == null) { + sl = new StatementList ((Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop]); + lbag.AddStatement (sl, GetLocation (yyVals[-1+yyTop])); + } else { + sl.Add ((Statement) yyVals[0+yyTop]); + lbag.AppendTo (sl, GetLocation (yyVals[-1+yyTop])); + } + + yyVal = sl; + } + +void case_820() +#line 5256 "cs-parser.jay" +{ + report.Error (230, GetLocation (yyVals[-5+yyTop]), "Type and identifier are both required in a foreach statement"); + yyVal = null; + } + +void case_821() +#line 5261 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-5+yyTop])); + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + yyVal = li; + } + +void case_822() +#line 5270 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Foreach f = new Foreach ((Expression) yyVals[-6+yyTop], (LocalVariable) yyVals[-1+yyTop], (Expression) yyVals[-3+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-8+yyTop])); + current_block.AddStatement (f); + + lbag.AddStatement (f, GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_829() +#line 5293 "cs-parser.jay" +{ + yyVal = new Break (GetLocation (yyVals[-1+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_830() +#line 5301 "cs-parser.jay" +{ + yyVal = new Continue (GetLocation (yyVals[-1+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_831() +#line 5309 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new Goto (lt.Value, GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_832() +#line 5315 "cs-parser.jay" +{ + yyVal = new GotoCase ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_833() +#line 5320 "cs-parser.jay" +{ + yyVal = new GotoDefault (GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_834() +#line 5328 "cs-parser.jay" +{ + yyVal = new Return ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_835() +#line 5336 "cs-parser.jay" +{ + yyVal = new Throw ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_836() +#line 5344 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (yyVals[-1+yyTop] == null) { + report.Error (1627, GetLocation (yyVals[0+yyTop]), "Expression expected after yield return"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + yyVal = new Yield ((Expression) yyVals[-1+yyTop], lt.Location); + lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_837() +#line 5360 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + yyVal = new YieldBreak (lt.Location); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_841() +#line 5386 "cs-parser.jay" +{ + yyVal = new TryFinally ((Statement) yyVals[-2+yyTop], (Block) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_842() +#line 5391 "cs-parser.jay" +{ + yyVal = new TryFinally (new TryCatch ((Block) yyVals[-3+yyTop], (List) yyVals[-2+yyTop], GetLocation (yyVals[-4+yyTop]), true), (Block) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_843() +#line 5396 "cs-parser.jay" +{ + report.Error (1524, GetLocation (yyVals[-2+yyTop]), "Expected catch or finally"); + yyVal = null; + } + +void case_844() +#line 5404 "cs-parser.jay" +{ + var l = new List (2); + + l.Add ((Catch) yyVals[0+yyTop]); + yyVal = l; + } + +void case_845() +#line 5411 "cs-parser.jay" +{ + var l = (List) yyVals[-1+yyTop]; + + Catch c = (Catch) yyVals[0+yyTop]; + if (l [0].IsGeneral) { + report.Error (1017, c.loc, "Try statement already has an empty catch block"); + } else { + if (c.IsGeneral) + l.Insert (0, c); + else + l.Add (c); + } + + yyVal = l; + } + +void case_849() +#line 5439 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-3+yyTop])); + var c = new Catch (current_block, GetLocation (yyVals[-4+yyTop])); + c.TypeExpression = (FullNamedExpression) yyVals[-2+yyTop]; + + if (yyVals[-1+yyTop] != null) { + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (c.Variable); + } + + lbag.AddLocation (c, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = c; + } + +void case_851() +#line 5458 "cs-parser.jay" +{ + if (yyToken == Token.CLOSE_PARENS) { + report.Error (1015, lexer.Location, + "A type that derives from `System.Exception', `object', or `string' expected"); + } else { + Error_SyntaxError (yyToken); + } + + yyVal = new Catch (null, GetLocation (yyVals[-2+yyTop])); + } + +void case_854() +#line 5486 "cs-parser.jay" +{ + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); + } + +void case_856() +#line 5496 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new Lock ((Expression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_857() +#line 5507 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-2+yyTop])); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_858() +#line 5517 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_859() +#line 5522 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Fixed f = new Fixed ((Fixed.VariableDeclaration) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + current_block.AddStatement (f); + lbag.AddStatement (f, GetLocation (yyVals[-8+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_860() +#line 5535 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-2+yyTop])); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Using.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_861() +#line 5545 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_862() +#line 5550 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Using u = new Using ((Using.VariableDeclaration) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + lbag.AddStatement (u, GetLocation (yyVals[-8+yyTop]), GetLocation (yyVals[-2+yyTop])); + current_block.AddStatement (u); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_863() +#line 5560 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Using u = new Using ((Expression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (u, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + yyVal = u; + } + +void case_865() +#line 5576 "cs-parser.jay" +{ + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + yyVal = current_variable; + } + +void case_866() +#line 5587 "cs-parser.jay" +{ + lexer.query_parsing = false; + + Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_867() +#line 5599 "cs-parser.jay" +{ + Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_868() +#line 5610 "cs-parser.jay" +{ + lexer.query_parsing = false; + yyVal = yyVals[-1+yyTop]; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_869() +#line 5617 "cs-parser.jay" +{ + yyVal = yyVals[-1+yyTop]; + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_870() +#line 5626 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); + } + +void case_871() +#line 5634 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-4+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-3+yyTop] + } + ); + } + +void case_872() +#line 5649 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); + } + +void case_873() +#line 5657 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-4+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-3+yyTop] + } + ); + } + +void case_875() +#line 5676 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_877() +#line 5691 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + + yyVal = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-4+yyTop] + }; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_878() +#line 5708 "cs-parser.jay" +{ + Linq.AQueryClause head = (Linq.AQueryClause)yyVals[-1+yyTop]; + + if (yyVals[0+yyTop] != null) + head.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + + if (yyVals[-2+yyTop] != null) { + Linq.AQueryClause clause = (Linq.AQueryClause)yyVals[-2+yyTop]; + clause.Tail.Next = head; + head = clause; + } + + yyVal = head; + } + +void case_880() +#line 5724 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_882() +#line 5736 "cs-parser.jay" +{ + yyVal = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_883() +#line 5743 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock)current_block); + } + +void case_884() +#line 5751 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_885() +#line 5758 "cs-parser.jay" +{ + yyVal = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)yyVals[-3+yyTop], linq_clause_blocks.Pop (), (Expression)yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_889() +#line 5775 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-1+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_896() +#line 5795 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_898() +#line 5814 "cs-parser.jay" +{ + yyVal = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_899() +#line 5824 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_900() +#line 5832 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_901() +#line 5840 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_902() +#line 5848 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) yyVals[-10+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if (yyVals[0+yyTop] == null) { + into = sn; + yyVal = new Linq.Join (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, GetLocation (yyVals[-11+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-3+yyTop])); + } else { + /**/ + /* Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions*/ + /**/ + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + into = new Linq.RangeVariable (lt.Value, lt.Location); + + yyVal = new Linq.GroupJoin (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, into, GetLocation (yyVals[-11+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + +void case_903() +#line 5886 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_904() +#line 5894 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_905() +#line 5902 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_906() +#line 5910 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) yyVals[-10+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if (yyVals[0+yyTop] == null) { + into = sn; + yyVal = new Linq.Join (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, GetLocation (yyVals[-12+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-11+yyTop] + }; + } else { + /**/ + /* Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions*/ + /**/ + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + into = new Linq.RangeVariable (lt.Value, lt.Location); /* TODO:*/ + + yyVal = new Linq.GroupJoin (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, into, GetLocation (yyVals[-12+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-11+yyTop] + }; + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + +void case_910() +#line 5965 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + yyVal = yyVals[0+yyTop]; + } + +void case_912() +#line 5976 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_913() +#line 5983 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-3+yyTop]).Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-3+yyTop]; + } + +void case_915() +#line 5992 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); + } + +void case_916() +#line 5999 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-3+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-3+yyTop]; + } + +void case_918() +#line 6011 "cs-parser.jay" +{ + yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_919() +#line 6016 "cs-parser.jay" +{ + yyVal = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_921() +#line 6028 "cs-parser.jay" +{ + yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_922() +#line 6033 "cs-parser.jay" +{ + yyVal = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_924() +#line 6043 "cs-parser.jay" +{ + /* query continuation block is not linked with query block but with block*/ + /* before. This means each query can use same range variable names for*/ + /* different identifiers.*/ + + current_block.SetEndLocation (GetLocation (yyVals[-1+yyTop])); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_925() +#line 6059 "cs-parser.jay" +{ + var current_block = linq_clause_blocks.Pop (); + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation (yyVals[-3+yyTop])) { + next = (Linq.AQueryClause)yyVals[0+yyTop] + }; + } + +void case_928() +#line 6086 "cs-parser.jay" +{ + current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); + current_class = current_container; + + /* (ref object retval)*/ + Parameter [] mpar = new Parameter [1]; + mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); + + ParametersCompiled pars = new ParametersCompiled (mpar); + var mods = Modifiers.PUBLIC | Modifiers.STATIC; + if (settings.Unsafe) + mods |= Modifiers.UNSAFE; + + current_local_parameters = pars; + Method method = new Method ( + current_class, + null, /* generic*/ + new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), + mods, + new MemberName ("Host"), + pars, + null /* attributes */); + + current_container.AddMethod (method); + + oob_stack.Push (method); + ++lexer.parsing_block; + start_block (lexer.Location); + } + +void case_929() +#line 6116 "cs-parser.jay" +{ + --lexer.parsing_block; + Method method = (Method) oob_stack.Pop (); + + method.Block = (ToplevelBlock) end_block(lexer.Location); + + InteractiveResult = (Class) pop_current_class (); + current_local_parameters = null; + } + +void case_939() +#line 6159 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-1+yyTop]; + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + yyVal = null; + } + +void case_940() +#line 6165 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-3+yyTop]; + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName (lt.Value); + } + +void case_943() +#line 6180 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedParameters = (List)yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-6+yyTop], new MemberName (MemberCache.IndexerNameAlias)); + } + +void case_944() +#line 6185 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; + yyVal = null; + } + +void case_945() +#line 6193 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; + yyVal = null; + } + +void case_946() +#line 6201 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = (Operator.OpType) yyVals[-1+yyTop]; + yyVal = null; + } + +void case_954() +#line 6239 "cs-parser.jay" +{ + var parameters = new List (); + parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); + yyVal = parameters; + } + +void case_955() +#line 6245 "cs-parser.jay" +{ + var parameters = yyVals[-2+yyTop] as List; + parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); + yyVal = parameters; + } + +void case_956() +#line 6254 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != null) + yyVal = new DocumentationParameter ((Parameter.Modifier) yyVals[-1+yyTop], (FullNamedExpression) yyVals[0+yyTop]); + else + yyVal = new DocumentationParameter ((FullNamedExpression) yyVals[0+yyTop]); + } + +#line default + static readonly short [] yyLhs = { -1, + 0, 4, 0, 0, 1, 1, 1, 1, 2, 2, + 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 16, 21, 22, 19, 20, 20, 20, 24, 24, 25, + 25, 18, 7, 7, 6, 6, 23, 23, 8, 8, + 26, 26, 27, 27, 27, 27, 27, 9, 9, 10, + 10, 35, 33, 38, 34, 34, 36, 36, 36, 36, + 37, 37, 42, 39, 40, 41, 41, 43, 43, 43, + 43, 43, 44, 44, 48, 45, 47, 49, 49, 49, + 50, 50, 51, 51, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 65, 67, 70, 71, 29, + 29, 73, 69, 72, 72, 74, 74, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 78, 53, 79, + 79, 80, 80, 81, 83, 77, 77, 82, 82, 88, + 54, 92, 54, 54, 87, 95, 87, 89, 89, 96, + 96, 97, 98, 97, 93, 93, 99, 99, 100, 101, + 91, 91, 94, 94, 94, 104, 55, 107, 108, 102, + 109, 110, 111, 102, 102, 103, 103, 106, 106, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, + 115, 118, 118, 118, 121, 118, 119, 119, 122, 122, + 123, 123, 123, 116, 116, 116, 124, 124, 124, 117, + 126, 128, 129, 56, 131, 132, 133, 58, 127, 127, + 127, 127, 127, 137, 134, 138, 135, 136, 136, 136, + 139, 140, 141, 143, 30, 30, 142, 142, 144, 144, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 148, + 59, 147, 147, 149, 149, 152, 146, 146, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 154, 153, 155, 153, 153, 153, 60, 158, 160, 156, + 157, 157, 159, 159, 164, 162, 165, 162, 162, 166, + 61, 168, 57, 171, 172, 57, 167, 174, 167, 169, + 169, 175, 175, 176, 177, 176, 178, 173, 170, 170, + 170, 170, 170, 182, 179, 183, 180, 181, 181, 185, + 187, 188, 31, 184, 184, 184, 186, 186, 186, 189, + 189, 190, 191, 190, 192, 193, 194, 32, 195, 195, + 17, 17, 196, 196, 199, 198, 198, 198, 200, 200, + 202, 64, 125, 105, 105, 130, 130, 203, 203, 203, + 201, 201, 204, 204, 205, 205, 207, 207, 86, 76, + 76, 90, 90, 120, 120, 150, 150, 208, 208, 208, + 208, 208, 212, 212, 213, 213, 211, 211, 211, 211, + 211, 211, 211, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 216, 216, 216, 217, 217, 217, 237, 237, + 238, 238, 239, 239, 219, 219, 236, 236, 236, 236, + 236, 236, 236, 236, 221, 240, 240, 241, 241, 242, + 242, 244, 244, 244, 245, 245, 245, 245, 245, 246, + 246, 163, 163, 250, 250, 250, 250, 250, 252, 252, + 251, 251, 253, 253, 253, 253, 254, 222, 249, 249, + 249, 255, 255, 256, 256, 223, 224, 224, 225, 226, + 227, 227, 218, 218, 218, 218, 218, 261, 257, 228, + 262, 262, 263, 263, 264, 264, 265, 265, 265, 265, + 258, 258, 209, 209, 260, 260, 266, 266, 259, 259, + 85, 85, 267, 267, 268, 229, 269, 269, 269, 270, + 270, 270, 270, 270, 271, 197, 230, 231, 232, 233, + 273, 234, 274, 234, 272, 272, 276, 275, 220, 277, + 277, 277, 277, 277, 279, 280, 278, 278, 278, 278, + 278, 278, 278, 281, 281, 281, 281, 282, 282, 282, + 282, 282, 282, 283, 283, 283, 284, 284, 284, 284, + 284, 285, 285, 285, 286, 286, 287, 287, 288, 288, + 289, 289, 290, 290, 291, 291, 292, 292, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 293, 293, 294, + 294, 295, 295, 295, 296, 296, 297, 297, 300, 298, + 299, 299, 302, 301, 303, 301, 304, 305, 301, 306, + 307, 301, 46, 46, 247, 247, 247, 247, 235, 235, + 235, 84, 309, 310, 311, 312, 313, 28, 63, 63, + 62, 62, 112, 112, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 66, + 66, 68, 68, 68, 315, 315, 316, 317, 317, 318, + 318, 318, 318, 206, 206, 319, 319, 321, 113, 322, + 322, 323, 161, 320, 320, 324, 324, 325, 325, 325, + 325, 329, 329, 330, 330, 330, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 331, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 345, 345, 345, 345, 332, 346, 328, 347, + 347, 348, 348, 348, 348, 348, 348, 210, 210, 349, + 351, 326, 354, 326, 350, 350, 350, 352, 352, 357, + 357, 358, 358, 353, 353, 355, 355, 359, 359, 360, + 356, 356, 356, 333, 333, 344, 344, 361, 362, 362, + 334, 334, 363, 363, 366, 364, 365, 365, 367, 367, + 367, 370, 368, 369, 369, 371, 371, 335, 335, 335, + 335, 372, 373, 377, 374, 376, 376, 378, 378, 382, + 381, 381, 379, 379, 380, 380, 384, 383, 383, 375, + 385, 375, 336, 336, 336, 336, 336, 336, 386, 387, + 388, 388, 388, 389, 390, 391, 391, 392, 392, 337, + 337, 337, 337, 393, 393, 395, 395, 394, 396, 394, + 394, 338, 339, 397, 342, 340, 399, 400, 343, 401, + 402, 341, 341, 398, 398, 308, 308, 308, 308, 403, + 403, 405, 405, 407, 406, 408, 406, 404, 404, 404, + 412, 410, 413, 414, 410, 409, 409, 415, 415, 416, + 416, 416, 416, 416, 421, 417, 422, 418, 423, 424, + 425, 419, 427, 428, 429, 419, 426, 426, 431, 420, + 430, 434, 430, 433, 436, 433, 432, 432, 432, 435, + 435, 435, 411, 437, 411, 3, 3, 438, 3, 3, + 439, 439, 248, 248, 243, 243, 5, 440, 440, 440, + 440, 444, 440, 440, 440, 440, 441, 441, 442, 445, + 442, 443, 443, 446, 446, 447, + }; + static readonly short [] yyLen = { 2, + 2, 0, 3, 1, 2, 4, 3, 1, 0, 1, + 1, 2, 4, 2, 1, 2, 1, 1, 5, 2, + 3, 0, 0, 11, 1, 3, 1, 0, 1, 0, + 1, 1, 0, 1, 0, 1, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 2, 0, 3, 0, 6, 3, 1, 1, 1, 1, + 1, 3, 0, 3, 1, 0, 3, 0, 1, 1, + 3, 3, 1, 1, 0, 4, 4, 0, 1, 1, + 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 13, + 5, 0, 4, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 9, 0, + 1, 1, 2, 3, 0, 3, 1, 1, 1, 0, + 8, 0, 9, 6, 0, 0, 3, 0, 1, 1, + 2, 2, 0, 5, 0, 1, 1, 2, 3, 0, + 4, 2, 1, 1, 1, 0, 3, 0, 0, 10, + 0, 0, 0, 12, 8, 1, 1, 0, 1, 1, + 3, 3, 3, 5, 3, 5, 1, 1, 1, 1, + 3, 4, 6, 4, 0, 7, 0, 1, 1, 2, + 1, 1, 1, 4, 6, 4, 1, 2, 2, 1, + 0, 0, 0, 10, 0, 0, 0, 13, 1, 2, + 1, 2, 1, 0, 5, 0, 5, 1, 1, 1, + 0, 0, 0, 0, 15, 5, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 5, 1, 1, 1, 1, 0, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 7, 0, 7, 2, 2, 2, 0, 0, 9, + 1, 1, 0, 1, 0, 6, 0, 6, 1, 0, + 8, 0, 9, 0, 0, 10, 0, 0, 3, 0, + 1, 1, 2, 2, 0, 5, 0, 2, 2, 2, + 1, 1, 1, 0, 5, 0, 5, 1, 1, 0, + 0, 0, 12, 0, 2, 2, 0, 1, 2, 1, + 3, 2, 0, 5, 0, 0, 0, 13, 0, 1, + 1, 3, 1, 4, 2, 0, 3, 2, 1, 3, + 0, 3, 1, 1, 3, 1, 2, 3, 4, 4, + 0, 3, 1, 3, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 4, 4, 4, 3, + 3, 4, 3, 4, 4, 0, 1, 3, 4, 0, + 1, 1, 3, 2, 3, 1, 2, 3, 2, 1, + 1, 0, 1, 1, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 4, 3, 1, 4, 1, 3, + 2, 1, 3, 1, 1, 1, 4, 3, 2, 2, + 6, 3, 7, 4, 3, 7, 3, 0, 2, 4, + 1, 2, 0, 1, 1, 3, 3, 1, 1, 1, + 0, 1, 1, 2, 2, 3, 1, 2, 0, 1, + 2, 4, 1, 3, 0, 5, 1, 1, 1, 2, + 3, 3, 4, 4, 1, 2, 4, 4, 4, 4, + 0, 4, 0, 5, 0, 1, 0, 4, 4, 1, + 2, 2, 1, 1, 4, 2, 1, 2, 2, 2, + 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, + 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, + 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 5, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 3, 3, 2, 1, 0, 1, 1, 1, 0, 2, + 1, 1, 0, 4, 0, 5, 0, 0, 7, 0, + 0, 8, 1, 1, 1, 1, 1, 1, 6, 4, + 4, 1, 1, 0, 0, 0, 0, 15, 0, 1, + 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 0, 1, 1, 1, 2, 4, 1, 3, 1, + 3, 1, 1, 0, 1, 1, 1, 0, 4, 1, + 1, 0, 4, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, + 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, + 0, 6, 0, 7, 0, 2, 1, 0, 1, 1, + 2, 2, 4, 0, 2, 0, 1, 1, 2, 4, + 1, 5, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 5, 7, 0, 8, 0, 1, 1, 2, + 1, 0, 3, 1, 2, 3, 1, 1, 1, 1, + 1, 5, 7, 0, 4, 7, 1, 0, 1, 0, + 5, 1, 0, 1, 0, 1, 1, 1, 3, 6, + 0, 9, 1, 1, 1, 1, 1, 1, 2, 2, + 3, 4, 3, 3, 3, 4, 3, 0, 1, 3, + 4, 5, 3, 1, 2, 0, 1, 2, 0, 7, + 3, 2, 2, 0, 3, 5, 0, 0, 10, 0, + 0, 10, 5, 0, 2, 2, 2, 2, 2, 4, + 5, 4, 5, 0, 5, 0, 6, 3, 2, 1, + 0, 3, 0, 0, 6, 0, 1, 1, 2, 1, + 1, 1, 1, 1, 0, 5, 0, 3, 0, 0, + 0, 12, 0, 0, 0, 13, 0, 2, 0, 3, + 1, 0, 4, 1, 0, 4, 1, 2, 2, 1, + 2, 2, 0, 0, 4, 2, 3, 0, 4, 2, + 2, 3, 0, 1, 1, 1, 2, 2, 2, 4, + 3, 0, 7, 4, 4, 3, 1, 3, 0, 0, + 4, 0, 1, 1, 3, 2, + }; + static readonly short [] yyDefRed = { 0, + 8, 0, 0, 0, 0, 0, 0, 0, 2, 4, + 0, 0, 11, 14, 0, 926, 0, 0, 930, 0, + 0, 15, 17, 18, 389, 395, 402, 390, 392, 0, + 391, 0, 398, 400, 387, 0, 394, 396, 388, 399, + 401, 397, 351, 947, 0, 393, 937, 0, 10, 1, + 0, 0, 0, 12, 0, 780, 0, 0, 0, 0, + 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, + 0, 0, 428, 0, 0, 0, 486, 0, 429, 0, + 525, 0, 854, 0, 0, 0, 638, 0, 0, 0, + 0, 0, 0, 0, 688, 0, 737, 0, 0, 0, + 0, 0, 0, 0, 0, 427, 0, 627, 0, 779, + 720, 0, 0, 0, 0, 404, 405, 0, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 421, 422, 425, 426, 634, 557, 0, 553, + 554, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 635, 633, 636, 637, 704, 706, 0, 702, + 705, 721, 723, 724, 725, 726, 727, 728, 729, 730, + 731, 732, 722, 0, 0, 0, 781, 782, 798, 799, + 800, 801, 823, 824, 825, 826, 827, 828, 0, 0, + 0, 20, 0, 0, 0, 341, 0, 343, 934, 16, + 927, 0, 0, 254, 253, 250, 255, 256, 249, 268, + 267, 260, 261, 257, 259, 258, 262, 251, 252, 263, + 264, 270, 269, 265, 266, 0, 0, 950, 0, 939, + 0, 938, 3, 52, 0, 0, 0, 42, 39, 41, + 43, 44, 45, 46, 47, 50, 13, 0, 0, 0, + 829, 431, 432, 852, 0, 0, 0, 0, 0, 0, + 406, 0, 830, 0, 547, 541, 546, 736, 778, 707, + 734, 733, 735, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 717, 718, 719, 0, 0, 0, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 839, 0, 403, 0, 0, 0, 0, 0, 0, + 853, 0, 0, 0, 750, 746, 0, 0, 0, 0, + 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 630, 556, 0, 0, 552, 558, 559, 551, + 563, 562, 560, 561, 0, 0, 623, 738, 536, 0, + 424, 423, 0, 0, 0, 0, 340, 0, 744, 745, + 0, 489, 490, 0, 0, 0, 742, 743, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 929, 703, 751, 741, 0, 776, 777, 880, + 897, 0, 0, 0, 909, 868, 866, 890, 0, 0, + 888, 891, 892, 893, 894, 869, 867, 0, 0, 0, + 345, 0, 21, 0, 0, 0, 946, 0, 352, 0, + 0, 0, 948, 0, 0, 40, 660, 666, 658, 0, + 655, 665, 659, 657, 656, 663, 661, 662, 668, 664, + 667, 669, 0, 0, 653, 51, 488, 0, 0, 484, + 485, 0, 482, 0, 753, 0, 0, 0, 0, 774, + 775, 0, 0, 0, 642, 0, 833, 831, 643, 0, + 0, 510, 0, 0, 0, 501, 0, 505, 515, 517, + 0, 497, 0, 0, 0, 0, 0, 492, 0, 495, + 0, 499, 372, 834, 0, 0, 835, 843, 0, 0, + 0, 844, 0, 0, 855, 0, 0, 749, 0, 382, + 0, 378, 379, 0, 377, 380, 381, 0, 0, 0, + 564, 0, 0, 543, 625, 0, 701, 0, 0, 696, + 698, 699, 700, 435, 436, 837, 0, 0, 0, 348, + 349, 0, 192, 191, 193, 0, 0, 0, 0, 374, + 0, 610, 0, 0, 440, 0, 443, 0, 441, 0, + 0, 0, 0, 0, 0, 469, 472, 0, 0, 464, + 471, 470, 0, 599, 600, 601, 602, 603, 604, 605, + 606, 607, 609, 608, 565, 567, 566, 572, 573, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 596, 0, 0, 514, 0, 0, + 0, 0, 0, 0, 0, 881, 883, 879, 0, 889, + 0, 0, 342, 944, 945, 366, 0, 0, 363, 0, + 0, 189, 0, 0, 954, 940, 942, 60, 58, 59, + 0, 0, 53, 0, 0, 61, 63, 27, 25, 0, + 0, 0, 650, 0, 654, 439, 0, 487, 0, 538, + 0, 549, 179, 200, 0, 0, 169, 0, 0, 0, + 180, 542, 0, 857, 807, 0, 818, 805, 0, 809, + 0, 0, 0, 832, 0, 0, 0, 500, 0, 516, + 518, 0, 0, 456, 0, 0, 452, 0, 0, 479, + 0, 520, 494, 0, 155, 521, 153, 154, 523, 0, + 537, 0, 848, 0, 841, 0, 845, 529, 0, 0, + 0, 367, 0, 527, 0, 0, 539, 0, 860, 0, + 872, 0, 870, 0, 0, 640, 641, 0, 0, 0, + 690, 691, 689, 697, 836, 618, 624, 617, 0, 739, + 0, 347, 613, 0, 0, 0, 555, 444, 438, 442, + 437, 540, 478, 477, 474, 473, 0, 468, 433, 434, + 445, 0, 0, 757, 0, 0, 898, 874, 0, 899, + 0, 895, 0, 910, 0, 0, 0, 0, 878, 19, + 344, 687, 686, 0, 685, 0, 362, 956, 190, 951, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 369, + 0, 644, 0, 0, 80, 79, 0, 483, 0, 0, + 0, 0, 0, 548, 0, 0, 0, 0, 0, 810, + 0, 0, 0, 0, 0, 856, 507, 506, 459, 0, + 0, 935, 936, 448, 454, 0, 457, 0, 481, 0, + 0, 0, 0, 0, 785, 851, 0, 842, 535, 530, + 0, 0, 526, 0, 863, 0, 802, 873, 871, 0, + 544, 626, 0, 622, 621, 620, 350, 612, 611, 628, + 476, 0, 466, 465, 598, 0, 771, 756, 0, 0, + 0, 760, 0, 876, 0, 903, 0, 918, 919, 912, + 882, 884, 924, 365, 364, 955, 0, 0, 62, 56, + 0, 64, 26, 23, 0, 0, 320, 0, 226, 0, + 101, 0, 77, 765, 128, 129, 0, 0, 0, 768, + 198, 199, 0, 0, 0, 0, 172, 181, 173, 175, + 0, 0, 0, 0, 814, 0, 819, 820, 0, 0, + 458, 460, 461, 455, 449, 453, 0, 512, 0, 480, + 491, 447, 524, 522, 0, 847, 0, 0, 531, 0, + 0, 639, 631, 0, 475, 0, 0, 752, 761, 875, + 0, 0, 0, 896, 0, 0, 0, 943, 0, 0, + 0, 69, 70, 73, 74, 0, 335, 326, 325, 0, + 645, 222, 97, 0, 754, 769, 184, 0, 196, 0, + 0, 0, 803, 865, 0, 0, 0, 821, 784, 496, + 493, 791, 0, 797, 0, 0, 789, 0, 794, 849, + 534, 533, 0, 0, 629, 0, 0, 877, 900, 0, + 0, 0, 914, 0, 925, 0, 75, 67, 0, 0, + 0, 321, 0, 0, 0, 0, 0, 185, 0, 176, + 174, 858, 811, 0, 0, 816, 0, 0, 786, 790, + 0, 795, 0, 861, 632, 0, 763, 0, 904, 921, + 922, 915, 885, 55, 0, 71, 72, 0, 0, 0, + 0, 0, 0, 0, 770, 183, 0, 195, 0, 0, + 822, 796, 0, 692, 850, 0, 772, 0, 0, 0, + 76, 0, 0, 336, 0, 322, 0, 330, 386, 385, + 0, 383, 674, 0, 646, 0, 675, 223, 98, 186, + 859, 806, 0, 862, 901, 0, 916, 0, 0, 0, + 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, + 905, 29, 24, 337, 0, 0, 331, 384, 0, 0, + 0, 102, 99, 693, 0, 0, 0, 0, 323, 682, + 0, 683, 680, 0, 678, 95, 0, 94, 0, 0, + 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 156, 0, 0, 239, 231, 232, 233, 234, 235, 236, + 237, 238, 0, 0, 229, 0, 0, 0, 902, 0, + 338, 334, 0, 0, 0, 647, 84, 0, 282, 277, + 281, 0, 224, 230, 116, 108, 109, 110, 111, 112, + 113, 114, 115, 117, 0, 0, 106, 100, 908, 906, + 681, 679, 0, 0, 0, 0, 0, 0, 0, 290, + 0, 0, 240, 0, 0, 248, 0, 167, 157, 166, + 0, 103, 107, 0, 0, 276, 0, 0, 275, 0, + 161, 0, 0, 356, 0, 354, 0, 0, 201, 0, + 0, 0, 0, 0, 648, 225, 118, 0, 353, 0, + 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, + 158, 0, 0, 205, 0, 357, 0, 243, 242, 241, + 0, 0, 294, 0, 273, 134, 0, 271, 0, 0, + 0, 136, 0, 358, 0, 0, 202, 0, 0, 0, + 355, 246, 127, 125, 0, 0, 298, 0, 0, 0, + 0, 0, 162, 0, 279, 0, 0, 0, 0, 140, + 0, 0, 0, 0, 359, 360, 0, 0, 0, 0, + 0, 122, 313, 0, 295, 0, 0, 307, 0, 0, + 0, 302, 0, 152, 0, 0, 0, 0, 147, 0, + 0, 291, 0, 137, 0, 131, 141, 159, 165, 213, + 0, 203, 0, 0, 0, 0, 126, 0, 119, 123, + 0, 0, 0, 309, 0, 310, 299, 0, 0, 293, + 303, 274, 0, 0, 133, 148, 272, 0, 289, 0, + 280, 284, 143, 0, 0, 0, 210, 212, 206, 247, + 124, 314, 316, 296, 0, 0, 308, 305, 151, 149, + 163, 0, 0, 0, 160, 214, 216, 204, 0, 0, + 0, 307, 0, 285, 287, 144, 0, 0, 207, 318, + 319, 315, 317, 306, 164, 0, 0, 220, 219, 218, + 215, 217, 0, 0, 0, 208, 286, 288, + }; + protected static readonly short [] yyDgoto = { 7, + 8, 50, 9, 51, 10, 11, 52, 235, 685, 429, + 12, 13, 53, 22, 23, 24, 321, 195, 238, 670, + 828, 1016, 1133, 1480, 825, 239, 240, 241, 242, 243, + 244, 245, 246, 663, 444, 664, 665, 928, 666, 667, + 932, 826, 1011, 1012, 1013, 269, 587, 1105, 837, 1199, + 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, + 1210, 463, 674, 1296, 942, 1112, 1075, 1145, 1183, 1168, + 1227, 1255, 1226, 1256, 1257, 1140, 1355, 1332, 1380, 1381, + 1382, 944, 1378, 945, 728, 1272, 1343, 1319, 1368, 512, + 1361, 1337, 1397, 907, 1366, 1369, 1370, 1464, 1398, 1399, + 1395, 1211, 1279, 1238, 1297, 686, 1345, 1444, 1316, 1401, + 1473, 464, 270, 687, 688, 689, 690, 691, 650, 568, + 1117, 651, 652, 843, 1299, 1323, 1412, 1373, 1446, 1300, + 1348, 1469, 1493, 1413, 1414, 1491, 1477, 1478, 940, 1074, + 1167, 1223, 1281, 1224, 1225, 1273, 1330, 1303, 1274, 323, + 226, 1377, 1276, 1362, 1359, 1212, 1240, 1293, 1441, 1403, + 1125, 1442, 588, 1486, 1487, 1292, 1358, 1334, 1390, 1385, + 1356, 1422, 1427, 1388, 1391, 1392, 1472, 1428, 1386, 1387, + 1482, 1470, 1471, 937, 1020, 1136, 1110, 1161, 1137, 1138, + 1175, 1071, 1159, 1187, 532, 196, 112, 431, 198, 562, + 439, 227, 1311, 648, 649, 814, 830, 324, 406, 530, + 303, 1141, 1142, 46, 114, 304, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 255, 791, 981, + 508, 715, 864, 716, 717, 974, 137, 201, 721, 589, + 590, 591, 592, 785, 472, 473, 298, 979, 723, 407, + 300, 495, 496, 497, 498, 501, 730, 310, 745, 746, + 880, 266, 478, 758, 267, 477, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 571, 572, 573, 767, 768, 896, 769, + 155, 558, 759, 353, 994, 546, 1054, 156, 490, 938, + 1073, 1165, 1277, 465, 1146, 1147, 1194, 1195, 815, 548, + 335, 763, 1153, 549, 550, 271, 272, 273, 159, 160, + 161, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 173, 286, 559, 174, 175, 317, 796, + 627, 910, 840, 681, 948, 908, 911, 912, 949, 950, + 287, 176, 177, 178, 1045, 985, 1046, 1047, 1048, 1091, + 1049, 179, 180, 181, 182, 698, 483, 699, 966, 1084, + 700, 964, 701, 1086, 1087, 183, 184, 185, 186, 187, + 188, 305, 521, 522, 987, 1093, 313, 963, 849, 1119, + 886, 1126, 189, 417, 190, 418, 913, 1001, 419, 639, + 809, 806, 807, 1006, 420, 421, 422, 423, 424, 425, + 917, 629, 915, 1098, 1170, 1229, 1003, 1129, 1186, 804, + 635, 805, 1062, 1005, 1063, 1130, 1007, 17, 19, 47, + 48, 230, 653, 822, 440, 654, 655, + }; + protected static readonly short [] yySindex = { -157, + 0, -201, -137, -18, 44,11653, 0, 248, 0, 0, + 44, -18, 0, 0, 104, 0, 6498, 44, 0, -196, + -237, 0, 0, 0, 0, 0, 0, 0, 0, 99, + 0, 223, 0, 0, 0, 1006, 0, 0, 0, 0, + 0, 0, 0, 0, 93, 0, 0, 544, 0, 0, + 248, 259, 44, 0, 258, 0, 87, 294, 353,11153, + 318, -29, 328, 6655, 0, -29, -29, -29, -175, -29, + -29, 587, 0,10172, -29, -29, 0,10172, 0, 388, + 0, 353, 0, -29, 330, -29, 0, 8204,11672, 390, + -29, -29, -162,10976, 0,10172, 0,10852,10852,10852, +10852,10852,10852,10852,10852, 0, -103, 0,11726, 0, + 0, 363, -260, 795, 302, 0, 0, 447, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1069, 0, + 0, 685, 66, 498, 616, 597, 456, 462, 480, 505, + 137, 548, 0, 0, 0, 0, 0, 0, 3318, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 571, 600, -285, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -105, 95, + 259, 0, 401, 606, 627, 0, 615, 0, 0, 0, + 0,11726,11726, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 674, 633, 0, 646, 0, + -249, 0, 0, 0, 259,12475, 259, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 830, 688,10308, + 0, 0, 0, 0,10172, -29, -29, 834, 512, 795, + 0, 698, 0,11726, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 801, 74,11153, 0,11726, +10172, 757, 776,10172,10172, 4520, 326, 109, 779,11743, + 264, 0, 782, 0, 822,11726,10172, 840, 516, -29, + 0,10172, 388, 9628, 0, 0, 330,10172, 330, -205, + 547, 803, 0, 600, 302, -1, 810,10172,10172,10172, + 328, 892, 0, 0, 6812, -56, 0, 0, 0, 0, + 0, 0, 0, 0, 870,10172, 0, 0, 0, 1324, + 0, 0,11582, -289, 860, 839, 0, -84, 0, 0, + 263, 0, 0, 842,10308, 9356, 0, 0,10852,10172, +10172,10172,10172,10172,10172,10172,10172,10172,10172,10172, +10852,10852,10852,11726,11726,10852,10852,10852,10852,10852, +10852,10852,10852,10852,10852,10852,10852,10852,10852,10852, +10852,10172, 0, 0, 0, 0, 600, 0, 0, 0, + 0,11797,11821, 849, 0, 0, 0, 0, 33, 856, + 0, 0, 0, 0, 0, 0, 0, 259, 259, 853, + 0, 867, 0, 839, 674, 674, 0, -86, 0, -206, + 674, 909, 0, -198,12475, 0, 0, 0, 0, -192, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 235,12518, 0, 0, 0, 839, 419, 0, + 0, 561, 0, 886, 0, 920, 67, 388, -29, 0, + 0, 881, 7735, -147, 0, 940, 0, 0, 0, 945, + 946, 0, 417, 0, 951, 0, 947, 0, 0, 0, + 680, 0, 7871, 681,10172, 779, 9356, 0, 7283, 0, + 330, 0, 0, 0, 948, 950, 0, 0, 353, 388, + 267, 0, 4201, 952, 0, 953, 908, 0, 956, 0, +10172, 0, 0, 1035, 0, 0, 0,10172, 1036, 972, + 0, 975, 976, 0, 0,11582, 0, -288, 6812, 0, + 0, 0, 0, 0, 0, 0, 974, 388, 6812, 0, + 0, -286, 0, 0, 0, 330, -289, 935,11871, 0, + 980, 0, 987,10852, 0, 275, 0, 349, 0, 839, + 793,10172,10172, 994, 1110, 0, 0, -36, 993, 0, + 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 685, + 685, 66, 66, 498, 498, 498, 498, 616, 616, 597, + 456, 462, 480, 505, 0, 995, -186, 0,10172, 80, + 955, 113, 957, 996,10172, 0, 0, 0, 1012, 0, + 200, 839, 0, 0, 0, 0, 517, 242, 0,11871, + -206, 0, 997, 1000, 0, 0, 0, 0, 0, 0, + -289, 606, 0, 1001, 1005, 0, 0, 0, 0, 1007, +11895, 963, 0, 361, 0, 0, 542, 0,10308, 0, + 1016, 0, 0, 0, 711, 1010, 0, 1041, 1042, 1044, + 0, 0,10172, 0, 0, 1002, 0, 0, 1043, 0, + 1049,10172, 1130, 0, 6655, 6655, 8030, 0, 4520, 0, + 0, 9764, 236, 0, -281, 58, 0, 999, 1003, 0, + -185, 0, 0, 1053, 0, 0, 0, 0, 0, 1055, + 0, 1063, 0, 4360, 0, 388, 0, 0, 330, 428, + 573, 0, 1013, 0, 1060, 1061, 0, 6655, 0, 6655, + 0,10172, 0,10172,11726, 0, 0, 388, 388, 1066, + 0, 0, 0, 0, 0, 0, 0, 0, 8187, 0, +11726, 0, 0, 1015,11582, 1092, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9220, 0, 0, 0, + 0, 9492,10172, 0, 7440, 1065, 0, 0, 1146, 0, + 1147, 0, 667, 0, 1068,10172,10172, 1025, 0, 0, + 0, 0, 0, 1028, 0, -86, 0, 0, 0, 0, + -206, -206, 0, 853, 1075, 1078, 1033, 1085, 963, 0, + 1079, 0, 1197, 1199, 0, 0,10172, 0, 9900, 1082, + 711,11871,11726, 0, 128, 1203, 1205, 1090, 1086, 0, +10172,10172, 1094,10172, 1188, 0, 0, 0, 0, 31, +10036, 0, 0, 0, 0, 7576, 0, 1225, 0, 600, +10172, 1115, 8030, 1116, 0, 0, 1067, 0, 0, 0, + 1072, 556, 0, 1073, 0, 1086, 0, 0, 0, 1111, + 0, 0, 1143, 0, 0, 0, 0, 0, 0, 0, + 0, 637, 0, 0, 0,11743, 0, 0, 1074, 1117, + 1065, 0,10172, 0,10172, 0,10172, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1125, 853, 0, 0, +10444, 0, 0, 0, 1136, 7300, 0, 963, 0, 963, + 0, 963, 0, 0, 0, 0, 1091, 1132, 1082, 0, + 0, 0, -188, -181, 1113, 1137, 0, 0, 0, 0, + 1134, 8030, 1065, -186, 0, 1138, 0, 0, 1140, 6655, + 0, 0, 0, 0, 0, 0, 1145, 0, 779, 0, + 0, 0, 0, 0, -203, 0, 1141, 556, 0, 1095, + 1065, 0, 0, 388, 0, 1096, 1142, 0, 0, 0, +10172, 1180,10172, 0,10172, 1179, 461, 0, 1005, 238, + 762, 0, 0, 0, 0, -18, 0, 0, 0, 1164, + 0, 0, 0, 1155, 0, 0, 0, 481, 0, 1156, + 1285, 1287, 0, 0, 1181, 1065,10172, 0, 0, 0, + 0, 0,10172, 0, 1184, -191, 0, -191, 0, 0, + 0, 0, 1182, 388, 0,10172, 7440, 0, 0, 1208, + 702, 1183, 0,10172, 0, 1186, 0, 0,10444, 44, + 67, 0, 1185, 1185, 1185, 9900, 1189, 0,10172, 0, + 0, 0, 0, 1192, 1049, 0, 6655, 1190, 0, 0, + 6812, 0, 1191, 0, 0, 1202, 0,10172, 0, 0, + 0, 0, 0, 0,10172, 0, 0, 259, 1195, 259, + 7457, 71, 71, 71, 0, 0,10172, 0, 6655, 6655, + 0, 0, 6812, 0, 0, 6655, 0, 1213,10172,10172, + 0, 259, 1201, 0, 1157, 0, 1204, 0, 0, 0, + 1207, 0, 0, 1158, 0, 1234, 0, 0, 0, 0, + 0, 0, 6812, 0, 0, 1235, 0, 1206, 71, 0, + 1216, 259, 7457, 1210, 1219, 0, 1220, 1221, 1224,10172, + 0, 0, 0, 0, 1212, 1206, 0, 0,11232, -65, + 259, 0, 0, 0, 1239,10172, 1222,10172, 0, 0, + 1226, 0, 0, 1228, 0, 0,12518, 0, 1232, -65, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -262,12518, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1238, 259, 0, 259, 1206, 1178, 0, 1239, + 0, 0, 1236,11232,11398, 0, 0, -255, 0, 0, + 0,11430, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1242, 259, 0, 0, 0, 0, + 0, 0,11726,11726, 225,11743, 316, 330, 1270, 0, + -289, 640, 0, 1306, 0, 0, 1206, 0, 0, 0, + 1206, 0, 0, 1198, 1200, 0,11726, -164, 0,11726, + 0, 1209, 1244, 0, -289, 0, 1246, 9112, 0, 1251, + 1211, -46, 351, 1006, 0, 0, 0, -289, 0, 1254, + 1214, 1252, 1237, 0, 1255, 1200, 1260, 67, 1241, 1261, + 0, 1262, 1258, 0, 839, 0, 678, 0, 0, 0, + 1264, -184, 0, 1266, 0, 0, 1267, 0, 1268, 1271, + 1273, 0, 1274, 0, 67, 67, 0, 67, 1276, 1277, + 0, 0, 0, 0, 1278, 62, 0, 1282, 67, 1401, + 1286, 67, 0, -255, 0, 8030, 1245, 1283, 1274, 0, + 1290, 1292, 77, 1295, 0, 0, 67, 9900, 1248, 1291, + 1278, 0, 0,12518, 0, 259, 259, 0, 1250, 1293, + 1282, 0, 1298, 0,10172, 1257, 1296, 1286, 0, 1301, + 67, 0, -77, 0, 1299, 0, 0, 0, 0, 0, +12518, 0, 77, 77, 1309, 1305, 0, -184, 0, 0, + 219, 1311,12518, 0,12518, 0, 0, 8030, 1300, 0, + 0, 0, 1312, 1267, 0, 0, 0, 1316, 0, 20, + 0, 0, 0, 71, 848, 1321, 0, 0, 0, 0, + 0, 0, 0, 0, 1375, 1428, 0, 0, 0, 0, + 0, 1323, 1325, 8030, 0, 0, 0, 0, 77, 412, + 412, 0, 71, 0, 0, 0, 110, 110, 0, 0, + 0, 0, 0, 0, 0, 9356, 9356, 0, 0, 0, + 0, 0, 1327, 1326, 1331, 0, 0, 0, + }; + protected static readonly short [] yyRindex = { 2851, + 0, 0, 6969, 2851, 0, 0, 0, 1704, 0, 0, + 3004, 2782, 0, 0, 0, 0, 0, 3004, 0, 0, + 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1708, 0, 0, 1708, 0, 0, + 1704, 3047, 2898, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, + 0,11949, 0, 1334, 0, 0, 0, 1334, 0, 0, + 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3630, 0, 0, 0, + 0, 0, 313, 4518, 3789, 0, 0, 4359, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4674, 0, + 0, 4742, 5086, 5290, 5630, 358, 5902, 6038, 6174, 6310, + -194, 293, 0, 0, 0, 0, 0, 0, 42, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1294, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 939, 939, + 3090, 0, 595, 1337, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1708, 228, 0, 0, 0, + 0, 0, 0, 0, 3133, 402, 3176, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3405, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1350, 0, 0, 0, 0, + 3405, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2039, 0, 1150, 692, + 2169, 0, 0, 2316, 2169, 692, 0, 0, 0, 0, + 1342, 0, 0, 0, 145, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1334, 0, 0, 0, 0, + 0, 0, 1349, 2441, 0, 3405, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, + 0, 0, 0, 0, 0, 0, 0, 3239, 2606, 0, + 0, 0, 0, 1886, 1708, 1708, 0, -122, 0, 7752, + 1708, 1722, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 364,11085, 0, 0, 0, 3405, 3948, 0, + 0, 0, 0, 0, 0, 0,11474, 0, 0, 0, + 0, 0, 1354, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 818, 0, 0, 1357, 0, 0, 0, + 0, 0, 191, 0, 0, 3882, 1363, 0, 0, 0, + 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1590, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1349, 0, 0, 201, 0, + 0, 0, 0, 0, 0, 0, 0, 8344, 0, 0, + 0, 0, 0, 0, 0, -197, 537, 0, 0, 0, + 1365, 0, 0, 0, 0, 3405, 0, 3405, 0, 4041, + 0, 0, 0, 127, 0, 0, 0, 0, -20, 0, + 0, 0, 4846, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4914, + 5018, 5154, 5222, 5358, 5426, 5494, 5562, 5698, 5766, 5834, + 5970, 6106, 6242, 6366, 0, 0, 786, 0, 0, 692, + 0, 692, 0, 0, 0, 0, 0, 0, 988, 0, + 0, 1886, 0, 0, 0, 0, 1322, 0, 0, 0, +11966, 0, 0, 800, 0, 0, 0, 0, 0, 0, + 744, 664, 0, 0, 1374, 0, 0, 0, 0, 1378, + 0, 0, 0, 0, 0, 0,10580, 0, 0, 0, + 807, 0, 0, 0,12020, 0, 0, 808, 824, 833, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1370, 0, 0, 0, 0, 0, 0, 0, 1380, 0, + 0, 0, 3471, 0, 0, 202, 0, 49, 3564, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1381, + 0, 0, 0, 0, 0, 0, 0, 0, 254, 804, + 658, 0, 0, 0, 0, 1379, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8344, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 251, 0, 0, 0, 1377, 0, 0, 0, 0, + 0, 0, 641, 0, 614, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -122, 0, 0, 0, 0, +12020, 8047, 0, 1384, 0, 805, 0, 0, 0, 0, + 1383, 0, 1338, 1341, 0, 0, 0, 0, 0, 1386, +12044, 0, 0, 0,11550, 0, 0, 0, 857, 0, + 1387, 0, 0, 0, 1757, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3723, + 0, 4200, 1396, 0, 0, 0, 1393, 0, 0, 0, + 0, 804, 0, 0, 0, 857, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 821, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 871, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1391, 0, + 0, 0, 0, 0, 880, 884, 0, 0, 0, 0, + 0, 0, 1407, 786, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3882, 0, + 0, 0, 0, 0, 1412, 0, 0, 804, 0, 932, + 1407, 0, 0, 8344, 0, 632, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 176, 0, 1374, 8394, + 0, 0, 0, 0, 0,12092, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 770, 0, 775, + 0, 0, 0, 0, 0, 1377, 1409, 0, 0, 0, + 0, 0, 0, 0, 0, 1414, 0, 7126, 0, 0, + 0, 0, 0, 8344, 0, 0, 0, 0, 0, 0, + 679, 730, 0, 0, 0, 0, 0, 0, 0,12135, +11474, 0, 170, 170, 170, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1411, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,12246, 0, -290, + 0, 1418, 1418, 1418, 0, 0, 0, 0, 0, 0, + 0, 0, -178, 0, 0, 0, 0, 0, 0, 0, + 0,12289, 0, 0, 0, 0, 1419, 0, 0, 0, + 216, 0, 0, 0, 0, 445, 0, 0, 0, 0, + 0, 0, 1420, 0, 0, 0, 0, 2961, 1410, -257, + 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2719, 0, 0, 0, 8548, + 8944, 0, 0, 0, 745, 0, 0, 0, 0, 0, + 0, 0, 0, -244, 0, 0,11256, 0, 0, 8647, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,11324, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9038, 0, 8746, 2719, 0, 0, 745, + 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, + 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8845, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4648, 457, 0, + 9080, 0, 0, 0, 9150, 0, 2719, 0, 0, 0, + 2719, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 866, 0, 1424, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 888, 0, 551, + 0, 0, 0, 0, 0, 0, 0,11474, 889, 0, + 0, 0, 0, 0, 1426, 0, 906, 0, 0, 0, + 0, 0, 0, 900, 0, 0, 0, 0, 0, 0, + 0, 0, 1437, 0,11474,11474, 0,11506, 0, 0, + 0, 0, 0, 0, 1460, 1390, 0, 1461,11474,10716, + 1463,11474, 0, 0, 0, 0, 0, 0, 1465, 0, + 0, 0,12445, 0, 0, 0,11474, 0, 0, 0, + 1467, 0, 0, 285, 0,11007,12407, 0, 0, 0, + 1468, 0, 0, 0, 0, 0, 0, 1472, 0, 0, +11474, 0, 490, 0, 910, 0, 0, 0, 0, 0, + 942, 0,12331,12369, 0, 0, 0, 0, 0, 0, + 0, 0, 1487, 0, 1586, 0, 0, 0, 926, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 492, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,12445,10888, +12203, 0, 492, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1363, 1363, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + protected static readonly short [] yyGindex = { 0, + 0, 1799, 0, 0, 0, -2, -10, -179, -42, 1800, + 0, 1841, 1854, 83, 0, 0, -6, 0, 0, 0, + 0, 0, 0, -826, -694, -224, -431, 0, 0, 0, + 0, 0, -193, 0, 0, 0, 934, 0, 1047, 0, + 0, 0, 0, 814, 815, -17, -230, 0, 0, 0, + 0, 672,-1118, -618, -488, -460, -427, -357, -308, -219, +-1116,-1131, 0, 1, 0, 234, 0,-1073, 0, 0, + 0, 0, 0, 0, 617, 173, 458, 0, 0, 0, + 493,-1039, 0, -276, -293, 1217, 0, 0, 0, -863, + 453, 0, 0, -492, 0, 0, 522, 0, 0, 497, + 0, 0, 532, 0,-1189, -934, 0, 0, 0, 0, + 0, 625, -13, 0, 0, 1054, 1056, 1057, 1215, -521, + 0, 0, -321, 1062, 613, 0, -995, 0, 0, 0, + 0, 0, 0, 0, 0, 427, 0, 0, 0, 0, + 0, 0, 0, 0, 683, 0, 0, 0, 0, -340, + 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 701, 0, -504, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 438, 0, 0, 535, 0, 0, 541, 543, + 465, 0, 0, 0, 0, 0, 0, 0, 0, 771, + 0, 0, 0, 0, -59, 0, -15, -91, 0, 0, + 605, 0, 665, 0, 1122, 0, 1416, -291, -274, -66, + 451, 0, 777, 0, -38, 518, 0, 0, 1027, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -269, 0, 132, 0, 0, + -320, 0, 0, 0, 1076, 0, -298, -134, 1229, 1159, + 0, 1151, 0, 1361, 1580, 1269, 0, 0, 968, 1882, + 0, 0, 0, 0, 1247, 0, 0, 0, 0, 0, + -515, 1624, 0, 0, 0, 0, 1865, 489, 0, 0, + 474, 922, 905, 918, 1564, 1565, 1566, 1572, 1563, 0, + 1571, 0, 0, 0, 1218, 1427, -708, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, + 0, 0, 0, -446, 0, 819, 0, 741, 0, 825, + 0, 0, 0, 890, -526, -16, -307, 12, 0, 1818, + 0, 68, 0, 86, 101, 105, 114, 117, 122, 147, + 148, 149, 150, 0, -667, 0, -25, 0, 0, 1020, + 0, -575, 0, 0, 0, 923, 0, 1077, 0, 1030, + -457, 0, 0, 0, 0, 0, 0, 941, 0, 0, + 937, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 949, 0, 0, 0, 0, 0, 0, 0, + 0, -26, 0, 1469, 0, 0, 0, 1103, 0, 0, + 0, 0, 0, -169, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1574, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 761, 0, 0, 0, 0, + 0, 0, 0, 0, 862, 0, 0, 0, 0, 0, + 0, -14, 1173, 0, 0, 0, 1175, + }; + protected static readonly short [] yyTable = { 110, + 157, 18, 724, 111, 197, 510, 44, 191, 513, 236, + 446, 428, 570, 194, 486, 352, 729, 675, 316, 471, + 427, 260, 764, 506, 403, 697, 494, 552, 158, 540, + 529, 569, 770, 232, 262, 874, 1115, 855, 856, 1148, + 1149, 933, 996, 466, 6, 254, 360, 774, 368, 535, + 892, 308, 1042, 359, 14, 367, 302, 658, 375, 192, + 302, 595, 1215, 668, 1043, 1235, 309, 1027, 311, 794, + 869, 1353, 197, 197, 1029, 442, 1043, 327, 336, 761, + 885, 1242, 887, 659, 162, 1174, 862, 771, 531, 793, + 408, 1313, 291, 197, 677, 1309, 357, 20, 1, 563, + 292, 349, 163, 200, 1124, 1215, 564, 1246, 1322, 1254, + 332, 95, 358, 1239, 331, 660, 332, 164, 565, 16, + 1278, 165, 677, 333, 350, 315, 1339, 48, 818, 772, + 166, 677, 628, 167, 471, 200, 1109, 1246, 168, 1254, + 762, 110, 157, 409, 595, 111, 702, 863, 236, 595, + 410, 595, 595, 595, 595, 595, 595, 595, 595, 595, + 595, 595, 345, 169, 170, 171, 172, 352, 43, 646, + 158, 48, 375, 595, 375, 595, 375, 595, 1439, 595, + 595, 595, 742, 48, 870, 349, 197, 197, 871, 793, + 1196, 199, 445, 264, 795, 595, 1354, 288, 289, 290, + 2, 294, 295, 446, 718, 570, 306, 307, 350, 352, + 346, 437, 722, 312, 857, 314, 15, 318, 1044, 661, + 375, 193, 329, 330, 569, 669, 162, 361, 570, 1028, + 1044, 443, 470, 411, 595, 466, 1030, 474, 412, 347, + 413, 552, 293, 793, 163, 366, 414, 415, 197, 260, + 528, 552, 1421, 1314, 533, 332, 333, 260, 537, 164, + 322, 327, 482, 165, 575, 536, 3, 4, 5, 6, + 703, 348, 166, 485, 197, 167, 489, 491, 1326, 1445, + 168, 355, 234, 1462, 197, 1055, 869, 349, 527, 516, + 197, 1455, 538, 1456, 524, 48, 526, 1440, 933, 525, + 489, 6, 1039, 234, 933, 169, 170, 171, 172, 570, + 350, 542, 543, 865, 1066, 554, 651, 1383, 551, 557, + 953, 651, 683, 416, 351, 651, 1143, 384, 302, 819, + 742, 1173, 1410, 576, 197, 789, 462, 197, 1417, 2, + 651, 252, 643, 577, 1463, 1095, 553, 470, 586, 1189, + 410, 463, 594, 595, 596, 597, 598, 599, 600, 601, + 602, 603, 604, 385, 502, 1488, 989, 651, 197, 197, + 1465, 1327, 555, 798, 435, 436, 676, 352, 20, 373, + 983, 636, 637, 1341, 626, 236, 651, 1035, 312, 349, + 253, 366, 790, 462, 967, 647, 197, 197, 971, 1485, + 1258, 352, 1288, 202, 871, 848, 800, 684, 463, 1144, + 1371, 1372, 350, 1374, 197, 1053, 933, 1447, 1448, 1121, + 644, 645, 933, 641, 1393, 670, 656, 1400, 197, 507, + 234, 866, 329, 411, 570, 234, 476, 662, 412, 494, + 413, 523, 1416, 386, 387, 234, 414, 415, 471, 480, + 1305, 1151, 1152, 569, 1306, 248, 45, 696, 1154, 249, + 1083, 638, 484, 228, 692, 229, 1438, 113, 955, 1034, + 349, 671, 1051, 1479, 1052, 503, 95, 504, 515, 252, + 1286, 1452, 48, 361, 779, 1489, 781, 720, 782, 586, + 373, 727, 373, 350, 373, 373, 234, 373, 638, 373, + 638, 570, 481, 349, 49, 733, 735, 743, 670, 250, + 113, 671, 694, 751, 113, 672, 741, 887, 887, 951, + 753, 55, 561, 426, 886, 886, 350, 203, 253, 1287, + 197, 505, 551, 1453, 115, 519, 670, 400, 325, 325, + 973, 373, 551, 373, 766, 946, 373, 651, 597, 401, + 811, 982, 736, 197, 671, 638, 608, 609, 450, 325, + 553, 903, 1216, 965, 784, 784, 361, 718, 695, 451, + 553, 1289, 432, 694, 747, 810, 673, 115, 347, 697, + 347, 115, 671, 867, 631, 633, 337, 338, 339, 340, + 341, 342, 343, 344, 361, 978, 764, 887, 361, 651, + 361, 361, 361, 361, 886, 1216, 347, 1247, 361, 113, + 693, 797, 677, 585, 513, 816, 861, 803, 1067, 450, + 1290, 352, 467, 747, 467, 368, 349, 234, 349, 695, + 451, 597, 832, 247, 197, 649, 597, 1247, 597, 597, + 597, 597, 597, 597, 597, 597, 597, 597, 597, 350, + 734, 350, 325, 325, 349, 197, 833, 817, 357, 649, + 597, 470, 597, 351, 597, 351, 597, 597, 597, 251, + 260, 368, 831, 651, 533, 489, 115, 350, 651, 467, + 578, 339, 651, 834, 853, 722, 649, 315, 350, 727, + 579, 351, 1217, 263, 720, 499, 585, 651, 265, 500, + 1015, 585, 778, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 325, 315, 410, 95, 197, 95, + 1218, 597, 878, 252, 651, 585, 1328, 585, 650, 585, + 339, 585, 585, 585, 888, 1217, 889, 1248, 113, 197, + 325, 585, 585, 651, 891, 766, 585, 585, 1198, 1214, + 325, 895, 650, 1219, 95, 197, 325, 585, 585, 197, + 328, 347, 350, 1218, 113, 1249, 1088, 1248, 1198, 586, + 585, 518, 253, 647, 586, 905, 780, 727, 95, 650, + 356, 430, 946, 552, 519, 113, 585, 1172, 921, 922, + 643, 349, 1214, 677, 1245, 1249, 1219, 707, 1250, 411, + 325, 520, 1118, 325, 412, 115, 413, 349, 197, 349, + 812, 673, 414, 415, 350, 552, 541, 662, 349, 943, + 673, 485, 813, 1220, 1245, 369, 197, 197, 1250, 935, + 350, 115, 350, 489, 325, 325, 969, 1065, 1015, 396, + 1150, 350, 593, 972, 351, 552, 351, 835, 879, 1077, + 397, 675, 115, 980, 836, 727, 283, 541, 672, 610, + 611, 1078, 325, 325, 398, 283, 1220, 672, 1251, 605, + 606, 607, 1221, 1404, 541, 541, 541, 541, 541, 541, + 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, + 197, 388, 389, 346, 1275, 1000, 811, 1002, 1251, 1004, + 447, 1275, 349, 357, 399, 346, 877, 446, 614, 346, + 614, 1232, 197, 1014, 228, 1221, 231, 1252, 352, 432, + 197, 662, 346, 448, 292, 350, 292, 890, 1132, 357, + 678, 292, 315, 113, 679, 1457, 449, 402, 1021, 351, + 1022, 451, 1023, 897, 727, 881, 452, 1252, 453, 454, + 455, 456, 911, 296, 346, 297, 457, 911, 315, 911, + 458, 1222, 911, 911, 1294, 911, 911, 346, 297, 350, + 346, 1476, 459, 325, 513, 460, 879, 461, 432, 917, + 766, 1494, 1495, 1058, 917, 1060, 917, 1061, 405, 917, + 917, 541, 917, 917, 394, 395, 325, 390, 391, 113, + 115, 462, 433, 773, 1222, 773, 1253, 773, 995, 113, + 792, 392, 393, 1070, 917, 954, 563, 920, 841, 325, + 918, 919, 920, 564, 920, 485, 339, 920, 920, 339, + 920, 920, 434, 65, 65, 565, 1253, 65, 1096, 727, + 766, 762, 911, 762, 228, 762, 1103, 438, 346, 710, + 719, 1014, 920, 711, 500, 1100, 1101, 1295, 485, 1108, + 346, 485, 777, 441, 346, 236, 115, 1135, 913, 917, + 381, 382, 383, 913, 551, 913, 115, 346, 913, 913, + 1128, 913, 913, 907, 946, 467, 261, 1131, 907, 236, + 907, 350, 438, 907, 907, 197, 907, 907, 508, 485, + 325, 346, 553, 346, 508, 468, 551, 920, 1019, 346, + 331, 1156, 1061, 346, 346, 475, 346, 346, 57, 1135, + 261, 325, 346, 346, 261, 261, 261, 261, 261, 261, + 261, 261, 487, 1068, 553, 1069, 551, 1197, 1213, 182, + 479, 182, 346, 182, 194, 509, 194, 197, 194, 371, + 346, 488, 1185, 346, 358, 113, 113, 1197, 913, 755, + 346, 755, 783, 197, 553, 252, 679, 361, 1230, 953, + 485, 953, 346, 907, 66, 346, 346, 170, 66, 170, + 764, 1213, 764, 1197, 325, 509, 362, 363, 425, 346, + 425, 509, 759, 177, 411, 177, 759, 514, 113, 412, + 113, 413, 178, 1320, 178, 325, 364, 414, 415, 425, + 425, 1466, 1467, 1197, 253, 517, 1320, 365, 197, 197, + 534, 325, 115, 115, 1280, 325, 197, 539, 864, 425, + 864, 574, 351, 1349, 545, 1350, 351, 425, 346, 130, + 425, 130, 68, 923, 68, 556, 130, 197, 197, 200, + 197, 200, 350, 171, 351, 171, 1301, 680, 351, 580, + 346, 351, 135, 351, 135, 115, 634, 115, 351, 1301, + 354, 197, 361, 297, 197, 297, 361, 657, 346, 361, + 351, 361, 1301, 142, 642, 142, 361, 886, 886, 1329, + 204, 682, 325, 325, 614, 615, 616, 617, 694, 304, + 1301, 304, 351, 532, 532, 651, 651, 1113, 1114, 612, + 613, 618, 619, 1384, 261, 704, 705, 706, 708, 731, + 709, 732, 261, 747, 748, 749, 923, 750, 752, 754, + 1411, 923, 205, 923, 923, 923, 923, 923, 923, 923, + 923, 923, 923, 1423, 1425, 755, 756, 757, 727, 765, + 1280, 1193, 773, 775, 541, 923, 325, 923, 776, 923, + 485, 923, 923, 923, 787, 788, 792, 808, 820, 793, + 1411, 1411, 799, 821, 801, 823, 802, 1433, 824, 827, + 43, 844, 206, 207, 208, 209, 325, 210, 211, 212, + 213, 214, 215, 216, 217, 261, 839, 218, 219, 220, + 221, 222, 223, 224, 225, 371, 1193, 261, 261, 261, + 727, 371, 261, 261, 845, 846, 923, 847, 851, 850, + 113, 513, 852, 854, 872, 868, 1411, 199, 873, 875, + 882, 883, 898, 884, 900, 1284, 1285, 893, 909, 914, + 916, 920, 923, 371, 930, 924, 727, 371, 931, 370, + 933, 934, 939, 936, 941, 947, 1481, 1481, 959, 1312, + 960, 961, 1315, 1490, 1490, 968, 962, 970, 586, 586, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 977, 503, 992, 984, 986, 993, 1031, 115, 371, 988, + 990, 997, 998, 371, 1008, 371, 371, 371, 371, 371, + 371, 371, 371, 371, 371, 371, 1017, 1025, 1024, 1033, + 1032, 1038, 1050, 1037, 1040, 879, 371, 371, 1056, 371, + 371, 371, 1057, 371, 371, 371, 1059, 371, 371, 1064, + 1072, 371, 371, 371, 371, 1076, 1079, 113, 371, 371, + 1080, 113, 1081, 371, 371, 371, 371, 371, 371, 371, + 371, 1089, 1082, 1094, 1099, 1104, 1102, 1124, 1116, 1111, + 1155, 325, 371, 1120, 1122, 371, 1134, 371, 1158, 113, + 113, 1127, 1144, 113, 1160, 1164, 113, 1162, 371, 560, + 1163, 1172, 1171, 1176, 1179, 1180, 1181, 1182, 25, 840, + 26, 1184, 1188, 27, 1228, 1259, 1233, 1231, 28, 1236, + 261, 1234, 29, 113, 115, 1243, 1291, 1261, 115, 1282, + 1304, 31, 1336, 325, 1318, 1307, 1321, 1308, 33, 1324, + 1333, 1342, 1335, 34, 1347, 1338, 1317, 35, 1325, 325, + 1340, 1327, 1346, 1344, 1352, 1360, 115, 115, 1363, 37, + 115, 38, 1364, 115, 1365, 39, 1357, 1367, 1375, 1376, + 48, 1379, 48, 40, 41, 1389, 1394, 42, 1406, 1396, + 319, 1408, 1405, 1409, 1415, 1418, 1419, 1429, 1430, 1432, + 115, 1435, 1437, 48, 1434, 1449, 1450, 513, 1454, 1443, + 1458, 1459, 513, 513, 325, 325, 48, 1461, 1468, 1453, + 1452, 48, 325, 1474, 1496, 1475, 48, 1497, 48, 48, + 48, 48, 1498, 9, 48, 513, 48, 949, 545, 838, + 48, 740, 32, 325, 325, 513, 325, 503, 513, 513, + 615, 941, 48, 513, 504, 48, 513, 48, 513, 808, + 513, 513, 513, 513, 462, 261, 616, 325, 513, 684, + 325, 354, 513, 30, 22, 812, 513, 502, 30, 324, + 528, 48, 758, 31, 513, 221, 783, 513, 96, 513, + 513, 766, 813, 31, 846, 513, 767, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 758, 787, + 815, 788, 817, 513, 672, 672, 328, 694, 513, 513, + 353, 513, 513, 513, 513, 513, 513, 513, 346, 513, + 513, 651, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 138, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 120, 300, 513, 145, 513, + 139, 513, 121, 301, 513, 840, 840, 146, 651, 233, + 513, 237, 54, 840, 840, 840, 840, 840, 21, 840, + 840, 1009, 840, 840, 840, 840, 840, 840, 840, 840, + 929, 1237, 1283, 1420, 840, 1451, 840, 840, 840, 840, + 840, 840, 1106, 1107, 840, 346, 1460, 829, 840, 840, + 1407, 840, 840, 840, 1436, 1402, 1298, 1310, 956, 842, + 957, 958, 952, 840, 1492, 840, 1244, 840, 840, 1484, + 1331, 840, 1241, 840, 840, 840, 840, 840, 840, 840, + 840, 840, 840, 840, 840, 1431, 840, 1426, 1424, 840, + 840, 1351, 1177, 840, 840, 1483, 1302, 925, 744, 1178, + 860, 976, 904, 786, 581, 902, 1041, 838, 840, 840, + 840, 840, 840, 299, 544, 858, 840, 840, 334, 620, + 840, 621, 624, 622, 1166, 840, 840, 840, 840, 840, + 623, 625, 760, 840, 1262, 840, 404, 1169, 1026, 1097, + 1123, 840, 840, 1036, 1092, 1085, 1090, 999, 991, 737, + 1260, 1157, 899, 640, 927, 926, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 840, 840, 840, 840, + 0, 840, 783, 783, 0, 0, 0, 0, 840, 0, + 783, 783, 783, 783, 783, 0, 783, 783, 0, 783, + 783, 783, 783, 783, 783, 783, 0, 0, 748, 0, + 0, 783, 0, 783, 783, 783, 783, 783, 783, 0, + 0, 783, 0, 0, 0, 783, 783, 0, 783, 783, + 783, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 783, 0, 783, 0, 783, 783, 0, 0, 783, 0, + 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, + 783, 783, 0, 783, 0, 0, 783, 783, 0, 0, + 783, 783, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 783, 783, 783, 783, 783, + 0, 0, 0, 783, 783, 0, 0, 783, 0, 0, + 0, 0, 783, 783, 783, 783, 783, 0, 0, 0, + 783, 346, 783, 0, 0, 0, 346, 346, 783, 783, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 339, 346, + 0, 0, 0, 783, 783, 783, 783, 0, 783, 346, + 0, 0, 346, 346, 0, 783, 0, 346, 0, 0, + 346, 0, 346, 0, 346, 346, 346, 346, 0, 0, + 0, 0, 346, 0, 0, 0, 346, 0, 0, 0, + 346, 0, 0, 0, 0, 0, 0, 0, 346, 0, + 0, 346, 0, 346, 346, 0, 0, 0, 0, 346, + 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 346, 0, 0, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 0, 0, 346, 346, 346, + 346, 346, 0, 0, 346, 346, 0, 0, 0, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 748, 0, 0, 0, 346, 748, + 748, 346, 0, 346, 0, 346, 0, 0, 346, 0, + 0, 0, 0, 0, 346, 376, 0, 0, 0, 0, + 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 748, 0, 0, 748, 748, 0, 0, 0, + 748, 0, 0, 748, 0, 748, 0, 748, 748, 748, + 748, 0, 0, 0, 0, 748, 0, 0, 0, 748, + 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, + 0, 748, 0, 0, 748, 0, 748, 748, 0, 0, + 0, 0, 748, 0, 748, 748, 748, 748, 748, 748, + 748, 748, 748, 748, 748, 0, 0, 0, 0, 0, + 748, 0, 0, 0, 0, 748, 748, 748, 748, 748, + 748, 0, 748, 748, 748, 0, 748, 748, 0, 0, + 748, 748, 748, 748, 339, 0, 0, 748, 748, 339, + 339, 0, 748, 748, 748, 748, 748, 748, 748, 748, + 346, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 748, 339, 0, 748, 0, 748, 0, 748, 0, + 0, 748, 339, 0, 0, 339, 339, 748, 0, 0, + 339, 0, 0, 339, 0, 339, 0, 339, 339, 339, + 339, 0, 0, 0, 0, 339, 0, 0, 0, 339, + 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 339, 0, 339, 339, 0, 0, + 0, 0, 339, 0, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 0, 0, 0, 0, 0, + 339, 0, 0, 0, 0, 339, 339, 339, 339, 339, + 339, 0, 339, 339, 339, 0, 339, 339, 0, 0, + 339, 339, 339, 339, 0, 0, 0, 339, 339, 0, + 0, 0, 339, 339, 339, 339, 339, 339, 339, 339, + 0, 376, 0, 0, 0, 0, 376, 376, 0, 0, + 0, 339, 0, 0, 339, 0, 339, 0, 339, 0, + 0, 339, 0, 0, 0, 0, 0, 339, 0, 376, + 0, 0, 0, 0, 0, 49, 0, 0, 0, 376, + 0, 0, 376, 376, 0, 0, 0, 376, 0, 0, + 376, 0, 376, 0, 376, 376, 376, 376, 0, 0, + 0, 0, 376, 0, 0, 0, 376, 0, 0, 0, + 376, 0, 0, 0, 0, 0, 0, 0, 376, 0, + 0, 376, 0, 376, 376, 0, 0, 0, 0, 376, + 0, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 376, 376, 0, 0, 0, 0, 0, 376, 0, 0, + 0, 0, 376, 376, 0, 376, 376, 376, 0, 376, + 376, 376, 0, 376, 376, 0, 346, 376, 376, 376, + 376, 0, 346, 0, 376, 376, 0, 0, 0, 376, + 376, 376, 376, 376, 376, 376, 376, 0, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 376, 0, + 0, 376, 0, 376, 346, 0, 0, 0, 346, 0, + 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, + 0, 36, 0, 0, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 0, 0, 346, + 346, 0, 0, 0, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 346, 0, 0, 346, 0, 346, 0, + 346, 0, 49, 346, 0, 0, 49, 0, 49, 346, + 49, 0, 49, 0, 0, 49, 0, 49, 49, 0, + 49, 0, 49, 0, 49, 0, 49, 49, 49, 49, + 0, 0, 49, 49, 0, 0, 0, 34, 49, 49, + 49, 49, 49, 0, 0, 49, 49, 49, 0, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 0, + 49, 0, 0, 0, 0, 49, 49, 0, 49, 49, + 0, 49, 49, 49, 0, 0, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 0, 0, 49, 0, 49, + 49, 0, 0, 0, 28, 28, 0, 0, 0, 28, + 0, 0, 49, 28, 0, 28, 0, 0, 28, 0, + 28, 28, 0, 28, 0, 28, 0, 28, 0, 28, + 28, 28, 28, 33, 0, 28, 28, 0, 0, 0, + 0, 28, 0, 28, 28, 28, 0, 0, 28, 28, + 28, 0, 28, 49, 0, 28, 0, 28, 28, 28, + 28, 0, 0, 0, 28, 28, 28, 0, 36, 28, + 28, 28, 36, 0, 0, 0, 5, 0, 28, 28, + 0, 28, 28, 36, 28, 28, 28, 0, 36, 0, + 28, 0, 36, 0, 0, 36, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 36, 0, + 28, 0, 36, 36, 0, 0, 28, 28, 36, 931, + 36, 36, 36, 36, 0, 28, 0, 0, 36, 0, + 0, 0, 36, 0, 36, 0, 0, 35, 0, 0, + 0, 35, 0, 0, 36, 0, 36, 36, 0, 36, + 0, 0, 35, 36, 0, 0, 0, 35, 0, 0, + 0, 35, 48, 0, 35, 0, 28, 0, 0, 0, + 0, 0, 0, 36, 0, 0, 35, 35, 0, 36, + 36, 35, 35, 0, 34, 0, 0, 35, 34, 35, + 35, 35, 35, 0, 0, 0, 0, 35, 0, 34, + 0, 35, 0, 35, 34, 7, 0, 0, 34, 0, + 0, 34, 0, 35, 0, 35, 35, 0, 35, 0, + 0, 0, 35, 34, 34, 0, 0, 0, 34, 34, + 0, 0, 0, 0, 34, 0, 34, 34, 34, 34, + 0, 0, 35, 0, 34, 0, 0, 28, 34, 35, + 34, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 0, 28, 34, 0, 34, 0, 28, 932, 34, + 0, 28, 0, 0, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28, 28, 0, 34, + 33, 28, 28, 0, 33, 34, 34, 28, 0, 28, + 28, 28, 28, 0, 0, 33, 0, 28, 0, 0, + 33, 28, 0, 28, 33, 0, 0, 33, 0, 0, + 0, 0, 0, 28, 0, 0, 28, 0, 28, 33, + 33, 0, 28, 5, 33, 33, 0, 48, 0, 0, + 33, 0, 33, 33, 33, 33, 0, 0, 48, 0, + 33, 0, 28, 48, 33, 0, 33, 48, 28, 28, + 48, 0, 0, 0, 0, 0, 33, 0, 0, 33, + 0, 33, 48, 48, 0, 33, 931, 48, 48, 0, + 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 0, 48, 0, 33, 48, 48, 0, 48, + 48, 0, 33, 48, 0, 0, 0, 0, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 0, 48, 48, + 48, 48, 0, 48, 0, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 48, 48, + 48, 0, 48, 48, 0, 0, 48, 0, 0, 0, + 0, 0, 48, 0, 0, 48, 0, 48, 48, 48, + 0, 48, 7, 48, 48, 0, 49, 0, 0, 48, + 0, 48, 48, 48, 48, 0, 0, 49, 0, 48, + 0, 48, 49, 48, 0, 48, 49, 0, 0, 49, + 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, + 48, 49, 49, 0, 48, 0, 49, 49, 0, 0, + 0, 0, 49, 0, 49, 49, 49, 49, 0, 0, + 0, 0, 49, 0, 48, 932, 49, 0, 49, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, + 48, 49, 0, 49, 0, 48, 0, 49, 0, 48, + 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 48, 0, 49, 0, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 0, 0, 48, + 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 0, 56, 48, 0, 48, 0, 0, 0, + 48, 57, 25, 58, 26, 0, 0, 27, 59, 0, + 60, 61, 28, 62, 63, 64, 29, 0, 0, 0, + 48, 0, 65, 0, 66, 31, 67, 68, 69, 70, + 0, 0, 33, 0, 0, 0, 71, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, + 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, + 346, 88, 89, 0, 0, 0, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, + 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, + 0, 102, 346, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 346, 0, 0, 0, + 0, 0, 346, 0, 106, 107, 108, 109, 0, 0, + 0, 0, 0, 346, 0, 0, 199, 0, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 346, 0, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 0, 515, + 0, 0, 346, 0, 346, 515, 0, 346, 0, 0, + 0, 0, 0, 346, 0, 0, 0, 0, 346, 0, + 0, 346, 0, 346, 346, 0, 0, 0, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 515, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 346, 346, 0, 0, 0, 0, 0, 0, + 346, 346, 0, 346, 0, 0, 0, 0, 0, 346, + 0, 0, 515, 0, 0, 0, 0, 515, 0, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 0, 0, 0, 0, 0, 0, 0, 346, 0, 0, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 0, 515, 515, 0, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 0, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 0, 511, 0, + 0, 0, 0, 515, 511, 0, 346, 0, 0, 0, + 0, 0, 515, 0, 0, 0, 0, 0, 346, 0, + 346, 0, 346, 0, 0, 346, 0, 346, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 511, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 346, 0, 346, + 403, 0, 346, 0, 0, 0, 0, 0, 346, 0, + 0, 511, 0, 0, 0, 0, 511, 0, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 0, + 0, 0, 0, 0, 0, 0, 403, 0, 0, 511, + 511, 0, 511, 511, 511, 511, 511, 511, 511, 0, + 511, 511, 0, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 0, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 0, 519, 0, 0, + 0, 0, 511, 519, 0, 511, 0, 0, 0, 0, + 0, 511, 0, 0, 0, 0, 0, 339, 0, 403, + 403, 403, 403, 0, 403, 0, 403, 403, 0, 403, + 403, 403, 403, 403, 0, 403, 403, 403, 403, 519, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 0, 0, 0, 0, 339, 0, 403, 346, + 0, 403, 0, 0, 0, 0, 0, 403, 0, 0, + 519, 0, 0, 0, 0, 519, 0, 519, 519, 519, + 519, 519, 519, 519, 519, 519, 519, 519, 0, 0, + 0, 0, 0, 0, 0, 346, 0, 0, 0, 519, + 0, 519, 519, 519, 519, 519, 519, 519, 0, 519, + 519, 0, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 0, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 519, 519, 519, 0, 346, 0, 0, 0, + 0, 519, 346, 0, 519, 0, 0, 0, 0, 0, + 519, 0, 0, 0, 0, 0, 0, 346, 346, 346, + 346, 346, 0, 0, 0, 346, 346, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 346, 0, 0, + 346, 0, 0, 0, 0, 0, 346, 0, 0, 346, + 0, 0, 0, 0, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 446, 738, 0, 0, 0, + 346, 446, 0, 346, 0, 25, 0, 26, 0, 346, + 27, 0, 0, 0, 0, 28, 0, 0, 0, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 33, 0, 446, 0, 0, + 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, + 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 0, 0, 42, 0, 0, 739, 446, 0, + 0, 0, 0, 446, 0, 446, 446, 446, 446, 446, + 446, 446, 446, 446, 446, 446, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 446, 0, 446, + 446, 446, 446, 446, 446, 446, 0, 446, 446, 0, + 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 0, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 446, 446, 446, 0, 406, 876, 0, 0, 740, 446, + 406, 0, 446, 0, 25, 0, 26, 0, 446, 27, + 0, 0, 0, 0, 28, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 406, 0, 0, 34, + 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, + 0, 39, 0, 0, 0, 0, 0, 0, 0, 40, + 41, 0, 0, 42, 0, 0, 319, 406, 0, 0, + 0, 0, 406, 0, 406, 406, 406, 406, 406, 406, + 406, 406, 406, 406, 406, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 406, 0, 406, 406, + 406, 406, 406, 406, 406, 0, 406, 0, 0, 406, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 0, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 406, 406, 0, 550, 0, 492, 0, 354, 406, 550, + 0, 406, 0, 57, 25, 0, 26, 406, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 550, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 550, 0, 0, 0, + 0, 550, 0, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 0, 0, 0, 0, 90, 91, + 92, 258, 0, 0, 0, 550, 0, 550, 0, 550, + 96, 550, 550, 550, 0, 550, 550, 0, 550, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 368, 0, + 0, 550, 550, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 550, 564, + 550, 368, 0, 0, 0, 564, 106, 493, 0, 0, + 0, 0, 0, 0, 368, 0, 550, 0, 0, 368, + 0, 0, 245, 0, 368, 0, 368, 368, 368, 368, + 0, 0, 0, 0, 368, 0, 0, 0, 368, 0, + 0, 564, 368, 0, 0, 0, 0, 0, 0, 0, + 368, 0, 0, 368, 0, 368, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 568, 0, 0, + 0, 0, 0, 568, 0, 0, 0, 0, 0, 368, + 0, 0, 564, 0, 0, 0, 0, 564, 0, 564, + 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 568, + 0, 564, 0, 564, 0, 564, 0, 564, 564, 564, + 0, 564, 564, 0, 0, 564, 564, 564, 564, 564, + 564, 564, 564, 564, 0, 368, 0, 564, 564, 564, + 564, 564, 564, 564, 564, 0, 0, 0, 0, 0, + 568, 0, 0, 0, 0, 568, 564, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 0, 0, + 0, 571, 564, 0, 0, 0, 0, 571, 0, 568, + 0, 568, 0, 568, 0, 568, 568, 568, 0, 568, + 568, 0, 0, 568, 568, 568, 568, 0, 0, 0, + 568, 568, 0, 0, 0, 568, 568, 568, 568, 568, + 568, 568, 568, 571, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 568, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 569, + 568, 0, 0, 0, 0, 569, 0, 0, 0, 0, + 0, 0, 0, 0, 571, 0, 0, 0, 0, 571, + 0, 571, 571, 571, 571, 571, 571, 571, 571, 571, + 571, 571, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 569, 0, 571, 0, 571, 0, 571, 0, 571, + 571, 571, 0, 571, 571, 0, 0, 571, 571, 571, + 571, 0, 0, 0, 571, 571, 0, 0, 0, 571, + 571, 571, 571, 571, 571, 571, 571, 0, 0, 0, + 0, 0, 569, 0, 0, 0, 0, 569, 571, 569, + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 0, 0, 0, 570, 571, 0, 0, 0, 0, 570, + 0, 569, 0, 569, 0, 569, 0, 569, 569, 569, + 0, 569, 569, 0, 0, 569, 569, 569, 569, 0, + 0, 0, 569, 569, 0, 0, 0, 569, 569, 569, + 569, 569, 569, 569, 569, 570, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 569, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 574, 569, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 570, 0, 0, 0, + 0, 570, 0, 570, 570, 570, 570, 570, 570, 570, + 570, 570, 570, 570, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 570, 0, 570, 0, 570, + 0, 570, 570, 570, 0, 570, 570, 0, 0, 570, + 570, 570, 570, 0, 0, 0, 570, 570, 0, 575, + 0, 570, 570, 570, 570, 570, 570, 570, 570, 0, + 0, 0, 0, 0, 574, 0, 0, 0, 0, 574, + 570, 574, 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 0, 0, 0, 0, 570, 0, 0, 0, + 0, 0, 0, 574, 0, 574, 0, 574, 0, 574, + 574, 574, 0, 0, 0, 0, 0, 574, 574, 574, + 574, 0, 0, 0, 574, 574, 0, 576, 0, 574, + 574, 574, 574, 574, 574, 574, 574, 0, 0, 0, + 0, 0, 575, 0, 0, 0, 0, 575, 574, 575, + 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, + 0, 0, 0, 0, 574, 0, 0, 0, 0, 0, + 0, 575, 0, 575, 0, 575, 0, 575, 575, 575, + 0, 0, 0, 0, 0, 575, 575, 575, 575, 0, + 0, 0, 575, 575, 0, 577, 0, 575, 575, 575, + 575, 575, 575, 575, 575, 0, 0, 0, 0, 0, + 576, 0, 0, 0, 0, 576, 575, 576, 576, 576, + 576, 576, 576, 576, 576, 576, 576, 576, 0, 0, + 0, 0, 575, 0, 0, 0, 0, 0, 0, 576, + 0, 576, 0, 576, 0, 576, 576, 576, 0, 0, + 0, 0, 0, 576, 576, 576, 576, 0, 0, 0, + 576, 576, 0, 578, 0, 576, 576, 576, 576, 576, + 576, 576, 576, 0, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 577, 576, 577, 577, 577, 577, 577, + 577, 577, 577, 577, 577, 577, 0, 0, 0, 0, + 576, 0, 0, 0, 0, 0, 0, 577, 0, 577, + 0, 577, 0, 577, 577, 577, 0, 0, 0, 0, + 0, 577, 577, 577, 577, 0, 0, 0, 577, 577, + 0, 579, 0, 0, 0, 577, 577, 577, 577, 577, + 577, 0, 0, 0, 0, 0, 578, 0, 0, 0, + 0, 578, 577, 578, 578, 578, 578, 578, 578, 578, + 578, 578, 578, 578, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 0, 0, 578, 0, 578, 0, 578, + 0, 578, 578, 578, 0, 0, 0, 0, 0, 578, + 578, 578, 578, 0, 0, 0, 578, 578, 0, 580, + 0, 0, 0, 578, 578, 578, 578, 578, 578, 0, + 0, 0, 0, 0, 579, 0, 0, 0, 0, 579, + 578, 579, 579, 579, 579, 579, 579, 579, 579, 579, + 579, 579, 0, 0, 0, 0, 578, 0, 0, 0, + 0, 0, 0, 579, 0, 579, 0, 579, 0, 579, + 579, 579, 0, 0, 0, 0, 0, 579, 579, 579, + 579, 0, 0, 0, 579, 579, 0, 581, 0, 0, + 0, 579, 579, 579, 579, 579, 579, 0, 0, 0, + 0, 0, 580, 0, 0, 0, 0, 580, 579, 580, + 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, + 0, 0, 0, 0, 579, 0, 0, 0, 0, 0, + 0, 580, 0, 580, 0, 580, 0, 580, 580, 580, + 0, 0, 0, 0, 0, 580, 580, 580, 580, 0, + 0, 0, 580, 580, 0, 582, 0, 0, 0, 580, + 580, 580, 580, 580, 580, 0, 0, 0, 0, 0, + 581, 0, 0, 0, 0, 581, 580, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 0, 0, + 0, 0, 580, 0, 0, 0, 0, 0, 0, 581, + 0, 581, 0, 581, 0, 581, 581, 581, 0, 0, + 0, 0, 0, 581, 581, 581, 581, 0, 0, 0, + 581, 581, 0, 583, 0, 0, 0, 581, 581, 581, + 581, 581, 581, 0, 0, 0, 0, 0, 582, 0, + 0, 0, 0, 582, 581, 582, 582, 582, 582, 582, + 582, 582, 582, 582, 582, 582, 0, 0, 0, 0, + 581, 0, 0, 0, 0, 0, 0, 582, 0, 582, + 0, 582, 0, 582, 582, 582, 0, 0, 0, 0, + 0, 0, 0, 582, 582, 0, 0, 0, 582, 582, + 0, 584, 0, 0, 0, 0, 0, 582, 582, 582, + 582, 0, 0, 0, 0, 0, 583, 0, 0, 0, + 0, 583, 582, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 583, 583, 0, 0, 0, 0, 582, 0, + 0, 0, 0, 0, 0, 583, 0, 583, 0, 583, + 0, 583, 583, 583, 0, 0, 0, 0, 0, 0, + 0, 583, 583, 0, 0, 0, 583, 583, 0, 586, + 0, 0, 0, 0, 0, 583, 583, 583, 583, 0, + 0, 0, 0, 0, 584, 0, 0, 0, 0, 584, + 583, 584, 584, 584, 584, 584, 584, 584, 584, 584, + 584, 584, 0, 0, 0, 0, 583, 0, 0, 0, + 0, 0, 0, 584, 0, 584, 0, 584, 0, 584, + 584, 584, 0, 0, 0, 0, 0, 0, 0, 584, + 584, 0, 0, 0, 584, 584, 0, 587, 0, 0, + 0, 0, 0, 584, 584, 584, 584, 0, 0, 0, + 0, 0, 586, 0, 0, 0, 0, 586, 584, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 0, 0, 0, 0, 584, 0, 0, 0, 0, 0, + 0, 586, 0, 586, 0, 586, 0, 586, 586, 586, + 0, 0, 0, 0, 0, 0, 0, 586, 586, 0, + 0, 0, 586, 586, 0, 588, 0, 0, 0, 0, + 0, 0, 0, 586, 586, 0, 0, 0, 0, 0, + 587, 0, 0, 0, 0, 587, 586, 587, 587, 587, + 587, 587, 587, 587, 587, 587, 587, 587, 0, 0, + 0, 0, 586, 0, 0, 0, 0, 0, 0, 587, + 0, 587, 0, 587, 0, 587, 587, 587, 0, 0, + 0, 0, 0, 0, 0, 0, 587, 0, 0, 0, + 587, 587, 0, 589, 0, 0, 0, 0, 0, 0, + 0, 587, 587, 0, 0, 0, 0, 0, 588, 0, + 0, 0, 0, 588, 587, 588, 588, 588, 588, 588, + 588, 588, 588, 588, 588, 588, 0, 0, 0, 0, + 587, 0, 0, 0, 0, 0, 0, 588, 0, 588, + 0, 588, 0, 588, 588, 588, 0, 0, 0, 0, + 0, 0, 0, 0, 588, 0, 0, 0, 588, 588, + 0, 590, 0, 0, 0, 0, 0, 0, 0, 588, + 588, 0, 0, 0, 0, 0, 589, 0, 0, 0, + 0, 589, 588, 589, 589, 589, 589, 589, 589, 589, + 589, 589, 589, 589, 0, 0, 0, 0, 588, 0, + 0, 0, 0, 0, 0, 589, 0, 589, 0, 589, + 0, 589, 589, 589, 0, 0, 0, 0, 0, 0, + 0, 0, 589, 0, 0, 0, 0, 589, 0, 591, + 0, 0, 0, 0, 0, 0, 0, 589, 589, 0, + 0, 0, 0, 0, 590, 0, 0, 0, 0, 590, + 589, 590, 590, 590, 590, 590, 590, 590, 590, 590, + 590, 590, 0, 0, 0, 0, 589, 0, 0, 0, + 0, 0, 0, 590, 0, 590, 0, 590, 0, 590, + 590, 590, 0, 0, 0, 0, 0, 0, 0, 0, + 590, 0, 0, 0, 0, 590, 0, 592, 0, 0, + 0, 0, 0, 0, 0, 590, 590, 0, 0, 0, + 0, 0, 591, 0, 0, 0, 0, 591, 590, 591, + 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, + 0, 0, 0, 0, 590, 0, 0, 0, 0, 0, + 0, 591, 0, 591, 0, 591, 0, 591, 591, 591, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 591, 0, 593, 0, 0, 0, 0, + 0, 0, 0, 591, 591, 0, 0, 0, 0, 0, + 592, 0, 0, 0, 0, 592, 591, 592, 592, 592, + 592, 592, 592, 592, 592, 592, 592, 592, 0, 0, + 0, 0, 591, 0, 0, 0, 0, 0, 0, 592, + 0, 592, 0, 592, 0, 592, 592, 592, 0, 0, + 0, 594, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 592, 592, 0, 0, 0, 0, 0, 593, 0, + 0, 0, 0, 593, 592, 593, 593, 593, 593, 593, + 593, 593, 593, 593, 593, 593, 0, 0, 0, 0, + 592, 0, 0, 0, 0, 0, 0, 593, 0, 593, + 0, 593, 0, 593, 593, 593, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 593, + 0, 0, 0, 0, 594, 0, 0, 0, 0, 594, + 593, 594, 594, 594, 594, 594, 594, 594, 594, 594, + 594, 594, 593, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 594, 0, 594, 0, 594, 593, 594, + 594, 594, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 56, 0, 594, 0, 0, 0, 0, + 0, 57, 25, 58, 26, 0, 594, 27, 59, 0, + 60, 61, 28, 62, 63, 64, 29, 0, 594, 0, + 0, 0, 65, 0, 66, 31, 67, 68, 69, 70, + 0, 0, 33, 0, 594, 0, 71, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, + 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, + 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 106, 107, 108, 109, 57, 25, + 58, 26, 0, 0, 27, 59, 0, 60, 61, 28, + 62, 63, 64, 29, 0, 0, 0, 0, 0, 65, + 0, 66, 31, 67, 68, 69, 70, 0, 0, 33, + 0, 0, 0, 71, 34, 0, 72, 73, 35, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, + 37, 0, 38, 75, 0, 0, 39, 0, 76, 77, + 78, 79, 80, 81, 40, 41, 82, 83, 42, 84, + 0, 85, 0, 0, 86, 87, 0, 0, 88, 89, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, + 0, 95, 0, 0, 0, 96, 0, 0, 0, 0, + 97, 98, 99, 100, 101, 0, 0, 0, 102, 0, + 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, + 0, 106, 107, 108, 109, 57, 25, 58, 26, 0, + 0, 27, 59, 0, 60, 61, 28, 62, 63, 64, + 29, 0, 0, 0, 0, 0, 65, 0, 66, 31, + 67, 68, 69, 70, 0, 0, 33, 0, 0, 0, + 71, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 76, 77, 78, 79, 80, + 81, 40, 41, 82, 83, 42, 84, 0, 85, 0, + 0, 86, 87, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 95, 0, + 0, 0, 96, 0, 0, 0, 0, 97, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 928, 0, 0, 0, 106, 107, + 108, 109, 928, 928, 928, 928, 0, 0, 928, 928, + 0, 928, 928, 928, 928, 928, 928, 928, 0, 0, + 0, 0, 0, 928, 0, 928, 928, 928, 928, 928, + 928, 0, 0, 928, 0, 0, 0, 928, 928, 0, + 928, 928, 928, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 928, 0, 928, 0, 928, 928, 0, 0, + 928, 0, 928, 928, 928, 928, 928, 928, 928, 928, + 928, 928, 928, 928, 0, 928, 0, 0, 928, 928, + 0, 0, 928, 928, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 928, 928, 928, + 928, 928, 0, 0, 0, 928, 0, 0, 0, 928, + 0, 0, 0, 0, 928, 928, 928, 928, 928, 0, + 0, 0, 928, 0, 928, 0, 0, 0, 0, 0, + 928, 928, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 792, 0, 0, 0, 928, 928, 928, 928, 792, + 792, 792, 792, 0, 0, 792, 792, 0, 792, 792, + 792, 792, 792, 792, 792, 0, 0, 0, 0, 0, + 792, 0, 792, 792, 792, 792, 792, 792, 0, 0, + 792, 0, 0, 0, 792, 792, 0, 792, 792, 792, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 792, + 0, 792, 0, 792, 792, 0, 0, 792, 0, 792, + 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, + 792, 0, 792, 0, 0, 792, 792, 0, 0, 792, + 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 792, 792, 792, 792, 792, 0, + 0, 0, 792, 0, 0, 0, 792, 0, 0, 0, + 0, 792, 792, 792, 792, 792, 0, 0, 0, 792, + 0, 792, 0, 0, 0, 0, 0, 792, 792, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 725, 0, + 0, 0, 792, 792, 792, 792, 57, 25, 0, 26, + 0, 0, 27, 256, 0, 1018, 0, 28, 62, 63, + 0, 29, 0, 0, 25, 0, 26, 65, 0, 27, + 31, 0, 0, 0, 28, 0, 0, 33, 29, 0, + 0, 0, 34, 0, 72, 73, 35, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 37, 34, + 38, 75, 0, 35, 39, 0, 0, 77, 0, 79, + 0, 81, 40, 41, 257, 37, 42, 38, 0, 0, + 0, 39, 0, 87, 0, 0, 88, 89, 0, 40, + 41, 0, 0, 42, 0, 0, 319, 0, 0, 0, + 0, 90, 91, 92, 93, 94, 0, 0, 0, 509, + 726, 0, 0, 96, 0, 0, 0, 0, 0, 98, + 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, + 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 725, 0, 0, 0, 106, + 301, 108, 109, 57, 25, 0, 26, 0, 0, 27, + 256, 0, 1139, 0, 28, 62, 63, 354, 29, 0, + 0, 25, 0, 26, 65, 0, 27, 31, 0, 0, + 0, 28, 0, 0, 33, 29, 0, 0, 0, 34, + 0, 72, 73, 35, 31, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 37, 34, 38, 75, 906, + 35, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 37, 42, 38, 0, 0, 0, 39, 0, + 87, 0, 0, 88, 89, 0, 40, 41, 0, 0, + 42, 0, 0, 319, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 354, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 712, 975, 0, 0, 96, 0, 0, 0, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 695, 0, 106, 713, 108, 109, 0, 0, 57, 25, + 0, 26, 0, 714, 27, 256, 0, 0, 0, 28, + 62, 63, 0, 29, 0, 0, 187, 0, 187, 65, + 0, 187, 31, 0, 0, 0, 187, 0, 0, 33, + 187, 0, 0, 0, 34, 0, 72, 73, 35, 187, + 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, + 37, 187, 38, 75, 0, 187, 39, 0, 0, 77, + 0, 79, 0, 81, 40, 41, 257, 187, 42, 187, + 0, 85, 0, 187, 0, 87, 0, 0, 88, 89, + 0, 187, 187, 0, 0, 187, 0, 0, 187, 0, + 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, + 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, + 103, 0, 0, 952, 0, 0, 104, 105, 0, 0, + 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, + 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, + 0, 106, 301, 108, 109, 65, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 187, + 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, + 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, + 40, 41, 257, 0, 42, 0, 0, 0, 0, 0, + 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, + 91, 92, 93, 94, 0, 0, 0, 712, 0, 0, + 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, + 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, + 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 725, 0, 106, 713, 108, + 109, 0, 0, 57, 25, 0, 26, 0, 714, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 0, 187, 0, 187, 65, 0, 187, 31, 0, 0, + 0, 187, 0, 0, 33, 187, 0, 0, 0, 34, + 0, 72, 73, 35, 187, 0, 0, 0, 0, 0, + 0, 187, 0, 0, 0, 37, 187, 38, 75, 0, + 187, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 187, 42, 187, 0, 0, 0, 187, 0, + 87, 0, 0, 88, 89, 0, 187, 187, 0, 0, + 187, 0, 0, 187, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 952, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 894, 0, 0, 0, 106, 301, 108, 109, + 57, 25, 0, 26, 0, 0, 27, 256, 0, 0, + 0, 28, 62, 63, 187, 29, 0, 0, 25, 0, + 26, 65, 0, 27, 31, 0, 0, 0, 28, 0, + 0, 33, 29, 0, 0, 0, 34, 0, 72, 73, + 35, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 37, 34, 38, 75, 0, 35, 39, 0, + 0, 77, 0, 79, 0, 81, 40, 41, 257, 37, + 42, 38, 0, 0, 0, 39, 0, 87, 0, 0, + 88, 89, 0, 40, 41, 0, 0, 42, 0, 0, + 319, 0, 0, 0, 0, 90, 91, 92, 93, 94, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, + 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 619, + 0, 0, 0, 106, 301, 108, 109, 619, 619, 0, + 619, 0, 0, 619, 619, 0, 0, 0, 619, 619, + 619, 320, 619, 0, 0, 0, 0, 0, 619, 0, + 0, 619, 0, 0, 0, 0, 0, 0, 619, 0, + 0, 0, 0, 619, 0, 619, 619, 619, 0, 0, + 0, 0, 0, 0, 0, 346, 0, 0, 0, 619, + 0, 619, 619, 0, 0, 619, 0, 0, 619, 0, + 619, 0, 619, 619, 619, 619, 0, 619, 0, 0, + 0, 0, 0, 0, 619, 0, 0, 619, 619, 0, + 0, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 619, 619, 619, 619, 619, 0, 0, 0, + 0, 0, 0, 0, 619, 0, 0, 0, 0, 0, + 619, 619, 619, 619, 0, 0, 0, 619, 0, 619, + 0, 0, 0, 0, 0, 619, 619, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 619, 619, 619, 619, 346, 346, 346, 346, 0, 0, + 0, 346, 346, 0, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 48, 0, + 0, 0, 48, 346, 48, 0, 346, 48, 0, 48, + 48, 0, 48, 0, 48, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, + 0, 48, 0, 0, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, + 48, 0, 0, 0, 0, 0, 0, 48, 48, 0, + 48, 48, 0, 48, 48, 48, 0, 0, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, + 0, 48, 0, 48, 0, 81, 48, 0, 48, 48, + 0, 48, 0, 48, 48, 48, 0, 48, 48, 48, + 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, + 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, + 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 0, 48, 48, 48, 48, 0, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, + 48, 0, 48, 48, 48, 0, 0, 0, 48, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, + 48, 0, 48, 0, 82, 48, 0, 48, 48, 0, + 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, + 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, + 48, 48, 48, 0, 0, 48, 0, 48, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, + 0, 48, 48, 48, 48, 0, 48, 48, 48, 0, + 0, 0, 0, 0, 0, 48, 48, 0, 48, 48, + 0, 48, 48, 48, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 48, 0, 48, 0, 48, + 0, 48, 0, 104, 48, 0, 48, 48, 0, 48, + 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 48, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 0, 0, + 48, 48, 48, 48, 0, 48, 48, 48, 0, 0, + 0, 0, 0, 0, 48, 48, 0, 48, 48, 0, + 48, 48, 48, 0, 0, 0, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, 48, 0, 48, 0, + 48, 0, 105, 48, 0, 48, 48, 0, 48, 0, + 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, + 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, + 48, 0, 0, 48, 0, 48, 0, 48, 0, 0, + 48, 0, 48, 48, 48, 48, 0, 0, 0, 48, + 48, 48, 48, 0, 48, 48, 48, 0, 0, 0, + 0, 0, 0, 48, 48, 0, 48, 48, 0, 48, + 48, 48, 0, 0, 0, 48, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, + 0, 0, 48, 0, 48, 48, 0, 48, 0, 48, + 48, 227, 48, 0, 48, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, + 346, 48, 0, 0, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, + 48, 48, 0, 346, 0, 0, 0, 48, 48, 0, + 48, 48, 447, 48, 48, 48, 346, 0, 0, 48, + 0, 346, 0, 0, 346, 0, 346, 0, 346, 346, + 346, 346, 0, 0, 0, 448, 346, 0, 0, 48, + 346, 0, 0, 0, 346, 228, 0, 0, 449, 0, + 367, 0, 346, 451, 0, 346, 0, 346, 452, 0, + 453, 454, 455, 456, 0, 0, 0, 0, 457, 0, + 0, 0, 458, 367, 0, 0, 346, 0, 0, 0, + 0, 346, 0, 0, 459, 0, 367, 460, 346, 461, + 278, 367, 346, 0, 244, 48, 367, 0, 367, 367, + 367, 367, 0, 0, 0, 346, 367, 0, 0, 0, + 367, 0, 0, 462, 367, 0, 0, 0, 0, 0, + 0, 0, 367, 57, 25, 367, 26, 367, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 346, 29, 0, + 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, + 0, 367, 0, 0, 33, 0, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 582, 0, 0, 0, 1308, + 0, 0, 583, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, + 584, 0, 0, 88, 89, 0, 0, 367, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, + 96, 901, 0, 585, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 469, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 582, 0, 0, 0, 0, 0, 0, 583, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 584, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 585, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 106, 469, 108, 109, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 0, 34, 0, 72, 73, 35, 0, 582, 0, 0, + 0, 0, 0, 0, 583, 0, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, + 0, 0, 584, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 469, + 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 0, 42, 0, 0, 85, 0, 0, 0, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, + 63, 0, 29, 0, 106, 301, 108, 109, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 0, 859, 0, 0, 96, 0, 0, 0, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 106, 301, 108, 109, 65, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, + 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 503, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 106, 301, 108, 109, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, + 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 301, + 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 0, 42, 0, 0, 0, 0, 0, 0, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, + 63, 0, 29, 0, 106, 469, 108, 109, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 78, 78, 0, 78, 0, 0, 78, + 78, 0, 0, 0, 78, 78, 78, 0, 78, 0, + 106, 1010, 108, 109, 78, 0, 0, 78, 0, 0, + 0, 0, 0, 0, 78, 0, 0, 0, 0, 78, + 0, 78, 78, 78, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 0, 78, 78, 0, + 0, 78, 0, 0, 78, 0, 78, 0, 78, 78, + 78, 78, 0, 78, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 78, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, + 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 0, 0, 0, 78, 78, 78, 78, + 0, 0, 0, 78, 0, 78, 0, 0, 0, 0, + 0, 78, 78, 0, 0, 0, 0, 0, 0, 150, + 150, 0, 150, 0, 0, 150, 150, 0, 0, 0, + 150, 150, 150, 0, 150, 0, 78, 78, 78, 78, + 150, 0, 0, 150, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 150, 0, 150, 150, 150, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 150, 150, 0, 0, 150, 0, 0, + 150, 0, 150, 0, 150, 150, 150, 150, 0, 150, + 0, 0, 0, 0, 0, 0, 150, 0, 0, 150, + 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 150, 150, 150, 150, 0, + 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, + 0, 0, 150, 150, 150, 150, 0, 0, 0, 150, + 0, 150, 0, 0, 0, 0, 0, 150, 150, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 150, 150, 150, 150, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 28, 0, + 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, + 75, 28, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 28, 42, 0, 0, 0, 28, + 0, 0, 0, 0, 28, 0, 28, 28, 28, 28, + 0, 0, 28, 0, 28, 0, 0, 0, 28, 0, + 90, 91, 92, 258, 94, 0, 0, 0, 0, 0, + 28, 0, 96, 28, 0, 28, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 57, + 25, 0, 26, 104, 105, 27, 256, 0, 0, 28, + 28, 62, 63, 0, 29, 28, 28, 0, 0, 0, + 65, 0, 0, 31, 0, 0, 0, 48, 106, 259, + 33, 109, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 48, 81, 40, 41, 257, 48, 42, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 0, 48, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 258, 94, 48, + 0, 0, 48, 0, 48, 0, 96, 652, 0, 652, + 0, 652, 98, 0, 652, 101, 652, 652, 0, 652, + 0, 652, 0, 652, 0, 652, 652, 652, 48, 0, + 0, 652, 652, 0, 311, 0, 0, 652, 0, 652, + 652, 0, 0, 0, 652, 0, 0, 0, 652, 0, + 0, 0, 106, 259, 0, 109, 0, 0, 0, 652, + 652, 0, 652, 0, 0, 0, 652, 652, 0, 0, + 0, 0, 0, 0, 652, 652, 57, 25, 652, 26, + 0, 652, 27, 256, 0, 0, 652, 28, 62, 63, + 0, 29, 0, 0, 0, 0, 0, 65, 0, 0, + 31, 0, 0, 0, 0, 0, 0, 33, 652, 652, + 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, + 0, 652, 0, 0, 0, 0, 0, 0, 37, 0, + 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, + 0, 81, 40, 41, 257, 0, 42, 0, 0, 85, + 0, 0, 0, 0, 0, 0, 25, 0, 26, 0, + 0, 27, 652, 1190, 0, 0, 28, 0, 0, 0, + 29, 90, 91, 92, 258, 0, 0, 0, 0, 31, + 651, 0, 651, 96, 0, 651, 33, 651, 651, 0, + 651, 34, 651, 1191, 651, 35, 651, 651, 651, 0, + 0, 0, 651, 651, 0, 0, 0, 37, 651, 38, + 651, 651, 0, 39, 1192, 651, 0, 0, 0, 651, + 0, 40, 41, 0, 0, 42, 0, 0, 319, 106, + 259, 651, 0, 651, 0, 0, 0, 651, 651, 0, + 0, 0, 0, 0, 0, 651, 651, 0, 651, 651, + 651, 0, 651, 651, 0, 651, 651, 651, 651, 0, + 651, 0, 651, 0, 651, 651, 651, 0, 0, 0, + 651, 651, 0, 0, 0, 0, 651, 0, 651, 651, + 0, 0, 0, 651, 0, 0, 0, 651, 0, 0, + 0, 0, 651, 0, 0, 0, 0, 0, 0, 651, + 0, 651, 0, 0, 0, 651, 651, 0, 0, 354, + 0, 0, 0, 651, 651, 0, 0, 651, 0, 0, + 651, 0, 25, 0, 26, 651, 0, 27, 0, 0, + 1263, 0, 28, 651, 671, 0, 29, 0, 672, 1264, + 1265, 0, 0, 0, 1266, 31, 0, 0, 0, 0, + 1267, 0, 33, 0, 25, 0, 26, 34, 0, 27, + 0, 35, 1263, 0, 28, 0, 671, 0, 29, 0, + 672, 1264, 1265, 37, 0, 38, 1266, 31, 0, 39, + 0, 0, 1267, 0, 33, 0, 0, 40, 41, 34, + 0, 42, 0, 35, 1268, 0, 0, 0, 48, 1269, + 48, 651, 0, 48, 0, 37, 0, 38, 48, 0, + 0, 39, 48, 0, 0, 0, 0, 0, 0, 40, + 41, 48, 0, 42, 0, 0, 1268, 0, 48, 0, + 48, 1269, 48, 48, 1270, 48, 0, 48, 0, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 0, 48, + 0, 48, 0, 48, 0, 48, 0, 0, 48, 0, + 48, 0, 0, 48, 48, 48, 0, 48, 0, 48, + 48, 48, 0, 48, 48, 1271, 48, 0, 48, 48, + 0, 48, 0, 48, 48, 0, 0, 48, 48, 0, + 48, 0, 0, 0, 0, 48, 48, 48, 0, 48, + 0, 0, 48, 0, 48, 168, 25, 1271, 26, 48, + 0, 27, 0, 48, 0, 48, 28, 48, 0, 0, + 29, 0, 48, 0, 0, 48, 0, 48, 0, 31, + 0, 48, 0, 0, 48, 168, 33, 0, 0, 48, + 48, 34, 0, 48, 0, 35, 48, 563, 0, 0, + 0, 48, 0, 0, 564, 0, 0, 37, 0, 38, + 0, 0, 0, 39, 0, 0, 565, 0, 0, 0, + 0, 40, 41, 0, 0, 42, 0, 25, 566, 26, + 0, 0, 27, 48, 0, 0, 0, 28, 0, 0, + 0, 29, 0, 0, 0, 30, 25, 0, 26, 0, + 31, 27, 0, 0, 0, 32, 28, 33, 0, 0, + 29, 0, 34, 0, 0, 0, 35, 36, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 48, 37, 0, + 38, 34, 0, 0, 39, 35, 0, 0, 0, 0, + 0, 0, 40, 41, 0, 0, 42, 37, 0, 38, + 25, 0, 26, 39, 0, 27, 0, 0, 0, 567, + 28, 40, 41, 0, 29, 42, 0, 25, 319, 26, + 0, 0, 27, 31, 0, 0, 0, 28, 0, 0, + 33, 29, 0, 0, 0, 34, 0, 0, 0, 35, + 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 37, 34, 38, 0, 0, 35, 39, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 0, 37, 42, + 38, 25, 319, 26, 39, 0, 27, 0, 0, 0, + 43, 28, 40, 41, 0, 29, 42, 0, 0, 511, + 0, 0, 0, 0, 31, 25, 0, 26, 0, 326, + 27, 33, 0, 0, 0, 28, 34, 0, 0, 29, + 35, 0, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 37, 0, 38, 33, 0, 0, 39, 0, + 34, 0, 0, 0, 35, 0, 40, 41, 0, 0, + 42, 0, 0, 319, 0, 25, 37, 26, 38, 0, + 27, 0, 39, 354, 0, 28, 0, 0, 0, 29, + 40, 41, 0, 0, 42, 0, 0, 319, 31, 25, + 354, 26, 0, 0, 27, 33, 0, 0, 0, 28, + 34, 0, 0, 29, 35, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 0, 37, 0, 38, 33, + 0, 0, 39, 0, 34, 0, 0, 0, 35, 0, + 40, 41, 0, 0, 42, 0, 0, 566, 0, 0, + 37, 0, 38, 498, 630, 498, 39, 0, 498, 0, + 0, 0, 0, 498, 40, 41, 0, 498, 42, 0, + 188, 739, 188, 0, 0, 188, 498, 0, 632, 0, + 188, 0, 0, 498, 188, 0, 0, 0, 498, 0, + 0, 0, 498, 188, 0, 0, 0, 0, 0, 0, + 188, 0, 0, 0, 498, 188, 498, 0, 0, 188, + 498, 0, 0, 0, 0, 0, 0, 0, 498, 498, + 0, 188, 498, 188, 187, 498, 187, 188, 354, 187, + 0, 0, 0, 0, 187, 188, 188, 0, 187, 188, + 0, 0, 188, 0, 0, 0, 0, 187, 197, 0, + 197, 0, 354, 197, 187, 0, 0, 0, 197, 187, + 0, 0, 197, 187, 0, 0, 0, 0, 0, 0, + 0, 197, 0, 0, 0, 187, 0, 187, 197, 0, + 0, 187, 0, 197, 0, 0, 0, 197, 0, 187, + 187, 0, 35, 187, 0, 0, 187, 0, 0, 197, + 0, 197, 0, 35, 0, 197, 498, 0, 35, 0, + 0, 0, 35, 197, 197, 35, 0, 197, 0, 0, + 197, 0, 0, 188, 0, 0, 0, 35, 35, 0, + 0, 0, 35, 35, 0, 33, 0, 0, 35, 0, + 35, 35, 35, 35, 0, 0, 33, 0, 35, 0, + 0, 33, 35, 0, 35, 33, 0, 0, 33, 0, + 0, 0, 0, 0, 35, 0, 35, 35, 0, 35, + 33, 33, 0, 35, 0, 33, 33, 187, 0, 0, + 0, 33, 0, 33, 33, 33, 33, 0, 0, 0, + 0, 33, 0, 35, 0, 33, 0, 33, 0, 35, + 35, 197, 0, 28, 0, 28, 0, 33, 0, 0, + 33, 0, 33, 0, 0, 0, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 28, + 0, 0, 33, 33, 28, 0, 48, 0, 0, 28, + 0, 28, 28, 28, 28, 0, 0, 48, 0, 28, + 0, 0, 48, 28, 0, 0, 48, 0, 0, 48, + 0, 0, 0, 0, 0, 28, 0, 0, 28, 0, + 28, 48, 48, 0, 0, 0, 48, 48, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, + 48, 0, 48, 0, 28, 48, 48, 0, 48, 48, + 28, 28, 48, 0, 0, 0, 0, 0, 48, 0, + 0, 48, 0, 48, 48, 48, 0, 48, 0, 48, + 48, 48, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 0, 48, + 0, 48, 0, 37, 48, 0, 0, 0, 0, 0, + 0, 48, 0, 0, 48, 0, 48, 48, 0, 48, + 48, 0, 48, 0, 0, 0, 0, 48, 0, 48, + 48, 48, 48, 0, 0, 0, 0, 48, 0, 0, + 48, 48, 48, 0, 0, 0, 38, 0, 0, 0, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 0, 0, 48, + 48, 0, 48, 0, 48, 48, 0, 0, 209, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 48, 0, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 0, 0, 48, 0, 0, 0, 48, 48, 0, + 48, 0, 48, 48, 0, 447, 211, 0, 0, 48, + 0, 48, 48, 0, 48, 0, 48, 0, 0, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 448, 0, + 0, 48, 0, 0, 0, 48, 0, 0, 48, 0, + 0, 449, 0, 0, 312, 450, 451, 48, 447, 0, + 48, 452, 48, 453, 454, 455, 456, 0, 0, 0, + 0, 457, 0, 0, 0, 458, 0, 0, 0, 0, + 0, 448, 0, 0, 0, 0, 48, 459, 48, 48, + 460, 0, 461, 0, 449, 0, 0, 0, 0, 451, + 0, 0, 0, 0, 452, 0, 453, 454, 455, 456, + 0, 0, 0, 0, 457, 0, 462, 0, 458, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 459, 0, 0, 460, 0, 461, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, + }; + protected static readonly short [] yyCheck = { 17, + 17, 4, 507, 17, 20, 299, 6, 18, 300, 52, + 235, 191, 353, 20, 291, 107, 509, 464, 85, 250, + 190, 60, 549, 298, 159, 483, 296, 335, 17, 328, + 318, 353, 559, 48, 60, 730, 1076, 705, 706, 1113, + 1114, 0, 906, 237, 0, 59, 113, 569, 115, 324, + 759, 78, 256, 113, 256, 115, 74, 256, 256, 256, + 78, 256, 1181, 256, 268, 1197, 80, 256, 82, 256, + 256, 256, 88, 89, 256, 325, 268, 368, 96, 368, + 748, 1213, 750, 282, 17, 1159, 368, 374, 294, 268, + 376, 256, 268, 109, 339, 1285, 357, 335, 256, 306, + 276, 391, 17, 21, 367, 1224, 313, 1226, 1298, 1226, + 368, 367, 373, 376, 277, 314, 374, 17, 325, 257, + 376, 17, 367, 381, 414, 386, 1316, 418, 650, 416, + 17, 376, 407, 17, 365, 53, 1071, 1256, 17, 1256, + 429, 159, 159, 429, 339, 159, 294, 429, 191, 344, + 256, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 266, 17, 17, 17, 17, 259, 418, 256, + 159, 294, 370, 368, 372, 370, 374, 372, 256, 374, + 375, 376, 523, 306, 370, 391, 202, 203, 374, 368, + 256, 429, 235, 62, 381, 390, 381, 66, 67, 68, + 358, 70, 71, 428, 503, 546, 75, 76, 414, 301, + 314, 226, 506, 82, 707, 84, 418, 86, 422, 418, + 418, 418, 91, 92, 546, 418, 159, 0, 569, 418, + 422, 231, 250, 339, 429, 429, 418, 255, 344, 343, + 346, 549, 418, 422, 159, 114, 352, 353, 264, 288, + 317, 559, 1384, 418, 321, 418, 419, 296, 325, 159, + 88, 89, 288, 159, 356, 325, 424, 425, 426, 427, + 418, 375, 159, 291, 290, 159, 294, 295, 325, 1411, + 159, 109, 369, 264, 300, 994, 256, 391, 314, 307, + 306, 1423, 294, 1425, 312, 418, 314, 375, 257, 313, + 318, 257, 970, 369, 256, 159, 159, 159, 159, 650, + 414, 329, 330, 256, 1009, 372, 272, 256, 335, 346, + 842, 277, 256, 429, 428, 281, 256, 262, 346, 651, + 671, 1158, 256, 418, 350, 372, 372, 353, 1378, 358, + 296, 371, 434, 428, 325, 1054, 335, 365, 366, 1176, + 256, 372, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 298, 256, 256, 882, 323, 384, 385, + 1444, 418, 429, 294, 202, 203, 468, 469, 335, 256, + 873, 349, 350, 1318, 402, 428, 342, 963, 257, 391, + 420, 260, 429, 429, 852, 438, 412, 413, 368, 1473, + 1227, 493, 1266, 305, 374, 693, 294, 341, 429, 339, + 1345, 1346, 414, 1348, 430, 991, 368, 1413, 1414, 1087, + 435, 436, 374, 430, 1359, 256, 441, 1362, 444, 298, + 369, 374, 368, 339, 775, 369, 264, 444, 344, 709, + 346, 310, 1377, 378, 379, 369, 352, 353, 679, 376, + 1277, 1119, 1120, 775, 1281, 369, 6, 483, 1126, 373, + 1036, 429, 290, 371, 478, 373, 1401, 17, 341, 962, + 391, 256, 988, 1469, 990, 367, 367, 369, 306, 371, + 256, 263, 418, 256, 576, 376, 578, 505, 580, 507, + 367, 509, 369, 414, 371, 372, 369, 374, 372, 376, + 374, 842, 429, 391, 257, 519, 520, 523, 339, 423, + 60, 277, 368, 531, 64, 281, 523, 349, 350, 841, + 538, 418, 350, 429, 349, 350, 414, 305, 420, 305, + 546, 423, 549, 315, 17, 269, 367, 401, 88, 89, + 861, 418, 559, 420, 558, 839, 423, 263, 256, 413, + 642, 872, 286, 569, 339, 429, 384, 385, 368, 109, + 549, 792, 1181, 851, 582, 583, 339, 866, 368, 368, + 559, 256, 373, 429, 369, 376, 342, 60, 343, 1037, + 343, 64, 367, 718, 412, 413, 98, 99, 100, 101, + 102, 103, 104, 105, 367, 870, 1123, 429, 371, 315, + 373, 374, 375, 376, 429, 1224, 343, 1226, 381, 159, + 479, 629, 375, 256, 906, 374, 381, 635, 381, 429, + 305, 713, 372, 418, 374, 372, 391, 369, 391, 429, + 429, 339, 272, 376, 650, 272, 344, 1256, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 414, + 519, 414, 202, 203, 391, 671, 296, 416, 357, 296, + 368, 679, 370, 428, 372, 428, 374, 375, 376, 376, + 709, 418, 672, 272, 741, 693, 159, 414, 277, 429, + 418, 369, 281, 323, 702, 979, 323, 386, 414, 707, + 428, 428, 1181, 376, 712, 370, 339, 296, 371, 374, + 931, 344, 428, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 264, 386, 256, 367, 734, 367, + 1181, 429, 736, 371, 323, 368, 376, 370, 272, 372, + 418, 374, 375, 376, 752, 1224, 754, 1226, 288, 755, + 290, 384, 385, 342, 758, 759, 389, 390, 1180, 1181, + 300, 769, 296, 1181, 367, 771, 306, 400, 401, 775, + 371, 343, 414, 1224, 314, 1226, 1043, 1256, 1200, 787, + 413, 256, 420, 816, 792, 793, 428, 795, 367, 323, + 418, 381, 1076, 1091, 269, 335, 429, 376, 806, 807, + 882, 391, 1224, 375, 1226, 1256, 1224, 381, 1226, 339, + 350, 286, 1079, 353, 344, 288, 346, 391, 824, 391, + 294, 367, 352, 353, 414, 1123, 328, 824, 391, 837, + 376, 839, 306, 1181, 1256, 379, 842, 843, 1256, 829, + 414, 314, 414, 851, 384, 385, 854, 1007, 1069, 384, + 1117, 414, 369, 861, 428, 1153, 428, 306, 421, 369, + 389, 1298, 335, 871, 313, 873, 367, 369, 367, 386, + 387, 381, 412, 413, 385, 376, 1224, 376, 1226, 381, + 382, 383, 1181, 1366, 386, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 906, 394, 395, 357, 1235, 913, 988, 915, 1256, 917, + 261, 1242, 391, 357, 400, 369, 734, 1132, 372, 373, + 374, 1188, 928, 931, 371, 1224, 373, 1226, 1010, 373, + 936, 928, 386, 284, 374, 414, 376, 755, 1108, 357, + 370, 381, 386, 483, 374, 1428, 297, 390, 938, 428, + 940, 302, 942, 771, 962, 373, 307, 1256, 309, 310, + 311, 312, 339, 367, 418, 369, 317, 344, 386, 346, + 321, 1181, 349, 350, 325, 352, 353, 373, 369, 414, + 376, 1464, 333, 523, 1266, 336, 421, 338, 373, 339, + 994, 1486, 1487, 1001, 344, 1003, 346, 1005, 418, 349, + 350, 503, 352, 353, 398, 399, 546, 382, 383, 549, + 483, 362, 376, 372, 1224, 374, 1226, 376, 372, 559, + 374, 396, 397, 1016, 374, 843, 306, 339, 308, 569, + 354, 355, 344, 313, 346, 1043, 369, 349, 350, 372, + 352, 353, 418, 370, 371, 325, 1256, 374, 1056, 1057, + 1054, 372, 429, 374, 371, 376, 1064, 415, 357, 370, + 370, 1069, 374, 374, 374, 354, 355, 418, 1076, 1070, + 369, 1079, 574, 418, 373, 1108, 549, 1110, 339, 429, + 386, 387, 388, 344, 1091, 346, 559, 386, 349, 350, + 1098, 352, 353, 339, 1378, 256, 60, 1105, 344, 1132, + 346, 414, 415, 349, 350, 1111, 352, 353, 368, 1117, + 650, 371, 1091, 373, 374, 418, 1123, 429, 936, 418, + 277, 1129, 1130, 370, 371, 418, 373, 374, 375, 1162, + 94, 671, 392, 393, 98, 99, 100, 101, 102, 103, + 104, 105, 376, 372, 1123, 374, 1153, 1180, 1181, 370, + 340, 372, 412, 374, 370, 367, 372, 1163, 374, 0, + 420, 376, 1170, 423, 373, 705, 706, 1200, 429, 374, + 357, 376, 370, 1179, 1153, 371, 374, 373, 1186, 370, + 1188, 372, 369, 429, 370, 372, 373, 370, 374, 372, + 374, 1224, 376, 1226, 734, 368, 392, 393, 371, 386, + 373, 374, 372, 370, 339, 372, 376, 376, 748, 344, + 750, 346, 370, 1295, 372, 755, 412, 352, 353, 392, + 393, 364, 365, 1256, 420, 376, 1308, 423, 1234, 1235, + 418, 771, 705, 706, 1238, 775, 1242, 418, 372, 412, + 374, 372, 367, 1325, 343, 1327, 371, 420, 373, 374, + 423, 376, 372, 256, 374, 376, 381, 1263, 1264, 370, + 1266, 372, 414, 370, 367, 372, 1272, 372, 371, 418, + 373, 374, 374, 376, 376, 748, 418, 750, 381, 1285, + 418, 1287, 367, 374, 1290, 376, 371, 369, 373, 374, + 415, 376, 1298, 374, 418, 376, 381, 349, 350, 1303, + 285, 372, 842, 843, 390, 391, 392, 393, 418, 374, + 1316, 376, 415, 372, 373, 364, 365, 1074, 1075, 388, + 389, 394, 395, 1356, 288, 376, 372, 372, 368, 372, + 374, 372, 296, 372, 372, 418, 339, 372, 294, 294, + 1373, 344, 327, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 1386, 1387, 374, 372, 372, 1366, 376, + 1364, 1179, 418, 374, 866, 368, 906, 370, 372, 372, + 1378, 374, 375, 376, 371, 256, 374, 356, 372, 375, + 1413, 1414, 418, 374, 418, 375, 381, 1395, 374, 373, + 418, 372, 377, 378, 379, 380, 936, 382, 383, 384, + 385, 386, 387, 388, 389, 369, 381, 392, 393, 394, + 395, 396, 397, 398, 399, 256, 1234, 381, 382, 383, + 1428, 262, 386, 387, 374, 374, 429, 374, 376, 418, + 970, 0, 374, 294, 372, 423, 1469, 429, 374, 367, + 418, 372, 418, 373, 343, 1263, 1264, 372, 374, 294, + 294, 374, 418, 294, 370, 418, 1464, 298, 371, 381, + 418, 367, 256, 375, 256, 374, 1470, 1471, 256, 1287, + 256, 372, 1290, 1477, 1478, 372, 381, 280, 1486, 1487, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 256, 367, 372, 368, 418, 343, 374, 970, 339, 418, + 418, 418, 376, 344, 370, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 371, 376, 418, 376, + 374, 372, 372, 376, 370, 421, 367, 368, 423, 370, + 371, 372, 381, 374, 375, 376, 347, 378, 379, 351, + 367, 382, 383, 384, 385, 381, 381, 1087, 389, 390, + 256, 1091, 256, 394, 395, 396, 397, 398, 399, 400, + 401, 368, 372, 372, 347, 370, 374, 367, 370, 375, + 348, 1111, 413, 372, 375, 416, 372, 418, 368, 1119, + 1120, 370, 339, 1123, 418, 418, 1126, 374, 429, 256, + 374, 376, 348, 368, 375, 367, 367, 367, 265, 0, + 267, 368, 381, 270, 356, 418, 371, 376, 275, 368, + 574, 374, 279, 1153, 1087, 368, 337, 372, 1091, 368, + 305, 288, 376, 1163, 371, 418, 371, 418, 295, 369, + 367, 381, 371, 300, 367, 371, 418, 304, 418, 1179, + 371, 418, 371, 373, 371, 369, 1119, 1120, 371, 316, + 1123, 318, 372, 1126, 372, 322, 381, 374, 373, 373, + 261, 374, 263, 330, 331, 374, 256, 334, 376, 374, + 337, 372, 418, 372, 370, 418, 376, 418, 376, 372, + 1153, 376, 372, 284, 418, 367, 372, 256, 368, 381, + 381, 370, 261, 262, 1234, 1235, 297, 372, 368, 315, + 263, 302, 1242, 371, 368, 371, 307, 372, 309, 310, + 311, 312, 372, 0, 315, 284, 317, 0, 367, 376, + 321, 418, 376, 1263, 1264, 294, 1266, 368, 297, 298, + 372, 0, 333, 302, 368, 336, 305, 338, 307, 376, + 309, 310, 311, 312, 372, 709, 372, 1287, 317, 418, + 1290, 418, 321, 370, 367, 376, 325, 368, 368, 367, + 372, 362, 376, 370, 333, 418, 0, 336, 418, 338, + 339, 376, 376, 368, 372, 344, 376, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 372, 368, + 372, 368, 372, 362, 367, 376, 368, 368, 367, 368, + 367, 370, 371, 372, 373, 374, 375, 376, 373, 378, + 379, 315, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, 376, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 376, 376, 416, 376, 418, + 376, 420, 376, 376, 423, 256, 257, 376, 263, 51, + 429, 52, 12, 264, 265, 266, 267, 268, 5, 270, + 271, 928, 273, 274, 275, 276, 277, 278, 279, 280, + 824, 1200, 1256, 1381, 285, 1418, 287, 288, 289, 290, + 291, 292, 1069, 1069, 295, 0, 1434, 671, 299, 300, + 1369, 302, 303, 304, 1398, 1364, 1272, 1285, 845, 685, + 845, 845, 841, 314, 1478, 316, 1224, 318, 319, 1472, + 1304, 322, 1212, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 1391, 337, 1387, 1386, 340, + 341, 1327, 1162, 344, 345, 1471, 1272, 816, 523, 1163, + 712, 866, 792, 583, 365, 787, 979, 679, 359, 360, + 361, 362, 363, 72, 331, 709, 367, 368, 94, 396, + 371, 397, 400, 398, 1146, 376, 377, 378, 379, 380, + 399, 401, 546, 384, 1234, 386, 159, 1153, 949, 1057, + 1091, 392, 393, 964, 1048, 1037, 1046, 911, 886, 521, + 1230, 1130, 775, 420, 822, 821, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 417, 418, 419, 420, + -1, 422, 256, 257, -1, -1, -1, -1, 429, -1, + 264, 265, 266, 267, 268, -1, 270, 271, -1, 273, + 274, 275, 276, 277, 278, 279, -1, -1, 0, -1, + -1, 285, -1, 287, 288, 289, 290, 291, 292, -1, + -1, 295, -1, -1, -1, 299, 300, -1, 302, 303, + 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 314, -1, 316, -1, 318, 319, -1, -1, 322, -1, + 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, -1, -1, 340, 341, -1, -1, + 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, + -1, -1, -1, 367, 368, -1, -1, 371, -1, -1, + -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, + 384, 256, 386, -1, -1, -1, 261, 262, 392, 393, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 284, + -1, -1, -1, 417, 418, 419, 420, -1, 422, 294, + -1, -1, 297, 298, -1, 429, -1, 302, -1, -1, + 305, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, -1, -1, 321, -1, -1, -1, + 325, -1, -1, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, -1, -1, -1, -1, 362, -1, -1, + -1, -1, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, + 385, 386, -1, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, -1, -1, 256, -1, -1, -1, 413, 261, + 262, 416, -1, 418, -1, 420, -1, -1, 423, -1, + -1, -1, -1, -1, 429, 0, -1, -1, -1, -1, + -1, -1, 284, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 294, -1, -1, 297, 298, -1, -1, -1, + 302, -1, -1, 305, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, -1, -1, 325, -1, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + 362, -1, -1, -1, -1, 367, 368, 369, 370, 371, + 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, + 382, 383, 384, 385, 256, -1, -1, 389, 390, 261, + 262, -1, 394, 395, 396, 397, 398, 399, 400, 401, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 413, 284, -1, 416, -1, 418, -1, 420, -1, + -1, 423, 294, -1, -1, 297, 298, 429, -1, -1, + 302, -1, -1, 305, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, -1, -1, 325, -1, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + 362, -1, -1, -1, -1, 367, 368, 369, 370, 371, + 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, + 382, 383, 384, 385, -1, -1, -1, 389, 390, -1, + -1, -1, 394, 395, 396, 397, 398, 399, 400, 401, + -1, 256, -1, -1, -1, -1, 261, 262, -1, -1, + -1, 413, -1, -1, 416, -1, 418, -1, 420, -1, + -1, 423, -1, -1, -1, -1, -1, 429, -1, 284, + -1, -1, -1, -1, -1, 0, -1, -1, -1, 294, + -1, -1, 297, 298, -1, -1, -1, 302, -1, -1, + 305, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, -1, -1, 321, -1, -1, -1, + 325, -1, -1, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, -1, 362, -1, -1, + -1, -1, 367, 368, -1, 370, 371, 372, -1, 374, + 375, 376, -1, 378, 379, -1, 256, 382, 383, 384, + 385, -1, 262, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 413, -1, + -1, 416, -1, 418, 294, -1, -1, -1, 298, -1, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, + -1, 0, -1, -1, 344, -1, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, -1, 378, 379, + -1, -1, 382, 383, 384, 385, 386, -1, -1, 389, + 390, -1, -1, -1, 394, 395, 396, 397, 398, 399, + 400, 401, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, 413, -1, -1, 416, -1, 418, -1, + 420, -1, 257, 423, -1, -1, 261, -1, 263, 429, + 265, -1, 267, -1, -1, 270, -1, 272, 273, -1, + 275, -1, 277, -1, 279, -1, 281, 282, 283, 284, + -1, -1, 287, 288, -1, -1, -1, 0, 293, 294, + 295, 296, 297, -1, -1, 300, 301, 302, -1, 304, + -1, 306, 307, 308, 309, 310, 311, 312, 313, -1, + 315, 316, 317, 318, -1, -1, 321, 322, 323, -1, + 325, -1, -1, -1, -1, 330, 331, -1, 333, 334, + -1, 336, 337, 338, -1, -1, -1, 342, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, 362, -1, 364, + 365, -1, -1, -1, 256, 257, -1, -1, -1, 261, + -1, -1, 377, 265, -1, 267, -1, -1, 270, -1, + 272, 273, -1, 275, -1, 277, -1, 279, -1, 281, + 282, 283, 284, 0, -1, 287, 288, -1, -1, -1, + -1, 293, -1, 295, 296, 297, -1, -1, 300, 301, + 302, -1, 304, 418, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, 316, 317, 318, -1, 257, 321, + 322, 323, 261, -1, -1, -1, 0, -1, 330, 331, + -1, 333, 334, 272, 336, 337, 338, -1, 277, -1, + 342, -1, 281, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 296, 297, -1, + 362, -1, 301, 302, -1, -1, 368, 369, 307, 0, + 309, 310, 311, 312, -1, 377, -1, -1, 317, -1, + -1, -1, 321, -1, 323, -1, -1, 257, -1, -1, + -1, 261, -1, -1, 333, -1, 335, 336, -1, 338, + -1, -1, 272, 342, -1, -1, -1, 277, -1, -1, + -1, 281, 0, -1, 284, -1, 418, -1, -1, -1, + -1, -1, -1, 362, -1, -1, 296, 297, -1, 368, + 369, 301, 302, -1, 257, -1, -1, 307, 261, 309, + 310, 311, 312, -1, -1, -1, -1, 317, -1, 272, + -1, 321, -1, 323, 277, 0, -1, -1, 281, -1, + -1, 284, -1, 333, -1, 335, 336, -1, 338, -1, + -1, -1, 342, 296, 297, -1, -1, -1, 301, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, 362, -1, 317, -1, -1, 257, 321, 369, + 323, 261, -1, -1, -1, -1, -1, -1, -1, -1, + 333, -1, 272, 336, -1, 338, -1, 277, 0, 342, + -1, 281, -1, -1, 284, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 296, 297, -1, 362, + 257, 301, 302, -1, 261, 368, 369, 307, -1, 309, + 310, 311, 312, -1, -1, 272, -1, 317, -1, -1, + 277, 321, -1, 323, 281, -1, -1, 284, -1, -1, + -1, -1, -1, 333, -1, -1, 336, -1, 338, 296, + 297, -1, 342, 257, 301, 302, -1, 261, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, 272, -1, + 317, -1, 362, 277, 321, -1, 323, 281, 368, 369, + 284, -1, -1, -1, -1, -1, 333, -1, -1, 336, + -1, 338, 296, 297, -1, 342, 257, 301, 302, -1, + 261, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, 272, -1, 317, -1, 362, 277, 321, -1, 323, + 281, -1, 369, 284, -1, -1, -1, -1, -1, 333, + -1, -1, 336, -1, 338, 296, 297, -1, 342, 257, + 301, 302, -1, 261, -1, -1, 307, -1, 309, 310, + 311, 312, -1, -1, 272, -1, 317, -1, 362, 277, + 321, -1, 323, 281, -1, -1, 284, -1, -1, -1, + -1, -1, 333, -1, -1, 336, -1, 338, 296, 297, + -1, 342, 257, 301, 302, -1, 261, -1, -1, 307, + -1, 309, 310, 311, 312, -1, -1, 272, -1, 317, + -1, 362, 277, 321, -1, 323, 281, -1, -1, 284, + -1, -1, -1, -1, -1, 333, -1, -1, 336, -1, + 338, 296, 297, -1, 342, -1, 301, 302, -1, -1, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, 362, 257, 321, -1, 323, 261, + -1, -1, -1, -1, -1, -1, -1, -1, 333, -1, + 272, 336, -1, 338, -1, 277, -1, 342, -1, 281, + -1, -1, 284, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 296, 297, -1, 362, -1, 301, + 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, 323, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, -1, 256, 336, -1, 338, -1, -1, -1, + 342, 264, 265, 266, 267, -1, -1, 270, 271, -1, + 273, 274, 275, 276, 277, 278, 279, -1, -1, -1, + 362, -1, 285, -1, 287, 288, 289, 290, 291, 292, + -1, -1, 295, -1, -1, -1, 299, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, + -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, -1, -1, 340, 341, -1, + 256, 344, 345, -1, -1, -1, 262, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, + -1, 384, 298, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, + -1, -1, 262, -1, 417, 418, 419, 420, -1, -1, + -1, -1, -1, 339, -1, -1, 429, -1, 344, -1, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, -1, -1, -1, -1, -1, -1, 298, -1, + -1, -1, 368, 369, 370, 371, 372, 373, 374, 375, + 376, -1, 378, 379, -1, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, -1, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, -1, 256, + -1, -1, 418, -1, 420, 262, -1, 423, -1, -1, + -1, -1, -1, 429, -1, -1, -1, -1, 368, -1, + -1, 371, -1, 373, 374, -1, -1, -1, 378, 379, + -1, -1, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 298, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 412, 413, -1, -1, -1, -1, -1, -1, + 420, 262, -1, 423, -1, -1, -1, -1, -1, 429, + -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + -1, 378, 379, -1, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 256, -1, + -1, -1, -1, 420, 262, -1, 357, -1, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, 369, -1, + 371, -1, 373, -1, -1, 376, -1, 378, 379, -1, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 298, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, -1, -1, -1, -1, 418, -1, 420, + 262, -1, 423, -1, -1, -1, -1, -1, 429, -1, + -1, 339, -1, -1, -1, -1, 344, -1, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, + -1, -1, -1, -1, -1, -1, 298, -1, -1, 367, + 368, -1, 370, 371, 372, 373, 374, 375, 376, -1, + 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, + 388, 389, 390, -1, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, -1, 256, -1, -1, + -1, -1, 420, 262, -1, 423, -1, -1, -1, -1, + -1, 429, -1, -1, -1, -1, -1, 369, -1, 371, + 372, 373, 374, -1, 376, -1, 378, 379, -1, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 298, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, -1, -1, -1, 418, -1, 420, 262, + -1, 423, -1, -1, -1, -1, -1, 429, -1, -1, + 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, -1, -1, -1, 298, -1, -1, -1, 368, + -1, 370, 371, 372, 373, 374, 375, 376, -1, 378, + 379, -1, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, -1, 256, -1, -1, -1, + -1, 420, 262, -1, 423, -1, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 370, 371, 372, + 373, 374, -1, -1, -1, 378, 379, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 298, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, -1, -1, -1, -1, -1, -1, 420, -1, -1, + 423, -1, -1, -1, -1, -1, 429, -1, -1, 339, + -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, + 370, 371, 372, 373, 374, 375, 376, -1, 378, 379, + -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, -1, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, -1, 256, 256, -1, -1, -1, + 420, 262, -1, 423, -1, 265, -1, 267, -1, 429, + 270, -1, -1, -1, -1, 275, -1, -1, -1, 279, + -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, + -1, -1, -1, -1, -1, 295, -1, 298, -1, -1, + 300, -1, -1, -1, 304, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 316, -1, 318, -1, + -1, -1, 322, -1, -1, -1, -1, -1, -1, -1, + 330, 331, -1, -1, 334, -1, -1, 337, 339, -1, + -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 368, -1, 370, + 371, 372, 373, 374, 375, 376, -1, 378, 379, -1, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + -1, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, -1, 256, 256, -1, -1, 418, 420, + 262, -1, 423, -1, 265, -1, 267, -1, 429, 270, + -1, -1, -1, -1, 275, -1, -1, -1, 279, -1, + -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, 298, -1, -1, 300, + -1, -1, -1, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, -1, -1, + -1, 322, -1, -1, -1, -1, -1, -1, -1, 330, + 331, -1, -1, 334, -1, -1, 337, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 368, -1, 370, 371, + 372, 373, 374, 375, 376, -1, 378, -1, -1, 381, + 382, 383, 384, 385, 386, 387, 388, 389, 390, -1, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, 256, -1, 256, -1, 418, 420, 262, + -1, 423, -1, 264, 265, -1, 267, 429, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + -1, -1, -1, -1, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, 298, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, 339, -1, -1, -1, + -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 359, 360, + 361, 362, -1, -1, -1, 368, -1, 370, -1, 372, + 371, 374, 375, 376, -1, 378, 379, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 261, -1, + -1, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 256, + 413, 284, -1, -1, -1, 262, 417, 418, -1, -1, + -1, -1, -1, -1, 297, -1, 429, -1, -1, 302, + -1, -1, 305, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, -1, 317, -1, -1, -1, 321, -1, + -1, 298, 325, -1, -1, -1, -1, -1, -1, -1, + 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, + -1, -1, -1, 262, -1, -1, -1, -1, -1, 362, + -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, 378, 379, -1, -1, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 418, -1, 394, 395, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, 256, 429, -1, -1, -1, -1, 262, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, 378, + 379, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, -1, -1, 394, 395, 396, 397, 398, + 399, 400, 401, 298, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 413, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, + 429, -1, -1, -1, -1, 262, -1, -1, -1, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 298, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, 256, 429, -1, -1, -1, -1, 262, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, 378, 379, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, -1, -1, 394, 395, 396, + 397, 398, 399, 400, 401, 298, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 413, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 256, 429, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, 378, 379, -1, -1, 382, + 383, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, 394, 395, 396, 397, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, 394, 395, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, 256, -1, 394, 395, 396, 397, 398, + 399, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, 382, 383, 384, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, 396, 397, 398, 399, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, 382, + 383, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, -1, -1, 396, 397, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, + -1, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, -1, -1, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, 256, -1, -1, -1, 396, 397, 398, + 399, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, 384, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, -1, -1, 398, 399, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, -1, -1, -1, -1, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, + -1, -1, -1, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, -1, -1, -1, + -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, + 389, 390, -1, 256, -1, -1, -1, -1, -1, -1, + -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, -1, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, -1, 385, -1, -1, -1, -1, 390, -1, 256, + -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, + 385, -1, -1, -1, -1, 390, -1, 256, -1, -1, + -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 390, -1, 256, -1, -1, -1, -1, + -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, 256, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 390, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 390, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 401, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 413, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, 429, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 256, -1, 390, -1, -1, -1, -1, + -1, 264, 265, 266, 267, -1, 401, 270, 271, -1, + 273, 274, 275, 276, 277, 278, 279, -1, 413, -1, + -1, -1, 285, -1, 287, 288, 289, 290, 291, 292, + -1, -1, 295, -1, 429, -1, 299, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, + -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, -1, -1, 340, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 256, -1, -1, -1, 417, 418, 419, 420, 264, 265, + 266, 267, -1, -1, 270, 271, -1, 273, 274, 275, + 276, 277, 278, 279, -1, -1, -1, -1, -1, 285, + -1, 287, 288, 289, 290, 291, 292, -1, -1, 295, + -1, -1, -1, 299, 300, -1, 302, 303, 304, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, + 316, -1, 318, 319, -1, -1, 322, -1, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, -1, -1, 340, 341, -1, -1, 344, 345, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, + -1, 367, -1, -1, -1, 371, -1, -1, -1, -1, + 376, 377, 378, 379, 380, -1, -1, -1, 384, -1, + 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, + -1, 417, 418, 419, 420, 264, 265, 266, 267, -1, + -1, 270, 271, -1, 273, 274, 275, 276, 277, 278, + 279, -1, -1, -1, -1, -1, 285, -1, 287, 288, + 289, 290, 291, 292, -1, -1, 295, -1, -1, -1, + 299, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 314, -1, 316, -1, 318, + 319, -1, -1, 322, -1, 324, 325, 326, 327, 328, + 329, 330, 331, 332, 333, 334, 335, -1, 337, -1, + -1, 340, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, 367, -1, + -1, -1, 371, -1, -1, -1, -1, 376, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 256, -1, -1, -1, 417, 418, + 419, 420, 264, 265, 266, 267, -1, -1, 270, 271, + -1, 273, 274, 275, 276, 277, 278, 279, -1, -1, + -1, -1, -1, 285, -1, 287, 288, 289, 290, 291, + 292, -1, -1, 295, -1, -1, -1, 299, 300, -1, + 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, + 322, -1, 324, 325, 326, 327, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, -1, -1, 340, 341, + -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, + 362, 363, -1, -1, -1, 367, -1, -1, -1, 371, + -1, -1, -1, -1, 376, 377, 378, 379, 380, -1, + -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, + 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 256, -1, -1, -1, 417, 418, 419, 420, 264, + 265, 266, 267, -1, -1, 270, 271, -1, 273, 274, + 275, 276, 277, 278, 279, -1, -1, -1, -1, -1, + 285, -1, 287, 288, 289, 290, 291, 292, -1, -1, + 295, -1, -1, -1, 299, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, + -1, 316, -1, 318, 319, -1, -1, 322, -1, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, -1, 337, -1, -1, 340, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, -1, -1, -1, 371, -1, -1, -1, + -1, 376, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, + -1, -1, 417, 418, 419, 420, 264, 265, -1, 267, + -1, -1, 270, 271, -1, 256, -1, 275, 276, 277, + -1, 279, -1, -1, 265, -1, 267, 285, -1, 270, + 288, -1, -1, -1, 275, -1, -1, 295, 279, -1, + -1, -1, 300, -1, 302, 303, 304, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, 316, 300, + 318, 319, -1, 304, 322, -1, -1, 325, -1, 327, + -1, 329, 330, 331, 332, 316, 334, 318, -1, -1, + -1, 322, -1, 341, -1, -1, 344, 345, -1, 330, + 331, -1, -1, 334, -1, -1, 337, -1, -1, -1, + -1, 359, 360, 361, 362, 363, -1, -1, -1, 367, + 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, + 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, + -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 256, -1, -1, -1, 417, + 418, 419, 420, 264, 265, -1, 267, -1, -1, 270, + 271, -1, 256, -1, 275, 276, 277, 418, 279, -1, + -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, + -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, + -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, + -1, 295, -1, -1, -1, 316, 300, 318, 319, 320, + 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, + 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, 418, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, 368, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 256, -1, 417, 418, 419, 420, -1, -1, 264, 265, + -1, 267, -1, 428, 270, 271, -1, -1, -1, 275, + 276, 277, -1, 279, -1, -1, 265, -1, 267, 285, + -1, 270, 288, -1, -1, -1, 275, -1, -1, 295, + 279, -1, -1, -1, 300, -1, 302, 303, 304, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + 316, 300, 318, 319, -1, 304, 322, -1, -1, 325, + -1, 327, -1, 329, 330, 331, 332, 316, 334, 318, + -1, 337, -1, 322, -1, 341, -1, -1, 344, 345, + -1, 330, 331, -1, -1, 334, -1, -1, 337, -1, + -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, + -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, + 386, -1, -1, 372, -1, -1, 392, 393, -1, -1, + -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, + 270, 271, -1, -1, -1, 275, 276, 277, -1, 279, + -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, + -1, -1, -1, -1, -1, 295, -1, -1, -1, 418, + 300, -1, 302, 303, 304, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, + -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, + 330, 331, 332, -1, 334, -1, -1, -1, -1, -1, + -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, + 360, 361, 362, 363, -1, -1, -1, 367, -1, -1, + -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, + 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, + -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 256, -1, 417, 418, 419, + 420, -1, -1, 264, 265, -1, 267, -1, 428, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, + -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, + -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, + -1, 295, -1, -1, -1, 316, 300, 318, 319, -1, + 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, + 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, 370, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 256, -1, -1, -1, 417, 418, 419, 420, + 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, + -1, 275, 276, 277, 418, 279, -1, -1, 265, -1, + 267, 285, -1, 270, 288, -1, -1, -1, 275, -1, + -1, 295, 279, -1, -1, -1, 300, -1, 302, 303, + 304, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, 316, 300, 318, 319, -1, 304, 322, -1, + -1, 325, -1, 327, -1, 329, 330, 331, 332, 316, + 334, 318, -1, -1, -1, 322, -1, 341, -1, -1, + 344, 345, -1, 330, 331, -1, -1, 334, -1, -1, + 337, -1, -1, -1, -1, 359, 360, 361, 362, 363, + -1, -1, -1, -1, -1, -1, -1, 371, -1, -1, + -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, + 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, + -1, -1, -1, 417, 418, 419, 420, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, 418, 279, -1, -1, -1, -1, -1, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, 262, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, 298, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 417, 418, 419, 420, 371, 372, 373, 374, -1, -1, + -1, 378, 379, -1, -1, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 261, -1, + -1, -1, 265, 420, 267, -1, 423, 270, -1, 272, + 273, -1, 275, -1, 277, -1, 279, -1, 281, 282, + 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, + -1, 304, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, 316, 317, 318, -1, -1, 321, 322, + 323, -1, -1, -1, -1, -1, -1, 330, 331, -1, + 333, 334, -1, 336, 337, 338, -1, -1, -1, 342, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 261, -1, 362, + -1, 265, -1, 267, -1, 368, 270, -1, 272, 273, + -1, 275, -1, 277, 377, 279, -1, 281, 282, 283, + 284, -1, -1, 287, 288, -1, -1, -1, -1, 293, + -1, 295, 296, 297, -1, -1, 300, -1, 302, -1, + 304, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, -1, 316, 317, 318, 418, -1, 321, 322, 323, + -1, -1, -1, -1, -1, -1, 330, 331, -1, 333, + 334, -1, 336, 337, 338, -1, -1, -1, 342, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 261, -1, 362, -1, + 265, -1, 267, -1, 368, 270, -1, 272, 273, -1, + 275, -1, 277, 377, 279, -1, 281, 282, 283, 284, + -1, -1, 287, 288, -1, -1, -1, -1, 293, -1, + 295, 296, 297, -1, -1, 300, -1, 302, -1, 304, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, 316, 317, 318, 418, -1, 321, 322, 323, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 333, 334, + -1, 336, 337, 338, -1, -1, -1, 342, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 261, -1, 362, -1, 265, + -1, 267, -1, 368, 270, -1, 272, 273, -1, 275, + -1, 277, 377, 279, -1, 281, 282, 283, 284, -1, + -1, 287, 288, -1, -1, -1, -1, 293, -1, 295, + 296, 297, -1, -1, 300, -1, 302, -1, 304, -1, + -1, 307, -1, 309, 310, 311, 312, -1, -1, -1, + 316, 317, 318, 418, -1, 321, 322, 323, -1, -1, + -1, -1, -1, -1, 330, 331, -1, 333, 334, -1, + 336, 337, 338, -1, -1, -1, 342, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 261, -1, 362, -1, 265, -1, + 267, -1, 368, 270, -1, 272, 273, -1, 275, -1, + 277, 377, 279, -1, 281, 282, 283, 284, -1, -1, + 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, + 297, -1, -1, 300, -1, 302, -1, 304, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, -1, 316, + 317, 318, 418, -1, 321, 322, 323, -1, -1, -1, + -1, -1, -1, 330, 331, -1, 333, 334, -1, 336, + 337, 338, -1, -1, -1, 342, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 261, -1, + -1, -1, 265, -1, 267, 362, -1, 270, -1, 272, + 273, 368, 275, -1, 277, -1, 279, -1, 281, 282, + 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, + 261, 304, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, 316, 317, 318, -1, -1, 321, 322, + 323, 418, -1, 284, -1, -1, -1, 330, 331, -1, + 333, 334, 261, 336, 337, 338, 297, -1, -1, 342, + -1, 302, -1, -1, 305, -1, 307, -1, 309, 310, + 311, 312, -1, -1, -1, 284, 317, -1, -1, 362, + 321, -1, -1, -1, 325, 368, -1, -1, 297, -1, + 261, -1, 333, 302, -1, 336, -1, 338, 307, -1, + 309, 310, 311, 312, -1, -1, -1, -1, 317, -1, + -1, -1, 321, 284, -1, -1, 357, -1, -1, -1, + -1, 362, -1, -1, 333, -1, 297, 336, 369, 338, + 371, 302, 373, -1, 305, 418, 307, -1, 309, 310, + 311, 312, -1, -1, -1, 386, 317, -1, -1, -1, + 321, -1, -1, 362, 325, -1, -1, -1, -1, -1, + -1, -1, 333, 264, 265, 336, 267, 338, -1, 270, + 271, -1, -1, -1, 275, 276, 277, 418, 279, -1, + -1, -1, -1, -1, 285, -1, -1, 288, -1, -1, + -1, 362, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, 306, -1, -1, -1, 418, + -1, -1, 313, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, 418, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + 371, 372, -1, 374, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, 306, -1, -1, -1, -1, -1, -1, 313, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, 371, -1, -1, 374, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + -1, 300, -1, 302, 303, 304, -1, 306, -1, -1, + -1, -1, -1, -1, 313, -1, -1, 316, -1, 318, + 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, + -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, + 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, + -1, -1, 295, -1, -1, -1, -1, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + -1, 334, -1, -1, 337, -1, -1, -1, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, 368, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, -1, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, + 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, + -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, + 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, + -1, -1, 295, -1, -1, -1, -1, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + -1, 334, -1, -1, -1, -1, -1, -1, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, 261, -1, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, + 319, 284, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, 297, 334, -1, -1, -1, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, 315, -1, 317, -1, -1, -1, 321, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + 333, -1, 371, 336, -1, 338, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, 264, + 265, -1, 267, 392, 393, 270, 271, -1, -1, 362, + 275, 276, 277, -1, 279, 368, 369, -1, -1, -1, + 285, -1, -1, 288, -1, -1, -1, 261, 417, 418, + 295, 420, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 284, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, 297, 329, 330, 331, 332, 302, 334, + -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, 315, -1, 317, -1, -1, -1, 321, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, 333, + -1, -1, 336, -1, 338, -1, 371, 263, -1, 265, + -1, 267, 377, -1, 270, 380, 272, 273, -1, 275, + -1, 277, -1, 279, -1, 281, 282, 283, 362, -1, + -1, 287, 288, -1, 368, -1, -1, 293, -1, 295, + 296, -1, -1, -1, 300, -1, -1, -1, 304, -1, + -1, -1, 417, 418, -1, 420, -1, -1, -1, 315, + 316, -1, 318, -1, -1, -1, 322, 323, -1, -1, + -1, -1, -1, -1, 330, 331, 264, 265, 334, 267, + -1, 337, 270, 271, -1, -1, 342, 275, 276, 277, + -1, 279, -1, -1, -1, -1, -1, 285, -1, -1, + 288, -1, -1, -1, -1, -1, -1, 295, 364, 365, + -1, -1, 300, -1, 302, 303, 304, -1, -1, -1, + -1, 377, -1, -1, -1, -1, -1, -1, 316, -1, + 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, + -1, 329, 330, 331, 332, -1, 334, -1, -1, 337, + -1, -1, -1, -1, -1, -1, 265, -1, 267, -1, + -1, 270, 418, 272, -1, -1, 275, -1, -1, -1, + 279, 359, 360, 361, 362, -1, -1, -1, -1, 288, + 265, -1, 267, 371, -1, 270, 295, 272, 273, -1, + 275, 300, 277, 302, 279, 304, 281, 282, 283, -1, + -1, -1, 287, 288, -1, -1, -1, 316, 293, 318, + 295, 296, -1, 322, 323, 300, -1, -1, -1, 304, + -1, 330, 331, -1, -1, 334, -1, -1, 337, 417, + 418, 316, -1, 318, -1, -1, -1, 322, 323, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 265, 334, + 267, -1, 337, 270, -1, 272, 273, 342, 275, -1, + 277, -1, 279, -1, 281, 282, 283, -1, -1, -1, + 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, + -1, -1, -1, 300, -1, -1, -1, 304, -1, -1, + -1, -1, 377, -1, -1, -1, -1, -1, -1, 316, + -1, 318, -1, -1, -1, 322, 323, -1, -1, 418, + -1, -1, -1, 330, 331, -1, -1, 334, -1, -1, + 337, -1, 265, -1, 267, 342, -1, 270, -1, -1, + 273, -1, 275, 418, 277, -1, 279, -1, 281, 282, + 283, -1, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, -1, 265, -1, 267, 300, -1, 270, + -1, 304, 273, -1, 275, -1, 277, -1, 279, -1, + 281, 282, 283, 316, -1, 318, 287, 288, -1, 322, + -1, -1, 293, -1, 295, -1, -1, 330, 331, 300, + -1, 334, -1, 304, 337, -1, -1, -1, 265, 342, + 267, 418, -1, 270, -1, 316, -1, 318, 275, -1, + -1, 322, 279, -1, -1, -1, -1, -1, -1, 330, + 331, 288, -1, 334, -1, -1, 337, -1, 295, -1, + 265, 342, 267, 300, 377, 270, -1, 304, -1, 306, + 275, 308, -1, -1, 279, -1, 313, -1, -1, 316, + -1, 318, -1, 288, -1, 322, -1, -1, 325, -1, + 295, -1, -1, 330, 331, 300, -1, 334, -1, 304, + 337, 306, -1, 308, 265, 418, 267, -1, 313, 270, + -1, 316, -1, 318, 275, -1, -1, 322, 279, -1, + 325, -1, -1, -1, -1, 330, 331, 288, -1, 334, + -1, -1, 337, -1, 295, 372, 265, 418, 267, 300, + -1, 270, -1, 304, -1, 306, 275, 308, -1, -1, + 279, -1, 313, -1, -1, 316, -1, 318, -1, 288, + -1, 322, -1, -1, 325, 370, 295, -1, -1, 330, + 331, 300, -1, 334, -1, 304, 337, 306, -1, -1, + -1, 418, -1, -1, 313, -1, -1, 316, -1, 318, + -1, -1, -1, 322, -1, -1, 325, -1, -1, -1, + -1, 330, 331, -1, -1, 334, -1, 265, 337, 267, + -1, -1, 270, 418, -1, -1, -1, 275, -1, -1, + -1, 279, -1, -1, -1, 283, 265, -1, 267, -1, + 288, 270, -1, -1, -1, 293, 275, 295, -1, -1, + 279, -1, 300, -1, -1, -1, 304, 305, -1, 288, + -1, -1, -1, -1, -1, -1, 295, 418, 316, -1, + 318, 300, -1, -1, 322, 304, -1, -1, -1, -1, + -1, -1, 330, 331, -1, -1, 334, 316, -1, 318, + 265, -1, 267, 322, -1, 270, -1, -1, -1, 418, + 275, 330, 331, -1, 279, 334, -1, 265, 337, 267, + -1, -1, 270, 288, -1, -1, -1, 275, -1, -1, + 295, 279, -1, -1, -1, 300, -1, -1, -1, 304, + 288, -1, -1, -1, -1, -1, -1, 295, -1, -1, + -1, 316, 300, 318, -1, -1, 304, 322, -1, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 316, 334, + 318, 265, 337, 267, 322, -1, 270, -1, -1, -1, + 418, 275, 330, 331, -1, 279, 334, -1, -1, 337, + -1, -1, -1, -1, 288, 265, -1, 267, -1, 418, + 270, 295, -1, -1, -1, 275, 300, -1, -1, 279, + 304, -1, -1, -1, -1, -1, -1, -1, 288, -1, + -1, -1, 316, -1, 318, 295, -1, -1, 322, -1, + 300, -1, -1, -1, 304, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, 265, 316, 267, 318, -1, + 270, -1, 322, 418, -1, 275, -1, -1, -1, 279, + 330, 331, -1, -1, 334, -1, -1, 337, 288, 265, + 418, 267, -1, -1, 270, 295, -1, -1, -1, 275, + 300, -1, -1, 279, 304, -1, -1, -1, -1, -1, + -1, -1, 288, -1, -1, -1, 316, -1, 318, 295, + -1, -1, 322, -1, 300, -1, -1, -1, 304, -1, + 330, 331, -1, -1, 334, -1, -1, 337, -1, -1, + 316, -1, 318, 265, 418, 267, 322, -1, 270, -1, + -1, -1, -1, 275, 330, 331, -1, 279, 334, -1, + 265, 337, 267, -1, -1, 270, 288, -1, 418, -1, + 275, -1, -1, 295, 279, -1, -1, -1, 300, -1, + -1, -1, 304, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, 316, 300, 318, -1, -1, 304, + 322, -1, -1, -1, -1, -1, -1, -1, 330, 331, + -1, 316, 334, 318, 265, 337, 267, 322, 418, 270, + -1, -1, -1, -1, 275, 330, 331, -1, 279, 334, + -1, -1, 337, -1, -1, -1, -1, 288, 265, -1, + 267, -1, 418, 270, 295, -1, -1, -1, 275, 300, + -1, -1, 279, 304, -1, -1, -1, -1, -1, -1, + -1, 288, -1, -1, -1, 316, -1, 318, 295, -1, + -1, 322, -1, 300, -1, -1, -1, 304, -1, 330, + 331, -1, 261, 334, -1, -1, 337, -1, -1, 316, + -1, 318, -1, 272, -1, 322, 418, -1, 277, -1, + -1, -1, 281, 330, 331, 284, -1, 334, -1, -1, + 337, -1, -1, 418, -1, -1, -1, 296, 297, -1, + -1, -1, 301, 302, -1, 261, -1, -1, 307, -1, + 309, 310, 311, 312, -1, -1, 272, -1, 317, -1, + -1, 277, 321, -1, 323, 281, -1, -1, 284, -1, + -1, -1, -1, -1, 333, -1, 335, 336, -1, 338, + 296, 297, -1, 342, -1, 301, 302, 418, -1, -1, + -1, 307, -1, 309, 310, 311, 312, -1, -1, -1, + -1, 317, -1, 362, -1, 321, -1, 323, -1, 368, + 369, 418, -1, 261, -1, 263, -1, 333, -1, -1, + 336, -1, 338, -1, -1, -1, 342, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 284, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 362, -1, -1, 297, + -1, -1, 368, 369, 302, -1, 261, -1, -1, 307, + -1, 309, 310, 311, 312, -1, -1, 272, -1, 317, + -1, -1, 277, 321, -1, -1, 281, -1, -1, 284, + -1, -1, -1, -1, -1, 333, -1, -1, 336, -1, + 338, 296, 297, -1, -1, -1, 301, 302, -1, 261, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + 272, -1, 317, -1, 362, 277, 321, -1, 323, 281, + 368, 369, 284, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 296, 297, -1, 342, -1, 301, + 302, 261, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, 362, -1, 321, + -1, 323, -1, 368, 284, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 297, -1, 261, + 342, -1, 302, -1, -1, -1, -1, 307, -1, 309, + 310, 311, 312, -1, -1, -1, -1, 317, -1, -1, + 362, 321, 284, -1, -1, -1, 368, -1, -1, -1, + -1, -1, -1, 333, -1, 297, 336, 261, 338, 263, + 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + 284, -1, 362, -1, 364, 365, -1, -1, 368, -1, + -1, 333, -1, 297, 336, 261, 338, -1, 302, -1, + -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, -1, -1, 317, -1, -1, -1, 321, 284, -1, + 362, -1, 364, 365, -1, 261, 368, -1, -1, 333, + -1, 297, 336, -1, 338, -1, 302, -1, -1, -1, + -1, 307, -1, 309, 310, 311, 312, -1, 284, -1, + -1, 317, -1, -1, -1, 321, -1, -1, 362, -1, + -1, 297, -1, -1, 368, 301, 302, 333, 261, -1, + 336, 307, 338, 309, 310, 311, 312, -1, -1, -1, + -1, 317, -1, -1, -1, 321, -1, -1, -1, -1, + -1, 284, -1, -1, -1, -1, 362, 333, 364, 365, + 336, -1, 338, -1, 297, -1, -1, -1, -1, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, -1, 317, -1, 362, -1, 321, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, + }; + +#line 6263 "cs-parser.jay" + +// +// A class used to hold info about an operator declarator +// +class OperatorDeclaration { + public readonly Operator.OpType optype; + public readonly FullNamedExpression ret_type; + public readonly Location location; + + public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) + { + optype = op; + this.ret_type = ret_type; + this.location = location; + } +} + +void Error_ExpectingTypeName (Expression expr) +{ + if (expr is Invocation){ + report.Error (1002, expr.Location, "Expecting `;'"); + } else { + Expression.Error_InvalidExpressionStatement (report, expr.Location); + } +} + +void Error_ParameterModifierNotValid (string modifier, Location loc) +{ + report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", + modifier); +} + +void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) +{ + report.Error (1107, loc, "Duplicate parameter modifier `{0}'", + Parameter.GetModifierSignature (mod)); +} + +void Error_TypeExpected (Location loc) +{ + report.Error (1031, loc, "Type expected"); +} + +void Error_UnsafeCodeNotAllowed (Location loc) +{ + report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); +} + +void Warning_EmptyStatement (Location loc) +{ + report.Warning (642, 3, loc, "Possible mistaken empty statement"); +} + +void Error_NamedArgumentExpected (NamedArgument a) +{ + report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); +} + +void push_current_class (TypeContainer tc, object partial_token) +{ + if (module.Evaluator != null && current_container is ModuleContainer){ + tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; + if (undo == null) + undo = new Undo (); + undo.AddTypeContainer (current_container, tc); + } + + if (partial_token != null) + current_container = current_container.AddPartial (tc); + else + current_container = current_container.AddTypeContainer (tc); + + ++lexer.parsing_declaration; + current_class = tc; + ubag.PushTypeDeclaration (tc); +} + +DeclSpace pop_current_class () +{ + DeclSpace retval = current_class; + + current_class = current_class.Parent; + current_container = current_class.PartialContainer; + ubag.PopTypeDeclaration (); + + return retval; +} + +// +// Given the @class_name name, it creates a fully qualified name +// based on the containing declaration space +// +MemberName +MakeName (MemberName class_name) +{ + Namespace ns = current_namespace.NS; + + if (current_container == module) { + if (ns.Name.Length != 0) + return new MemberName (ns.MemberName, class_name); + else + return class_name; + } else { + return new MemberName (current_container.MemberName, class_name); + } +} + +[System.Diagnostics.Conditional ("FULL_AST")] +void StoreModifierLocation (object token, Location loc) +{ + if (lbag == null) + return; + + if (mod_locations == null) + mod_locations = new List> (); + + mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); +} + +List> GetModifierLocations () +{ + var result = mod_locations; + mod_locations = null; + return result; +} + +string CheckAttributeTarget (string a, Location l) +{ + switch (a) { + case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : + return a; + } + + report.Warning (658, 1, l, + "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); + return string.Empty; +} + +static bool IsUnaryOperator (Operator.OpType op) +{ + switch (op) { + + case Operator.OpType.LogicalNot: + case Operator.OpType.OnesComplement: + case Operator.OpType.Increment: + case Operator.OpType.Decrement: + case Operator.OpType.True: + case Operator.OpType.False: + case Operator.OpType.UnaryPlus: + case Operator.OpType.UnaryNegation: + return true; + } + return false; +} + +void syntax_error (Location l, string msg) +{ + report.Error (1003, l, "Syntax error, " + msg); +} + +Tokenizer lexer; + +public Tokenizer Lexer { + get { + return lexer; + } +} + +static CSharpParser () +{ + oob_stack = new Stack (); +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file) + : this (reader, file, file.NamespaceContainer.Module.Compiler.Report) +{ +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report) +{ + this.file = file; + current_namespace = file.NamespaceContainer; + + this.module = current_namespace.Module; + this.compiler = module.Compiler; + this.settings = compiler.Settings; + this.report = report; + + lang_version = settings.Version; + doc_support = settings.DocumentationFile != null; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes + oob_stack.Clear (); + lexer = new Tokenizer (reader, file, compiler); + + use_global_stacks = true; +} + +public void parse () +{ + eof_token = Token.EOF; + Tokenizer.LocatedToken.Initialize (); + + try { + if (yacc_verbose_flag > 1) + yyparse (lexer, new yydebug.yyDebugSimple ()); + else + yyparse (lexer); + + Tokenizer tokenizer = lexer as Tokenizer; + tokenizer.cleanup (); + } catch (Exception e){ + if (e is yyParser.yyUnexpectedEof) { + Error_SyntaxError (yyToken); + UnexpectedEOF = true; + return; + } + + if (e is yyParser.yyException) { + report.Error (-25, lexer.Location, "Parsing error"); + } else { + // Used by compiler-tester to test internal errors + if (yacc_verbose_flag > 0) + throw; + + report.Error (589, lexer.Location, "Internal compiler error during parsing"); + } + } +} + +void CheckToken (int error, int yyToken, string msg, Location loc) +{ + if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) + report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); + else + report.Error (error, loc, msg); +} + +string ConsumeStoredComment () +{ + string s = tmpComment; + tmpComment = null; + Lexer.doc_state = XmlCommentState.Allowed; + return s; +} + +void FeatureIsNotAvailable (Location loc, string feature) +{ + report.FeatureIsNotAvailable (compiler, loc, feature); +} + +Location GetLocation (object obj) +{ + var lt = obj as Tokenizer.LocatedToken; + if (lt != null) + return lt.Location; + + var mn = obj as MemberName; + if (mn != null) + return mn.Location; + + var expr = obj as Expression; + if (expr != null) + return expr.Location; + + return lexer.Location; +} + +public LocationsBag LocationsBag { + get { + return lbag; + } + set { + lbag = value; + } +} + +public UsingsBag UsingsBag { + get { + return ubag; + } + set { + ubag = value; + } +} + +void start_block (Location loc) +{ + if (current_block == null) { + current_block = new ToplevelBlock (compiler, current_local_parameters, loc); + parsing_anonymous_method = false; + } else if (parsing_anonymous_method) { + current_block = new ParametersBlock (current_block, current_local_parameters, loc); + parsing_anonymous_method = false; + } else { + current_block = new ExplicitBlock (current_block, loc, Location.Null); + } +} + +Block +end_block (Location loc) +{ + Block retval = current_block.Explicit; + retval.SetEndLocation (loc); + current_block = retval.Parent; + return retval; +} + +void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync, Location loc) +{ + oob_stack.Push (current_anonymous_method); + oob_stack.Push (current_local_parameters); + oob_stack.Push (current_variable); + + current_local_parameters = parameters; + if (isLambda) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (loc, "lambda expressions"); + + current_anonymous_method = new LambdaExpression (isAsync, loc); + } else { + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (loc, "anonymous methods"); + + current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); + } + + // Force the next block to be created as a ToplevelBlock + parsing_anonymous_method = true; +} + +/* + * Completes the anonymous method processing, if lambda_expr is null, this + * means that we have a Statement instead of an Expression embedded + */ +AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) +{ + AnonymousMethodExpression retval; + + current_anonymous_method.Block = anon_block; + retval = current_anonymous_method; + + current_variable = (BlockVariableDeclaration) oob_stack.Pop (); + current_local_parameters = (ParametersCompiled) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + + return retval; +} + +void Error_SyntaxError (int token) +{ + Error_SyntaxError (0, token, "Unexpected symbol"); +} + +void Error_SyntaxError (int error_code, int token, string msg) +{ + Lexer.CompleteOnEOF = false; + + // An error message has been reported by tokenizer + if (token == Token.ERROR) + return; + + string symbol = GetSymbolName (token); + string expecting = GetExpecting (); + var loc = lexer.Location - symbol.Length; + + if (error_code == 0) { + if (expecting == "`identifier'") { + if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { + report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); + return; + } + + error_code = 1001; + expecting = "identifier"; + } else if (expecting == "`)'") { + error_code = 1026; + } else { + error_code = 1525; + } + } + + if (string.IsNullOrEmpty (expecting)) + report.Error (error_code, loc, "{1} `{0}'", symbol, msg); + else + report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); +} + +string GetExpecting () +{ + int [] tokens = yyExpectingTokens (yyExpectingState); + var names = new List (tokens.Length); + bool has_type = false; + bool has_identifier = false; + for (int i = 0; i < tokens.Length; i++){ + int token = tokens [i]; + has_identifier |= token == Token.IDENTIFIER; + + string name = GetTokenName (token); + if (name == "") + continue; + + has_type |= name == "type"; + if (names.Contains (name)) + continue; + + names.Add (name); + } + + // + // Too many tokens to enumerate + // + if (names.Count > 8) + return null; + + if (has_type && has_identifier) + names.Remove ("identifier"); + + if (names.Count == 1) + return "`" + GetTokenName (tokens [0]) + "'"; + + StringBuilder sb = new StringBuilder (); + names.Sort (); + int count = names.Count; + for (int i = 0; i < count; i++){ + bool last = i + 1 == count; + if (last) + sb.Append ("or "); + sb.Append ('`'); + sb.Append (names [i]); + sb.Append (last ? "'" : count < 3 ? "' " : "', "); + } + return sb.ToString (); +} + + +string GetSymbolName (int token) +{ + switch (token){ + case Token.LITERAL: + return ((Constant)lexer.Value).GetValue ().ToString (); + case Token.IDENTIFIER: + return ((Tokenizer.LocatedToken)lexer.Value).Value; + + case Token.BOOL: + return "bool"; + case Token.BYTE: + return "byte"; + case Token.CHAR: + return "char"; + case Token.VOID: + return "void"; + case Token.DECIMAL: + return "decimal"; + case Token.DOUBLE: + return "double"; + case Token.FLOAT: + return "float"; + case Token.INT: + return "int"; + case Token.LONG: + return "long"; + case Token.SBYTE: + return "sbyte"; + case Token.SHORT: + return "short"; + case Token.STRING: + return "string"; + case Token.UINT: + return "uint"; + case Token.ULONG: + return "ulong"; + case Token.USHORT: + return "ushort"; + case Token.OBJECT: + return "object"; + + case Token.PLUS: + return "+"; + case Token.UMINUS: + case Token.MINUS: + return "-"; + case Token.BANG: + return "!"; + case Token.BITWISE_AND: + return "&"; + case Token.BITWISE_OR: + return "|"; + case Token.STAR: + return "*"; + case Token.PERCENT: + return "%"; + case Token.DIV: + return "/"; + case Token.CARRET: + return "^"; + case Token.OP_INC: + return "++"; + case Token.OP_DEC: + return "--"; + case Token.OP_SHIFT_LEFT: + return "<<"; + case Token.OP_SHIFT_RIGHT: + return ">>"; + case Token.OP_LT: + return "<"; + case Token.OP_GT: + return ">"; + case Token.OP_LE: + return "<="; + case Token.OP_GE: + return ">="; + case Token.OP_EQ: + return "=="; + case Token.OP_NE: + return "!="; + case Token.OP_AND: + return "&&"; + case Token.OP_OR: + return "||"; + case Token.OP_PTR: + return "->"; + case Token.OP_COALESCING: + return "??"; + case Token.OP_MULT_ASSIGN: + return "*="; + case Token.OP_DIV_ASSIGN: + return "/="; + case Token.OP_MOD_ASSIGN: + return "%="; + case Token.OP_ADD_ASSIGN: + return "+="; + case Token.OP_SUB_ASSIGN: + return "-="; + case Token.OP_SHIFT_LEFT_ASSIGN: + return "<<="; + case Token.OP_SHIFT_RIGHT_ASSIGN: + return ">>="; + case Token.OP_AND_ASSIGN: + return "&="; + case Token.OP_XOR_ASSIGN: + return "^="; + case Token.OP_OR_ASSIGN: + return "|="; + } + + return GetTokenName (token); +} + +static string GetTokenName (int token) +{ + switch (token){ + case Token.ABSTRACT: + return "abstract"; + case Token.AS: + return "as"; + case Token.ADD: + return "add"; + case Token.ASYNC: + return "async"; + case Token.BASE: + return "base"; + case Token.BREAK: + return "break"; + case Token.CASE: + return "case"; + case Token.CATCH: + return "catch"; + case Token.CHECKED: + return "checked"; + case Token.CLASS: + return "class"; + case Token.CONST: + return "const"; + case Token.CONTINUE: + return "continue"; + case Token.DEFAULT: + return "default"; + case Token.DELEGATE: + return "delegate"; + case Token.DO: + return "do"; + case Token.ELSE: + return "else"; + case Token.ENUM: + return "enum"; + case Token.EVENT: + return "event"; + case Token.EXPLICIT: + return "explicit"; + case Token.EXTERN: + case Token.EXTERN_ALIAS: + return "extern"; + case Token.FALSE: + return "false"; + case Token.FINALLY: + return "finally"; + case Token.FIXED: + return "fixed"; + case Token.FOR: + return "for"; + case Token.FOREACH: + return "foreach"; + case Token.GOTO: + return "goto"; + case Token.IF: + return "if"; + case Token.IMPLICIT: + return "implicit"; + case Token.IN: + return "in"; + case Token.INTERFACE: + return "interface"; + case Token.INTERNAL: + return "internal"; + case Token.IS: + return "is"; + case Token.LOCK: + return "lock"; + case Token.NAMESPACE: + return "namespace"; + case Token.NEW: + return "new"; + case Token.NULL: + return "null"; + case Token.OPERATOR: + return "operator"; + case Token.OUT: + return "out"; + case Token.OVERRIDE: + return "override"; + case Token.PARAMS: + return "params"; + case Token.PRIVATE: + return "private"; + case Token.PROTECTED: + return "protected"; + case Token.PUBLIC: + return "public"; + case Token.READONLY: + return "readonly"; + case Token.REF: + return "ref"; + case Token.RETURN: + return "return"; + case Token.REMOVE: + return "remove"; + case Token.SEALED: + return "sealed"; + case Token.SIZEOF: + return "sizeof"; + case Token.STACKALLOC: + return "stackalloc"; + case Token.STATIC: + return "static"; + case Token.STRUCT: + return "struct"; + case Token.SWITCH: + return "switch"; + case Token.THIS: + return "this"; + case Token.THROW: + return "throw"; + case Token.TRUE: + return "true"; + case Token.TRY: + return "try"; + case Token.TYPEOF: + return "typeof"; + case Token.UNCHECKED: + return "unchecked"; + case Token.UNSAFE: + return "unsafe"; + case Token.USING: + return "using"; + case Token.VIRTUAL: + return "virtual"; + case Token.VOLATILE: + return "volatile"; + case Token.WHERE: + return "where"; + case Token.WHILE: + return "while"; + case Token.ARGLIST: + return "__arglist"; + case Token.REFVALUE: + return "__refvalue"; + case Token.REFTYPE: + return "__reftype"; + case Token.MAKEREF: + return "__makeref"; + case Token.PARTIAL: + return "partial"; + case Token.ARROW: + return "=>"; + case Token.FROM: + case Token.FROM_FIRST: + return "from"; + case Token.JOIN: + return "join"; + case Token.ON: + return "on"; + case Token.EQUALS: + return "equals"; + case Token.SELECT: + return "select"; + case Token.GROUP: + return "group"; + case Token.BY: + return "by"; + case Token.LET: + return "let"; + case Token.ORDERBY: + return "orderby"; + case Token.ASCENDING: + return "ascending"; + case Token.DESCENDING: + return "descending"; + case Token.INTO: + return "into"; + case Token.GET: + return "get"; + case Token.SET: + return "set"; + case Token.OPEN_BRACE: + return "{"; + case Token.CLOSE_BRACE: + return "}"; + case Token.OPEN_BRACKET: + case Token.OPEN_BRACKET_EXPR: + return "["; + case Token.CLOSE_BRACKET: + return "]"; + case Token.OPEN_PARENS_CAST: + case Token.OPEN_PARENS_LAMBDA: + case Token.OPEN_PARENS: + return "("; + case Token.CLOSE_PARENS: + return ")"; + case Token.DOT: + return "."; + case Token.COMMA: + return ","; + case Token.DEFAULT_COLON: + return "default:"; + case Token.COLON: + return ":"; + case Token.SEMICOLON: + return ";"; + case Token.TILDE: + return "~"; + + case Token.PLUS: + case Token.UMINUS: + case Token.MINUS: + case Token.BANG: + case Token.OP_LT: + case Token.OP_GT: + case Token.BITWISE_AND: + case Token.BITWISE_OR: + case Token.STAR: + case Token.PERCENT: + case Token.DIV: + case Token.CARRET: + case Token.OP_INC: + case Token.OP_DEC: + case Token.OP_SHIFT_LEFT: + case Token.OP_SHIFT_RIGHT: + case Token.OP_LE: + case Token.OP_GE: + case Token.OP_EQ: + case Token.OP_NE: + case Token.OP_AND: + case Token.OP_OR: + case Token.OP_PTR: + case Token.OP_COALESCING: + case Token.OP_MULT_ASSIGN: + case Token.OP_DIV_ASSIGN: + case Token.OP_MOD_ASSIGN: + case Token.OP_ADD_ASSIGN: + case Token.OP_SUB_ASSIGN: + case Token.OP_SHIFT_LEFT_ASSIGN: + case Token.OP_SHIFT_RIGHT_ASSIGN: + case Token.OP_AND_ASSIGN: + case Token.OP_XOR_ASSIGN: + case Token.OP_OR_ASSIGN: + return ""; + + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.VOID: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + case Token.USHORT: + case Token.OBJECT: + return "type"; + + case Token.ASSIGN: + return "="; + case Token.OP_GENERICS_LT: + case Token.GENERIC_DIMENSION: + return "<"; + case Token.OP_GENERICS_GT: + return ">"; + case Token.INTERR: + case Token.INTERR_NULLABLE: + return "?"; + case Token.DOUBLE_COLON: + return "::"; + case Token.LITERAL: + return "value"; + case Token.IDENTIFIER: + return "identifier"; + + case Token.EOF: + return "end-of-file"; + + // All of these are internal. + case Token.NONE: + case Token.ERROR: + case Token.FIRST_KEYWORD: + case Token.EVAL_COMPILATION_UNIT_PARSER: + case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: + case Token.EVAL_STATEMENT_PARSER: + case Token.LAST_KEYWORD: + case Token.GENERATE_COMPLETION: + case Token.COMPLETE_COMPLETION: + return ""; + + // A bit more robust. + default: + return yyNames [token]; + } +} + +/* end end end */ +} +#line default +namespace yydebug { + using System; + internal interface yyDebug { + void push (int state, Object value); + void lex (int state, int token, string name, Object value); + void shift (int from, int to, int errorFlag); + void pop (int state); + void discard (int state, int token, string name, Object value); + void reduce (int from, int to, int rule, string text, int len); + void shift (int from, int to); + void accept (Object value); + void error (string message); + void reject (); + } + + class yyDebugSimple : yyDebug { + void println (string s){ + Console.Error.WriteLine (s); + } + + public void push (int state, Object value) { + println ("push\tstate "+state+"\tvalue "+value); + } + + public void lex (int state, int token, string name, Object value) { + println("lex\tstate "+state+"\treading "+name+"\tvalue "+value); + } + + public void shift (int from, int to, int errorFlag) { + switch (errorFlag) { + default: // normally + println("shift\tfrom state "+from+" to "+to); + break; + case 0: case 1: case 2: // in error recovery + println("shift\tfrom state "+from+" to "+to + +"\t"+errorFlag+" left to recover"); + break; + case 3: // normally + println("shift\tfrom state "+from+" to "+to+"\ton error"); + break; + } + } + + public void pop (int state) { + println("pop\tstate "+state+"\ton error"); + } + + public void discard (int state, int token, string name, Object value) { + println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value); + } + + public void reduce (int from, int to, int rule, string text, int len) { + println("reduce\tstate "+from+"\tuncover "+to + +"\trule ("+rule+") "+text); + } + + public void shift (int from, int to) { + println("goto\tfrom state "+from+" to "+to); + } + + public void accept (Object value) { + println("accept\tvalue "+value); + } + + public void error (string message) { + println("error\t"+message); + } + + public void reject () { + println("reject"); + } + + } +} +// %token constants + class Token { + public const int EOF = 257; + public const int NONE = 258; + public const int ERROR = 259; + public const int FIRST_KEYWORD = 260; + public const int ABSTRACT = 261; + public const int AS = 262; + public const int ADD = 263; + public const int BASE = 264; + public const int BOOL = 265; + public const int BREAK = 266; + public const int BYTE = 267; + public const int CASE = 268; + public const int CATCH = 269; + public const int CHAR = 270; + public const int CHECKED = 271; + public const int CLASS = 272; + public const int CONST = 273; + public const int CONTINUE = 274; + public const int DECIMAL = 275; + public const int DEFAULT = 276; + public const int DELEGATE = 277; + public const int DO = 278; + public const int DOUBLE = 279; + public const int ELSE = 280; + public const int ENUM = 281; + public const int EVENT = 282; + public const int EXPLICIT = 283; + public const int EXTERN = 284; + public const int FALSE = 285; + public const int FINALLY = 286; + public const int FIXED = 287; + public const int FLOAT = 288; + public const int FOR = 289; + public const int FOREACH = 290; + public const int GOTO = 291; + public const int IF = 292; + public const int IMPLICIT = 293; + public const int IN = 294; + public const int INT = 295; + public const int INTERFACE = 296; + public const int INTERNAL = 297; + public const int IS = 298; + public const int LOCK = 299; + public const int LONG = 300; + public const int NAMESPACE = 301; + public const int NEW = 302; + public const int NULL = 303; + public const int OBJECT = 304; + public const int OPERATOR = 305; + public const int OUT = 306; + public const int OVERRIDE = 307; + public const int PARAMS = 308; + public const int PRIVATE = 309; + public const int PROTECTED = 310; + public const int PUBLIC = 311; + public const int READONLY = 312; + public const int REF = 313; + public const int RETURN = 314; + public const int REMOVE = 315; + public const int SBYTE = 316; + public const int SEALED = 317; + public const int SHORT = 318; + public const int SIZEOF = 319; + public const int STACKALLOC = 320; + public const int STATIC = 321; + public const int STRING = 322; + public const int STRUCT = 323; + public const int SWITCH = 324; + public const int THIS = 325; + public const int THROW = 326; + public const int TRUE = 327; + public const int TRY = 328; + public const int TYPEOF = 329; + public const int UINT = 330; + public const int ULONG = 331; + public const int UNCHECKED = 332; + public const int UNSAFE = 333; + public const int USHORT = 334; + public const int USING = 335; + public const int VIRTUAL = 336; + public const int VOID = 337; + public const int VOLATILE = 338; + public const int WHERE = 339; + public const int WHILE = 340; + public const int ARGLIST = 341; + public const int PARTIAL = 342; + public const int ARROW = 343; + public const int FROM = 344; + public const int FROM_FIRST = 345; + public const int JOIN = 346; + public const int ON = 347; + public const int EQUALS = 348; + public const int SELECT = 349; + public const int GROUP = 350; + public const int BY = 351; + public const int LET = 352; + public const int ORDERBY = 353; + public const int ASCENDING = 354; + public const int DESCENDING = 355; + public const int INTO = 356; + public const int INTERR_NULLABLE = 357; + public const int EXTERN_ALIAS = 358; + public const int REFVALUE = 359; + public const int REFTYPE = 360; + public const int MAKEREF = 361; + public const int ASYNC = 362; + public const int AWAIT = 363; + public const int GET = 364; + public const int SET = 365; + public const int LAST_KEYWORD = 366; + public const int OPEN_BRACE = 367; + public const int CLOSE_BRACE = 368; + public const int OPEN_BRACKET = 369; + public const int CLOSE_BRACKET = 370; + public const int OPEN_PARENS = 371; + public const int CLOSE_PARENS = 372; + public const int DOT = 373; + public const int COMMA = 374; + public const int COLON = 375; + public const int SEMICOLON = 376; + public const int TILDE = 377; + public const int PLUS = 378; + public const int MINUS = 379; + public const int BANG = 380; + public const int ASSIGN = 381; + public const int OP_LT = 382; + public const int OP_GT = 383; + public const int BITWISE_AND = 384; + public const int BITWISE_OR = 385; + public const int STAR = 386; + public const int PERCENT = 387; + public const int DIV = 388; + public const int CARRET = 389; + public const int INTERR = 390; + public const int DOUBLE_COLON = 391; + public const int OP_INC = 392; + public const int OP_DEC = 393; + public const int OP_SHIFT_LEFT = 394; + public const int OP_SHIFT_RIGHT = 395; + public const int OP_LE = 396; + public const int OP_GE = 397; + public const int OP_EQ = 398; + public const int OP_NE = 399; + public const int OP_AND = 400; + public const int OP_OR = 401; + public const int OP_MULT_ASSIGN = 402; + public const int OP_DIV_ASSIGN = 403; + public const int OP_MOD_ASSIGN = 404; + public const int OP_ADD_ASSIGN = 405; + public const int OP_SUB_ASSIGN = 406; + public const int OP_SHIFT_LEFT_ASSIGN = 407; + public const int OP_SHIFT_RIGHT_ASSIGN = 408; + public const int OP_AND_ASSIGN = 409; + public const int OP_XOR_ASSIGN = 410; + public const int OP_OR_ASSIGN = 411; + public const int OP_PTR = 412; + public const int OP_COALESCING = 413; + public const int OP_GENERICS_LT = 414; + public const int OP_GENERICS_LT_DECL = 415; + public const int OP_GENERICS_GT = 416; + public const int LITERAL = 417; + public const int IDENTIFIER = 418; + public const int OPEN_PARENS_LAMBDA = 419; + public const int OPEN_PARENS_CAST = 420; + public const int GENERIC_DIMENSION = 421; + public const int DEFAULT_COLON = 422; + public const int OPEN_BRACKET_EXPR = 423; + public const int EVAL_STATEMENT_PARSER = 424; + public const int EVAL_COMPILATION_UNIT_PARSER = 425; + public const int EVAL_USING_DECLARATIONS_UNIT_PARSER = 426; + public const int DOC_SEE = 427; + public const int GENERATE_COMPLETION = 428; + public const int COMPLETE_COMPLETION = 429; + public const int UMINUS = 430; + public const int yyErrorCode = 256; + } + namespace yyParser { + using System; + /** thrown for irrecoverable syntax errors and stack overflow. + */ + internal class yyException : System.Exception { + public yyException (string message) : base (message) { + } + } + internal class yyUnexpectedEof : yyException { + public yyUnexpectedEof (string message) : base (message) { + } + public yyUnexpectedEof () : base ("") { + } + } + + /** must be implemented by a scanner object to supply input to the parser. + */ + internal interface yyInput { + /** move on to next token. + @return false if positioned beyond tokens. + @throws IOException on input error. + */ + bool advance (); // throws java.io.IOException; + /** classifies current token. + Should not be called if advance() returned false. + @return current %token or single character. + */ + int token (); + /** associated with current token. + Should not be called if advance() returned false. + @return value for token(). + */ + Object value (); + } + } +} // close outermost namespace, that MUST HAVE BEEN opened in the prolog diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay new file mode 100644 index 0000000000..5e6f9e9095 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -0,0 +1,7108 @@ +%{ +// +// cs-parser.jay: The Parser for the C# compiler +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual Licensed under the terms of the GNU GPL and the MIT X11 license +// +// (C) 2001 Ximian, Inc (http://www.ximian.com) +// (C) 2004 Novell, Inc +// +// TODO: +// (1) Figure out why error productions dont work. `type-declaration' is a +// great spot to put an `error' because you can reproduce it with this input: +// "public X { }" +// + +using System.Text; +using System.IO; +using System; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + /// + /// The C# Parser + /// + public class CSharpParser + { + [Flags] + enum ParameterModifierType + { + Ref = 1 << 1, + Out = 1 << 2, + This = 1 << 3, + Params = 1 << 4, + Arglist = 1 << 5, + DefaultValue = 1 << 6, + + All = Ref | Out | This | Params | Arglist | DefaultValue + } + + static readonly object ModifierNone = 0; + + NamespaceContainer current_namespace; + TypeContainer current_container; + DeclSpace current_class; + PropertyBase current_property; + EventProperty current_event; + EventField current_event_field; + FieldBase current_field; + + /// + /// Current block is used to add statements as we find + /// them. + /// + Block current_block; + + BlockVariableDeclaration current_variable; + + Delegate current_delegate; + + AnonymousMethodExpression current_anonymous_method; + + /// + /// This is used by the unary_expression code to resolve + /// a name against a parameter. + /// + + // FIXME: This is very ugly and it's very hard to reset it correctly + // on all places, especially when some parameters are autogenerated. + ParametersCompiled current_local_parameters; + + bool parsing_anonymous_method; + + /// + /// An out-of-band stack. + /// + static Stack oob_stack; + + /// + /// Controls the verbosity of the errors produced by the parser + /// + static public int yacc_verbose_flag; + + /// + /// Used by the interactive shell, flags whether EOF was reached + /// and an error was produced + /// + public bool UnexpectedEOF; + + /// + /// The current file. + /// + readonly CompilationSourceFile file; + + /// + /// Temporary Xml documentation cache. + /// For enum types, we need one more temporary store. + /// + string tmpComment; + string enumTypeComment; + + /// Current attribute target + string current_attr_target; + + ParameterModifierType valid_param_mod; + + bool default_parameter_used; + + /// When using the interactive parser, this holds the + /// resulting expression + public Class InteractiveResult; + + // + // Keeps track of global data changes to undo on parser error + // + public Undo undo; + + Stack linq_clause_blocks; + + ModuleContainer module; + + readonly CompilerContext compiler; + readonly LanguageVersion lang_version; + readonly bool doc_support; + readonly CompilerSettings settings; + readonly Report report; + + // + // Instead of allocating carrier array everytime we + // share the bucket for very common constructs which can never + // be recursive + // + static List parameters_bucket = new List (6); + + // + // Full AST support members + // + LocationsBag lbag; + UsingsBag ubag; + List> mod_locations; + Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Stack> locationListStack = new Stack> (); // used for type parameters + + object lastYYVal; + + // Can be used for code completion to get the last valid expression before an error. + // needs a hack in yyparse to make it work add + // lastYYVal = yyVal; + // after the big switch/case (somewhere around line 3915) + public object LastYYVal { + get { + return lastYYVal; + } + } + +%} + +%token EOF +%token NONE /* This token is never returned by our lexer */ +%token ERROR // This is used not by the parser, but by the tokenizer. + // do not remove. + +/* + *These are the C# keywords + */ +%token FIRST_KEYWORD +%token ABSTRACT +%token AS +%token ADD +%token BASE +%token BOOL +%token BREAK +%token BYTE +%token CASE +%token CATCH +%token CHAR +%token CHECKED +%token CLASS +%token CONST +%token CONTINUE +%token DECIMAL +%token DEFAULT +%token DELEGATE +%token DO +%token DOUBLE +%token ELSE +%token ENUM +%token EVENT +%token EXPLICIT +%token EXTERN +%token FALSE +%token FINALLY +%token FIXED +%token FLOAT +%token FOR +%token FOREACH +%token GOTO +%token IF +%token IMPLICIT +%token IN +%token INT +%token INTERFACE +%token INTERNAL +%token IS +%token LOCK +%token LONG +%token NAMESPACE +%token NEW +%token NULL +%token OBJECT +%token OPERATOR +%token OUT +%token OVERRIDE +%token PARAMS +%token PRIVATE +%token PROTECTED +%token PUBLIC +%token READONLY +%token REF +%token RETURN +%token REMOVE +%token SBYTE +%token SEALED +%token SHORT +%token SIZEOF +%token STACKALLOC +%token STATIC +%token STRING +%token STRUCT +%token SWITCH +%token THIS +%token THROW +%token TRUE +%token TRY +%token TYPEOF +%token UINT +%token ULONG +%token UNCHECKED +%token UNSAFE +%token USHORT +%token USING +%token VIRTUAL +%token VOID +%token VOLATILE +%token WHERE +%token WHILE +%token ARGLIST +%token PARTIAL +%token ARROW +%token FROM +%token FROM_FIRST +%token JOIN +%token ON +%token EQUALS +%token SELECT +%token GROUP +%token BY +%token LET +%token ORDERBY +%token ASCENDING +%token DESCENDING +%token INTO +%token INTERR_NULLABLE +%token EXTERN_ALIAS +%token REFVALUE +%token REFTYPE +%token MAKEREF +%token ASYNC +%token AWAIT + +/* C# keywords which are not really keywords */ +%token GET +%token SET + +%left LAST_KEYWORD + +/* C# single character operators/punctuation. */ +%token OPEN_BRACE +%token CLOSE_BRACE +%token OPEN_BRACKET +%token CLOSE_BRACKET +%token OPEN_PARENS +%token CLOSE_PARENS + +%token DOT +%token COMMA +%token COLON +%token SEMICOLON +%token TILDE + +%token PLUS +%token MINUS +%token BANG +%token ASSIGN +%token OP_LT +%token OP_GT +%token BITWISE_AND +%token BITWISE_OR +%token STAR +%token PERCENT +%token DIV +%token CARRET +%token INTERR + +/* C# multi-character operators. */ +%token DOUBLE_COLON +%token OP_INC +%token OP_DEC +%token OP_SHIFT_LEFT +%token OP_SHIFT_RIGHT +%token OP_LE +%token OP_GE +%token OP_EQ +%token OP_NE +%token OP_AND +%token OP_OR +%token OP_MULT_ASSIGN +%token OP_DIV_ASSIGN +%token OP_MOD_ASSIGN +%token OP_ADD_ASSIGN +%token OP_SUB_ASSIGN +%token OP_SHIFT_LEFT_ASSIGN +%token OP_SHIFT_RIGHT_ASSIGN +%token OP_AND_ASSIGN +%token OP_XOR_ASSIGN +%token OP_OR_ASSIGN +%token OP_PTR +%token OP_COALESCING + +/* Generics <,> tokens */ +%token OP_GENERICS_LT +%token OP_GENERICS_LT_DECL +%token OP_GENERICS_GT + +%token LITERAL + +%token IDENTIFIER +%token OPEN_PARENS_LAMBDA +%token OPEN_PARENS_CAST +%token GENERIC_DIMENSION +%token DEFAULT_COLON +%token OPEN_BRACKET_EXPR + +// Make the parser go into eval mode parsing (statements and compilation units). +%token EVAL_STATEMENT_PARSER +%token EVAL_COMPILATION_UNIT_PARSER +%token EVAL_USING_DECLARATIONS_UNIT_PARSER + +%token DOC_SEE + +// +// This token is generated to trigger the completion engine at this point +// +%token GENERATE_COMPLETION + +// +// This token is return repeatedly after the first GENERATE_COMPLETION +// token is produced and before the final EOF +// +%token COMPLETE_COMPLETION + +/* Add precedence rules to solve dangling else s/r conflict */ +%nonassoc IF +%nonassoc ELSE + +/* Define the operator tokens and their precedences */ +%right ASSIGN +%right OP_COALESCING +%right INTERR +%left OP_OR +%left OP_AND +%left BITWISE_OR +%left BITWISE_AND +%left OP_SHIFT_LEFT OP_SHIFT_RIGHT +%left PLUS MINUS +%left STAR DIV PERCENT +%right BANG CARRET UMINUS +%nonassoc OP_INC OP_DEC +%left OPEN_PARENS +%left OPEN_BRACKET OPEN_BRACE +%left DOT + +%start compilation_unit +%% + +compilation_unit + : outer_declaration opt_EOF + { + Lexer.check_incorrect_doc_comment (); + } + | interactive_parsing { Lexer.CompleteOnEOF = false; } opt_EOF + | documentation_parsing + ; + +outer_declaration + : opt_extern_alias_directives opt_using_directives + | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes + { + if ($4 != null) { + Attributes attrs = (Attributes) $4; + report.Error (1730, attrs.Attrs [0].Location, + "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); + } + } + | opt_extern_alias_directives opt_using_directives attribute_sections + { + module.AddAttributes ((Attributes) $3, current_namespace); + } + | error + { + if (yyToken == Token.EXTERN_ALIAS) + report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); + else + Error_SyntaxError (yyToken); + } + ; + +opt_EOF + : /* empty */ + | EOF + ; + +extern_alias_directives + : extern_alias_directive + | extern_alias_directives extern_alias_directive + ; + +extern_alias_directive + : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + string s = lt.Value; + if (s != "alias"){ + syntax_error (lt.Location, "`alias' expected"); + } else if (lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (lt.Location, "external alias"); + } else { + lt = (Tokenizer.LocatedToken) $3; + current_namespace.AddUsingExternalAlias (lt.Value, lt.Location, report); + ubag.AddExternAlias (GetLocation ($1), GetLocation ($2), lt, GetLocation ($4)); + } + } + | EXTERN_ALIAS error + { + syntax_error (GetLocation ($1), "`alias' expected"); // TODO: better + } + ; + +using_directives + : using_directive + | using_directives using_directive + ; + +using_directive + : using_alias_directive + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + | using_namespace_directive + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +using_alias_directive + : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { + report.Warning (440, 2, lt.Location, + "An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); + } + + current_namespace.AddUsingAlias (lt.Value, (MemberName) $4, GetLocation ($1)); + ubag.AddUsingAlias (GetLocation ($1), lt, GetLocation ($3), (MemberName) $4, GetLocation ($5)); + } + | USING error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +using_namespace_directive + : USING namespace_name SEMICOLON + { + current_namespace.AddUsing ((MemberName) $2, GetLocation ($1)); + ubag.AddUsing (GetLocation ($1), (MemberName) $2, GetLocation ($3)); + } + ; + +// +// Strictly speaking, namespaces don't have attributes but +// we parse global attributes along with namespace declarations and then +// detach them +// +namespace_declaration + : opt_attributes NAMESPACE qualified_identifier + { + Attributes attrs = (Attributes) $1; + MemberName name = (MemberName) $3; + if (attrs != null) { + bool valid_global_attrs = true; + if ((current_namespace.DeclarationFound || current_namespace != file.NamespaceContainer)) { + valid_global_attrs = false; + } else { + foreach (var a in attrs.Attrs) { + if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") + continue; + + valid_global_attrs = false; + break; + } + } + + if (!valid_global_attrs) + report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); + } + + module.AddAttributes (attrs, current_namespace); + + current_namespace = new NamespaceContainer (name, module, current_namespace, file); + module.AddTypesContainer (current_namespace); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + + ubag.DeclareNamespace (GetLocation ($2), name); + } + OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + ubag.OpenNamespace (GetLocation ($5)); + } + opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon + { + if ($11 != null) + lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); + else + lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10)); + + current_namespace = current_namespace.Parent; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + ubag.CloseNamespace (GetLocation ($10)); + ubag.EndNamespace (GetLocation ($10)); + } + ; + +qualified_identifier + : IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, lt.Location); + } + | qualified_identifier DOT IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location); + } + | error + { + Error_SyntaxError (yyToken); + $$ = new MemberName ("", lexer.Location); + } + ; + +opt_semicolon + : /* empty */ + | SEMICOLON + ; + +opt_comma + : /* empty */ + | COMMA + ; + +namespace_name + : namespace_or_type_name + { + MemberName name = (MemberName) $1; + + if (name.TypeArguments != null) + syntax_error (lexer.Location, "namespace name expected"); + + $$ = name; + } + ; + +opt_using_directives + : /* empty */ + | using_directives + ; + +opt_extern_alias_directives + : /* empty */ + | extern_alias_directives + ; + +opt_namespace_or_type_declarations + : /* empty */ + | namespace_or_type_declarations + ; + +namespace_or_type_declarations + : namespace_or_type_declaration + | namespace_or_type_declarations namespace_or_type_declaration + ; + +namespace_or_type_declaration + : type_declaration + { + if ($1 != null) { + TypeContainer ds = (TypeContainer)$1; + + if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ + report.Error (1527, ds.Location, + "Namespace elements cannot be explicitly declared as private, protected or protected internal"); + } + + // Here is a trick, for explicit attributes we don't know where they belong to until + // we parse succeeding declaration hence we parse them as normal and re-attach them + // when we know whether they are global (assembly:, module:) or local (type:). + if (ds.OptAttributes != null) { + ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file.NamespaceContainer); + } + } + current_namespace.DeclarationFound = true; + } + | namespace_declaration + { + current_namespace.DeclarationFound = true; + } + ; + +type_declaration + : class_declaration + | struct_declaration + | interface_declaration + | enum_declaration + | delegate_declaration +// +// Enable this when we have handled all errors, because this acts as a generic fallback +// +// | error { +// Console.WriteLine ("Token=" + yyToken); +// report.Error (1518, GetLocation ($1), "Expected class, struct, interface, enum or delegate"); +// } + ; + +// +// Attributes +// + +opt_attributes + : /* empty */ + | attribute_sections + ; + +attribute_sections + : attribute_section + { + var sect = (List) $1; + $$ = new Attributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + } + | attribute_sections attribute_section + { + Attributes attrs = $1 as Attributes; + var sect = (List) $2; + if (attrs == null) + attrs = new Attributes (sect); + else + attrs.AddAttributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + $$ = attrs; + } + ; + +attribute_section + : OPEN_BRACKET + { + lexer.parsing_attribute_section = true; + savedOpenLocation = GetLocation ($1); + } + attribute_section_cont + { + lexer.parsing_attribute_section = false; + $$ = $3; + } + ; + +attribute_section_cont + : attribute_target COLON + { + current_attr_target = (string) $1; + if (current_attr_target == "assembly" || current_attr_target == "module") { + Lexer.check_incorrect_doc_comment (); + } + } + attribute_list opt_comma CLOSE_BRACKET + { + // when attribute target is invalid + if (current_attr_target == string.Empty) + $$ = new List (0); + else + $$ = $4; + + current_attr_target = null; + lexer.parsing_attribute_section = false; + savedCloseLocation = GetLocation ($6); + } + | attribute_list opt_comma CLOSE_BRACKET + { + $$ = $1; + savedCloseLocation = GetLocation ($3); + } + ; + +attribute_target + : IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = CheckAttributeTarget (lt.Value, lt.Location); + } + | EVENT { $$ = "event"; } + | RETURN { $$ = "return"; } + | error + { + if (yyToken == Token.IDENTIFIER) { + Error_SyntaxError (yyToken); + $$ = null; + } else { + string name = GetTokenName (yyToken); + $$ = CheckAttributeTarget (name, GetLocation ($1)); + } + } + ; + +attribute_list + : attribute + { + $$ = new List (4) { (Attribute) $1 }; + } + | attribute_list COMMA attribute + { + var attrs = (List) $1; + attrs.Add ((Attribute) $3); + + $$ = attrs; + } + ; + +attribute + : attribute_name + { + ++lexer.parsing_block; + } + opt_attribute_arguments + { + --lexer.parsing_block; + MemberName mname = (MemberName) $1; + if (mname.IsGeneric) { + report.Error (404, lexer.Location, + "'<' unexpected: attributes cannot be generic"); + } + + Arguments [] arguments = (Arguments []) $3; + ATypeNameExpression expr = mname.GetTypeExpression (); + $$ = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); + if (arguments != null) { + lbag.AddLocation ($$, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + } + } + ; + +attribute_name + : namespace_or_type_name + ; + +opt_attribute_arguments + : /* empty */ { $$ = null; } + | OPEN_PARENS attribute_arguments CLOSE_PARENS + { + savedAttrParenOpenLocation = GetLocation ($1); + savedAttrParenCloseLocation = GetLocation ($3); + $$ = $2; + } + ; + + +attribute_arguments + : /* empty */ { $$ = null; } + | positional_or_named_argument + { + Arguments a = new Arguments (4); + a.Add ((Argument) $1); + $$ = new Arguments [] { a, null }; + } + | named_attribute_argument + { + Arguments a = new Arguments (4); + a.Add ((Argument) $1); + $$ = new Arguments [] { null, a }; + } + | attribute_arguments COMMA positional_or_named_argument + { + Arguments[] o = (Arguments[]) $1; + if (o [1] != null) { + report.Error (1016, ((Argument) $3).Expr.Location, "Named attribute arguments must appear after the positional arguments"); + o [0] = new Arguments (4); + } + + Arguments args = ((Arguments) o [0]); + if (args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) $3); + lbag.AppendTo (args, GetLocation ($2)); + } + | attribute_arguments COMMA named_attribute_argument + { + Arguments[] o = (Arguments[]) $1; + if (o [1] == null) { + o [1] = new Arguments (4); + } + + ((Arguments) o [1]).Add ((Argument) $3); + lbag.AppendTo (o[1], GetLocation ($2)); + } + ; + +positional_or_named_argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | named_argument + ; + +named_attribute_argument + : IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + expression + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $1; + $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4); + lbag.AddLocation ($$, GetLocation($2)); + } + ; + +named_argument + : IDENTIFIER COLON opt_named_modifier expression + { + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (GetLocation ($1), "named argument"); + + // Avoid boxing in common case (no modifier) + var arg_mod = $3 == null ? Argument.AType.None : (Argument.AType) $3; + + var lt = (Tokenizer.LocatedToken) $1; + $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod); + } + ; + +opt_named_modifier + : /* empty */ { $$ = null; } + | REF + { + $$ = Argument.AType.Ref; + } + | OUT + { + $$ = Argument.AType.Out; + } + ; + +opt_class_member_declarations + : /* empty */ + | class_member_declarations + ; + +class_member_declarations + : class_member_declaration + | class_member_declarations + class_member_declaration + ; + +class_member_declaration + : constant_declaration + | field_declaration + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + | constructor_declaration + | destructor_declaration + | type_declaration + | error + { + report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", + GetSymbolName (yyToken)); + $$ = null; + lexer.parsing_generic_declaration = false; + } + ; + +struct_declaration + : opt_attributes + opt_modifiers + opt_partial + STRUCT + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + + if (doc_support) + current_container.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + } + struct_body + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($13)); + $$ = pop_current_class (); + } + | opt_attributes opt_modifiers opt_partial STRUCT error + { + Error_SyntaxError (yyToken); + } + ; + +struct_body + : OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_struct_member_declarations CLOSE_BRACE + { + lbag.AppendToMember (current_class, GetLocation ($1), GetLocation ($4)); + } + ; + +opt_struct_member_declarations + : /* empty */ + | struct_member_declarations + ; + +struct_member_declarations + : struct_member_declaration + | struct_member_declarations struct_member_declaration + ; + +struct_member_declaration + : constant_declaration + | field_declaration + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + | constructor_declaration + | type_declaration + + /* + * This is only included so we can flag error 575: + * destructors only allowed on class types + */ + | destructor_declaration + ; + +constant_declaration + : opt_attributes + opt_modifiers + CONST type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $5; + var mod = (Modifiers) $2; + current_field = new Const (current_class, (FullNamedExpression) $4, mod, new MemberName (lt.Value, lt.Location), (Attributes) $1); + current_container.AddConstant ((Const) current_field); + + if ((mod & Modifiers.STATIC) != 0) { + report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); + } + + $$ = current_field; + } + constant_initializer opt_constant_declarators SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) $7; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + current_field = null; + } + ; + +opt_constant_declarators + : /* empty */ + | constant_declarators + ; + +constant_declarators + : constant_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | constant_declarators constant_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +constant_declarator + : COMMA IDENTIFIER constant_initializer + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); + lbag.AddLocation ($$, GetLocation ($1)); + } + ; + +constant_initializer + : ASSIGN + { + ++lexer.parsing_block; + } + constant_initializer_expr + { + --lexer.parsing_block; + $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($1)); + } + | error + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + $$ = null; + } + ; + +constant_initializer_expr + : constant_expression + | array_initializer + ; + +field_declaration + : opt_attributes + opt_modifiers + member_type IDENTIFIER + { + lexer.parsing_generic_declaration = false; + + FullNamedExpression type = (FullNamedExpression) $3; + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (670, GetLocation ($3), "Fields cannot have void type"); + + var lt = (Tokenizer.LocatedToken) $4; + current_field = new Field (current_class, type, (Modifiers) $2, new MemberName (lt.Value, lt.Location), (Attributes) $1); + current_container.AddField (current_field); + $$ = current_field; + } + opt_field_initializer + opt_field_declarators + SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($8)); + $$ = current_field; + current_field = null; + } + | opt_attributes + opt_modifiers + FIXED simple_type IDENTIFIER + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($3), "fixed size buffers"); + + var lt = (Tokenizer.LocatedToken) $5; + current_field = new FixedField (current_class, (FullNamedExpression) $4, (Modifiers) $2, + new MemberName (lt.Value, lt.Location), (Attributes) $1); + + current_container.AddField (current_field); + } + fixed_field_size opt_fixed_field_declarators SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) $7; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + $$ = current_field; + current_field = null; + } + | opt_attributes + opt_modifiers + FIXED simple_type error + SEMICOLON + { + report.Error (1641, GetLocation ($5), "A fixed size buffer field must have the array size specifier after the field name"); + } + ; + +opt_field_initializer + : /* empty */ + | ASSIGN + { + ++lexer.parsing_block; + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + start_block (GetLocation ($1)); + } + variable_initializer + { + --lexer.parsing_block; + current_field.Initializer = (Expression) $3; + lbag.AppendToMember (current_field, GetLocation ($1)); + end_block (lexer.Location); + current_local_parameters = null; + } + ; + +opt_field_declarators + : /* empty */ + | field_declarators + ; + +field_declarators + : field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | field_declarators field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +field_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation ($$, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + variable_initializer + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +opt_fixed_field_declarators + : /* empty */ + | fixed_field_declarators + ; + +fixed_field_declarators + : fixed_field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | fixed_field_declarators fixed_field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +fixed_field_declarator + : COMMA IDENTIFIER fixed_field_size + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); + lbag.AddLocation ($$, GetLocation ($1)); + } + ; + +fixed_field_size + : OPEN_BRACKET + { + ++lexer.parsing_block; + } + expression CLOSE_BRACKET + { + --lexer.parsing_block; + $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($4)); + } + | OPEN_BRACKET error + { + report.Error (443, lexer.Location, "Value or constant expected"); + $$ = null; + } + ; + +variable_initializer + : expression + | array_initializer + | error + { + // It has to be here for the parent to safely restore artificial block + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +method_declaration + : method_header + { + if (doc_support) + Lexer.doc_state = XmlCommentState.NotAllowed; + + // Add it early in the case of body being eof for full aot + current_container.AddMethod ((Method) $1); + } + method_body + { + Method method = (Method) $1; + method.Block = (ToplevelBlock) $3; + + if (method.Block == null) { + method.ParameterInfo.CheckParameters (method); + + if ((method.ModFlags & Modifiers.ASYNC) != 0) { + report.Error (1994, method.Location, "`{0}': The async modifier can only be used with methods that have a body", + method.GetSignatureForError ()); + } + } else { + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, method.Location, "`{0}': interface members cannot have a definition", + method.GetSignatureForError ()); + } + } + + current_local_parameters = null; + + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +method_header + : opt_attributes + opt_modifiers + member_type + method_declaration_name OPEN_PARENS + { + valid_param_mod = ParameterModifierType.All; + } + opt_formal_parameter_list CLOSE_PARENS + { + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + MemberName name = (MemberName) $4; + current_local_parameters = (ParametersCompiled) $7; + + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + (FullNamedExpression) $3, current_local_parameters); + + generic.SetParameterInfo ((List) $10); + } else if ($10 != null) { + report.Error (80, GetLocation ($10), + "Constraints are not allowed on non-generic declarations"); + } + + Method method = new Method (current_class, generic, (FullNamedExpression) $3, (Modifiers) $2, + name, current_local_parameters, (Attributes) $1); + + if ($10 != null && ((method.ModFlags & Modifiers.OVERRIDE) != 0 || method.IsExplicitImpl)) { + report.Error (460, method.Location, + "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods", + method.GetSignatureForError ()); + } + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (method, GetModifierLocations (), GetLocation ($5), GetLocation ($8)); + $$ = method; + } + | opt_attributes + opt_modifiers + PARTIAL + VOID + { + lexer.parsing_generic_declaration = true; + } + method_declaration_name + OPEN_PARENS + { + lexer.parsing_generic_declaration = false; + valid_param_mod = ParameterModifierType.All; + } + opt_formal_parameter_list CLOSE_PARENS + { + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + + MemberName name = (MemberName) $6; + current_local_parameters = (ParametersCompiled) $9; + + if ($11 != null && name.TypeArguments == null) + report.Error (80, lexer.Location, + "Constraints are not allowed on non-generic declarations"); + + Method method; + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)), + current_local_parameters); + + generic.SetParameterInfo ((List) $11); + } + + var modifiers = (Modifiers) $2; + + const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN | + Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL; + + if ((modifiers & invalid_partial_mod) != 0) { + report.Error (750, name.Location, "A partial method cannot define access modifier or " + + "any of abstract, extern, new, override, sealed, or virtual modifiers"); + modifiers &= ~invalid_partial_mod; + } + + if ((current_class.ModFlags & Modifiers.PARTIAL) == 0) { + report.Error (751, name.Location, "A partial method must be declared within a " + + "partial class or partial struct"); + } + + modifiers |= Modifiers.PARTIAL | Modifiers.PRIVATE; + + method = new Method (current_class, generic, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)), + modifiers, name, current_local_parameters, (Attributes) $1); + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($3)); + lbag.AddMember (method, mod_locations, GetLocation ($7), GetLocation ($10)); + $$ = method; + } + | opt_attributes + opt_modifiers + member_type + modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + MemberName name = (MemberName) $5; + report.Error (1585, name.Location, + "Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) $4)); + + Method method = new Method (current_class, null, (FullNamedExpression) $3, + 0, name, (ParametersCompiled) $7, (Attributes) $1); + + current_local_parameters = (ParametersCompiled) $7; + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + $$ = method; + } + ; + +method_body + : block + | SEMICOLON { $$ = null; } + ; + +opt_formal_parameter_list + : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } + | formal_parameter_list + ; + +formal_parameter_list + : fixed_parameters + { + var pars_list = (List) $1; + $$ = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation ($$, lbag.GetLocations (pars_list)); + } + | fixed_parameters COMMA parameter_array + { + var pars_list = (List) $1; + pars_list.Add ((Parameter) $3); + + $$ = new ParametersCompiled (pars_list.ToArray ()); + } + | fixed_parameters COMMA arglist_modifier + { + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | parameter_array COMMA error + { + if ($1 != null) + report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); + + $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); + } + | fixed_parameters COMMA parameter_array COMMA error + { + if ($3 != null) + report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | arglist_modifier COMMA error + { + report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list"); + + $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); + } + | fixed_parameters COMMA ARGLIST COMMA error + { + report.Error (257, GetLocation ($3), "An __arglist parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | parameter_array + { + $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); + } + | arglist_modifier + { + $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); + } + | error + { + Error_SyntaxError (yyToken); + $$ = ParametersCompiled.EmptyReadOnlyParameters; + } + ; + +fixed_parameters + : fixed_parameter + { + parameters_bucket.Clear (); + Parameter p = (Parameter) $1; + parameters_bucket.Add (p); + + default_parameter_used = p.HasDefaultValue; + $$ = parameters_bucket; + } + | fixed_parameters COMMA fixed_parameter + { + var pars = (List) $1; + Parameter p = (Parameter) $3; + if (p != null) { + if (p.HasExtensionMethodModifier) + report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); + else if (!p.HasDefaultValue && default_parameter_used) + report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); + + default_parameter_used |= p.HasDefaultValue; + pars.Add (p); + + lbag.AppendTo (pars, GetLocation ($2)); + } + + $$ = $1; + } + ; + +fixed_parameter + : opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $4; + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + { + var lt = (Tokenizer.LocatedToken) $4; + report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + error + { + Error_SyntaxError (yyToken); + Location l = GetLocation ($4); + $$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER + ASSIGN + { + ++lexer.parsing_block; + } + constant_expression + { + --lexer.parsing_block; + if (lang_version <= LanguageVersion.V_3) { + FeatureIsNotAvailable (GetLocation ($5), "optional parameter"); + } + + Parameter.Modifier mod = (Parameter.Modifier) $2; + if (mod != Parameter.Modifier.NONE) { + switch (mod) { + case Parameter.Modifier.REF: + case Parameter.Modifier.OUT: + report.Error (1741, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + + case Parameter.Modifier.This: + report.Error (1743, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + default: + throw new NotImplementedException (mod.ToString ()); + } + + mod = Parameter.Modifier.NONE; + } + + if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) + report.Error (1065, GetLocation ($5), "Optional parameter is not valid in this context"); + + var lt = (Tokenizer.LocatedToken) $4; + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, mod, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation, GetLocation ($5)); // parameterModifierLocation should be ignored when mod == NONE + + if ($7 != null) + ((Parameter) $$).DefaultValue = new DefaultParameterValueExpression ((Expression) $7); + } + ; + +opt_parameter_modifier + : /* empty */ { $$ = Parameter.Modifier.NONE; } + | parameter_modifiers + ; + +parameter_modifiers + : parameter_modifier + { + $$ = $1; + parameterModifierLocation = GetLocation ($1); + } + | parameter_modifiers parameter_modifier + { + Parameter.Modifier p2 = (Parameter.Modifier)$2; + Parameter.Modifier mod = (Parameter.Modifier)$1 | p2; + if (((Parameter.Modifier)$1 & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); + } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); + break; + case Parameter.Modifier.OUT: + report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); + break; + default: + report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); + break; + } + } + $$ = mod; + } + ; + +parameter_modifier + : REF + { + if ((valid_param_mod & ParameterModifierType.Ref) == 0) + Error_ParameterModifierNotValid ("ref", GetLocation ($1)); + + $$ = Parameter.Modifier.REF; + } + | OUT + { + if ((valid_param_mod & ParameterModifierType.Out) == 0) + Error_ParameterModifierNotValid ("out", GetLocation ($1)); + + $$ = Parameter.Modifier.OUT; + } + | THIS + { + if ((valid_param_mod & ParameterModifierType.This) == 0) + Error_ParameterModifierNotValid ("this", GetLocation ($1)); + + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "extension methods"); + + $$ = Parameter.Modifier.This; + } + ; + +parameter_array + : opt_attributes params_modifier type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $4; + $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + } + | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression + { + report.Error (1751, GetLocation ($2), "Cannot specify a default value for a parameter array"); + + var lt = (Tokenizer.LocatedToken) $4; + $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + } + | opt_attributes params_modifier type error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +params_modifier + : PARAMS + { + if ((valid_param_mod & ParameterModifierType.Params) == 0) + report.Error (1670, (GetLocation ($1)), "The `params' modifier is not allowed in current context"); + } + | PARAMS parameter_modifier + { + Parameter.Modifier mod = (Parameter.Modifier)$2; + if ((mod & Parameter.Modifier.This) != 0) { + report.Error (1104, GetLocation ($1), "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { + report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); + } + } + | PARAMS params_modifier + { + Error_DuplicateParameterModifier (GetLocation ($1), Parameter.Modifier.PARAMS); + } + ; + +arglist_modifier + : ARGLIST + { + if ((valid_param_mod & ParameterModifierType.Arglist) == 0) + report.Error (1669, GetLocation ($1), "__arglist is not valid in this context"); + } + ; + +property_declaration + : opt_attributes + opt_modifiers + member_type + member_declaration_name + { + if (doc_support) + tmpComment = Lexer.consume_doc_comment (); + } + OPEN_BRACE + { + var type = (FullNamedExpression) $3; + current_property = new Property (current_class, type, (Modifiers) $2, + (MemberName) $4, (Attributes) $1); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (547, GetLocation ($3), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); + + current_container.AddProperty ((Property)current_property); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($6)); + + lexer.PropertyParsing = true; + } + accessor_declarations + { + lexer.PropertyParsing = false; + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + } + CLOSE_BRACE + { + lbag.AppendToMember (current_property, GetLocation ($10)); + current_property = null; + } + ; + + +indexer_declaration + : opt_attributes opt_modifiers + member_type indexer_declaration_name OPEN_BRACKET + { + valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE + { + valid_param_mod = 0; + var type = (FullNamedExpression) $3; + Indexer indexer = new Indexer (current_class, type, (MemberName) $4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1); + + current_property = indexer; + + current_container.AddIndexer (indexer); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($5), GetLocation ($8), GetLocation ($9)); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (620, GetLocation ($3), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); + + if (indexer.ParameterInfo.IsEmpty) { + report.Error (1551, GetLocation ($5), "Indexers must have at least one parameter"); + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lexer.PropertyParsing = true; + } + accessor_declarations + { + lexer.PropertyParsing = false; + } + CLOSE_BRACE + { + if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) + ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + + lbag.AppendToMember (current_property, GetLocation ($12)); + current_property = null; + } + ; + + +accessor_declarations + : get_accessor_declaration + | get_accessor_declaration accessor_declarations + | set_accessor_declaration + | set_accessor_declaration accessor_declarations + | error + { + if (yyToken == Token.CLOSE_BRACE) { + report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); + } else { + if (yyToken == Token.SEMICOLON) + report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); + else + report.Error (1014, GetLocation ($1), "A get or set accessor expected"); + } + } + ; + +get_accessor_declaration + : opt_attributes opt_modifiers GET + { + if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); + } + + if (current_property.Get != null) { + report.Error (1007, GetLocation ($3), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) $2, ((Indexer)current_property).ParameterInfo.Clone (), + (Attributes) $1, GetLocation ($3)); + } else { + current_property.Get = new Property.GetMethod (current_property, + (Modifiers) $2, (Attributes) $1, GetLocation ($3)); + } + + current_local_parameters = current_property.Get.ParameterInfo; + lbag.AddMember (current_property.Get, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + accessor_body + { + if ($5 != null) { + current_property.Get.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Get.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support) + if (Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + ; + +set_accessor_declaration + : opt_attributes opt_modifiers SET + { + if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); + } + + if (current_property.Set != null) { + report.Error (1007, GetLocation ($3), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) $2, + ParametersCompiled.MergeGenerated (compiler, + ((Indexer)current_property).ParameterInfo, true, new Parameter ( + current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation ($3)), + null), + (Attributes) $1, GetLocation ($3)); + } else { + current_property.Set = new Property.SetMethod (current_property, (Modifiers) $2, + ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation ($3)), + (Attributes) $1, GetLocation ($3)); + } + + current_local_parameters = current_property.Set.ParameterInfo; + lbag.AddMember (current_property.Set, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + accessor_body + { + if ($5 != null) { + current_property.Set.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Set.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support + && Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + ; + +accessor_body + : block + | SEMICOLON + { + lbag.AppendToMember (lbag.LastMember, GetLocation ($1)); + $$ = null; + } + | error + { + Error_SyntaxError (1043, yyToken, "Invalid accessor body"); + $$ = null; + } + ; + +interface_declaration + : opt_attributes + opt_modifiers + opt_partial + INTERFACE + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); + $$ = pop_current_class (); + } + | opt_attributes opt_modifiers opt_partial INTERFACE error + { + Error_SyntaxError (yyToken); + } + ; + +opt_interface_member_declarations + : /* empty */ + | interface_member_declarations + ; + +interface_member_declarations + : interface_member_declaration + | interface_member_declarations interface_member_declaration + ; + +interface_member_declaration + : constant_declaration + { + report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); + } + | field_declaration + { + report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); + } + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + { + report.Error (567, GetLocation ($1), "Interfaces cannot contain operators"); + } + | constructor_declaration + { + report.Error (526, GetLocation ($1), "Interfaces cannot contain contructors"); + } + | type_declaration + { + report.Error (524, GetLocation ($1), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); + } + ; + +operator_declaration + : opt_attributes opt_modifiers operator_declarator + { + } + operator_body + { + OperatorDeclaration decl = (OperatorDeclaration) $3; + if (decl != null) { + Operator op = new Operator ( + current_class, decl.optype, decl.ret_type, (Modifiers) $2, + current_local_parameters, + (ToplevelBlock) $5, (Attributes) $1, decl.location); + + if (op.Block == null) + op.ParameterInfo.CheckParameters (op); + + if (doc_support) { + op.DocComment = tmpComment; + Lexer.doc_state = XmlCommentState.Allowed; + } + + // Note again, checking is done in semantic analysis + current_container.AddOperator (op); + + lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + } + + current_local_parameters = null; + } + ; + +operator_body + : block + | SEMICOLON { $$ = null; } + ; + +operator_type + : type_expression_or_array + | VOID + { + report.Error (590, GetLocation ($1), "User-defined operators cannot return void"); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +operator_declarator + : operator_type OPERATOR overloadable_operator OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + Operator.OpType op = (Operator.OpType) $3; + current_local_parameters = (ParametersCompiled)$6; + + int p_count = current_local_parameters.Count; + if (p_count == 1) { + if (op == Operator.OpType.Addition) + op = Operator.OpType.UnaryPlus; + else if (op == Operator.OpType.Subtraction) + op = Operator.OpType.UnaryNegation; + } + + if (IsUnaryOperator (op)) { + if (p_count == 2) { + report.Error (1020, loc, "Overloadable binary operator expected"); + } else if (p_count != 1) { + report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", + Operator.GetName (op)); + } + } else { + if (p_count > 2) { + report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", + Operator.GetName (op)); + } else if (p_count != 2) { + report.Error (1019, loc, "Overloadable unary operator expected"); + } + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3), GetLocation ($4), GetLocation ($7)); + } + | conversion_operator_declarator + ; + +overloadable_operator +// Unary operators: + : BANG { $$ = Operator.OpType.LogicalNot; } + | TILDE { $$ = Operator.OpType.OnesComplement; } + | OP_INC { $$ = Operator.OpType.Increment; } + | OP_DEC { $$ = Operator.OpType.Decrement; } + | TRUE { $$ = Operator.OpType.True; } + | FALSE { $$ = Operator.OpType.False; } +// Unary and binary: + | PLUS { $$ = Operator.OpType.Addition; } + | MINUS { $$ = Operator.OpType.Subtraction; } +// Binary: + | STAR { $$ = Operator.OpType.Multiply; } + | DIV { $$ = Operator.OpType.Division; } + | PERCENT { $$ = Operator.OpType.Modulus; } + | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; } + | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; } + | CARRET { $$ = Operator.OpType.ExclusiveOr; } + | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; } + | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; } + | OP_EQ { $$ = Operator.OpType.Equality; } + | OP_NE { $$ = Operator.OpType.Inequality; } + | OP_GT { $$ = Operator.OpType.GreaterThan; } + | OP_LT { $$ = Operator.OpType.LessThan; } + | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; } + | OP_LE { $$ = Operator.OpType.LessThanOrEqual; } + ; + +conversion_operator_declarator + : IMPLICIT OPERATOR type OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + current_local_parameters = (ParametersCompiled)$6; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) $3, loc); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); + } + | EXPLICIT OPERATOR type OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + current_local_parameters = (ParametersCompiled)$6; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) $3, loc); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); + } + | IMPLICIT error + { + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + $$ = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation ($1)); + } + | EXPLICIT error + { + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + $$ = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation ($1)); + } + ; + +constructor_declaration + : constructor_declarator + constructor_body + { + Constructor c = (Constructor) $1; + c.Block = (ToplevelBlock) $2; + + if (doc_support) + c.DocComment = ConsumeStoredComment (); + + current_container.AddConstructor (c); + + current_local_parameters = null; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +constructor_declarator + : opt_attributes + opt_modifiers + IDENTIFIER + { + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + valid_param_mod = ParameterModifierType.All; + } + OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + current_local_parameters = (ParametersCompiled) $6; + + // + // start block here, so possible anonymous methods inside + // constructor initializer can get correct parent block + // + start_block (lexer.Location); + } + opt_constructor_initializer + { + var lt = (Tokenizer.LocatedToken) $3; + var mods = (Modifiers) $2; + ConstructorInitializer ci = (ConstructorInitializer) $9; + + Constructor c = new Constructor (current_class, lt.Value, mods, + (Attributes) $1, current_local_parameters, ci, lt.Location); + + if (lt.Value != current_container.MemberName.Name) { + report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); + } else if ((mods & Modifiers.STATIC) != 0) { + if ((mods & Modifiers.AccessibilityMask) != 0){ + report.Error (515, c.Location, + "`{0}': static constructor cannot have an access modifier", + c.GetSignatureForError ()); + } + if (ci != null) { + report.Error (514, c.Location, + "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", + c.GetSignatureForError ()); + + } + } + + lbag.AddMember (c, GetModifierLocations (), GetLocation ($5), GetLocation ($7)); + $$ = c; + } + ; + +constructor_body + : block_prepared + | SEMICOLON { current_block = null; $$ = null; } + ; + +opt_constructor_initializer + : /* Empty */ + | constructor_initializer + ; + +constructor_initializer + : COLON BASE OPEN_PARENS + { + ++lexer.parsing_block; + } + opt_argument_list CLOSE_PARENS + { + --lexer.parsing_block; + $$ = new ConstructorBaseInitializer ((Arguments) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); + } + | COLON THIS OPEN_PARENS + { + ++lexer.parsing_block; + } + opt_argument_list CLOSE_PARENS + { + --lexer.parsing_block; + $$ = new ConstructorThisInitializer ((Arguments) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); + } + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +destructor_declaration + : opt_attributes opt_modifiers TILDE + { + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body + { + var lt = (Tokenizer.LocatedToken) $5; + if (lt.Value != current_container.MemberName.Name){ + report.Error (574, lt.Location, "Name of destructor must match name of class"); + } else if (current_container.Kind != MemberKind.Class){ + report.Error (575, lt.Location, "Only class types can contain destructor"); + } + + Destructor d = new Destructor (current_class, (Modifiers) $2, + ParametersCompiled.EmptyReadOnlyParameters, (Attributes) $1, lt.Location); + if (doc_support) + d.DocComment = ConsumeStoredComment (); + + d.Block = (ToplevelBlock) $8; + current_container.AddMethod (d); + lbag.AddMember (d, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($7)); + + current_local_parameters = null; + } + ; + +event_declaration + : opt_attributes + opt_modifiers + EVENT type member_declaration_name + { + current_event_field = new EventField (current_class, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); + current_container.AddEvent (current_event_field); + + if (current_event_field.MemberName.Left != null) { + report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", + current_event_field.GetSignatureForError ()); + } + + $$ = current_event_field; + } + opt_event_initializer + opt_event_declarators + SEMICOLON + { + if (doc_support) { + current_event_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_event_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + current_event_field = null; + } + | opt_attributes + opt_modifiers + EVENT type member_declaration_name + OPEN_BRACE + { + current_event = new EventProperty (current_class, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); + current_container.AddEvent (current_event); + lbag.AddMember (current_event, GetModifierLocations (), GetLocation ($3), GetLocation ($6)); + + lexer.EventParsing = true; + } + event_accessor_declarations + { + if (current_container.Kind == MemberKind.Interface) + report.Error (69, GetLocation ($6), "Event in interface cannot have add or remove accessors"); + + lexer.EventParsing = false; + } + CLOSE_BRACE + { + if (doc_support) { + current_event.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AppendToMember (current_event, GetLocation ($9)); + current_event = null; + current_local_parameters = null; + } + ; + +opt_event_initializer + : /* empty */ + | ASSIGN + { + ++lexer.parsing_block; + } + event_variable_initializer + { + --lexer.parsing_block; + current_event_field.Initializer = (Expression) $3; + } + ; + +opt_event_declarators + : /* empty */ + | event_declarators + ; + +event_declarators + : event_declarator + { + current_event_field.AddDeclarator ((FieldDeclarator) $1); + } + | event_declarators event_declarator + { + current_event_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +event_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation ($$, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + event_variable_initializer + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +event_variable_initializer + : { + if (current_container.Kind == MemberKind.Interface) { + report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + + if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { + report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + } + variable_initializer + { + $$ = $2; + } + ; + +event_accessor_declarations + : add_accessor_declaration remove_accessor_declaration + | remove_accessor_declaration add_accessor_declaration + | add_accessor_declaration + { + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + | remove_accessor_declaration + { + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + | error + { + report.Error (1055, GetLocation ($1), "An add or remove accessor expected"); + $$ = null; + } + ; + +add_accessor_declaration + : opt_attributes opt_modifiers ADD + { + if ($2 != ModifierNone) { + report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); + current_local_parameters = current_event.Add.ParameterInfo; + + lbag.AddMember (current_event.Add, GetModifierLocations ()); + lexer.EventParsing = false; + } + event_accessor_block + { + lexer.EventParsing = true; + + current_event.Add.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Add.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); + } + + current_local_parameters = null; + } + ; + +remove_accessor_declaration + : opt_attributes opt_modifiers REMOVE + { + if ($2 != ModifierNone) { + report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); + current_local_parameters = current_event.Remove.ParameterInfo; + + lbag.AddMember (current_event.Remove, GetModifierLocations ()); + lexer.EventParsing = false; + } + event_accessor_block + { + lexer.EventParsing = true; + + current_event.Remove.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Remove.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); + } + + current_local_parameters = null; + } + ; + +event_accessor_block + : opt_semicolon + { + report.Error (73, lexer.Location, "An add or remove accessor must have a body"); + $$ = null; + } + | block; + ; + +enum_declaration + : opt_attributes + opt_modifiers + ENUM type_declaration_name + opt_enum_base + { + if (doc_support) + enumTypeComment = Lexer.consume_doc_comment (); + } + OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + + MemberName name = (MemberName) $4; + if (name.IsGeneric) { + report.Error (1675, name.Location, "Enums cannot have type parameters"); + } + + push_current_class (new Enum (current_namespace, current_class, (TypeExpression) $5, (Modifiers) $2, MakeName (name), (Attributes) $1), null); + } + opt_enum_member_declarations + { + // here will be evaluated after CLOSE_BLACE is consumed. + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + CLOSE_BRACE opt_semicolon + { + if (doc_support) + current_class.DocComment = enumTypeComment; + + --lexer.parsing_declaration; + +// if (doc_support) +// em.DocComment = ev.DocComment; + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($3), GetLocation ($7), GetLocation ($11)); + $$ = pop_current_class (); + } + ; + +opt_enum_base + : /* empty */ + | COLON type + { + var te = $2 as TypeExpression; + if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { + Enum.Error_1008 (GetLocation ($2), report); + $$ = null; + } else { + $$ = $2; + } + } + | COLON error + { + Error_TypeExpected (GetLocation ($1)); + $$ = null; + } + ; + +opt_enum_member_declarations + : /* empty */ + | enum_member_declarations + | enum_member_declarations COMMA + { + lbag.AddLocation ($1, GetLocation ($2)); + } + ; + +enum_member_declarations + : enum_member_declaration + | enum_member_declarations COMMA enum_member_declaration + { + lbag.AddLocation ($1, GetLocation ($2)); + $$ = $3; + } + ; + +enum_member_declaration + : opt_attributes IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) $1); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) { + em.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + $$ = em; + } + | opt_attributes IDENTIFIER + { + ++lexer.parsing_block; + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + } + ASSIGN constant_expression + { + --lexer.parsing_block; + + var lt = (Tokenizer.LocatedToken) $2; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) $1); + em.Initializer = new ConstInitializer (em, (Expression) $5, GetLocation ($4)); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) + em.DocComment = ConsumeStoredComment (); + + $$ = em; + } + ; + +delegate_declaration + : opt_attributes + opt_modifiers + DELEGATE + member_type type_declaration_name + OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + MemberName name = MakeName ((MemberName) $5); + ParametersCompiled p = (ParametersCompiled) $8; + + Delegate del = new Delegate (current_namespace, current_class, (FullNamedExpression) $4, + (Modifiers) $2, name, p, (Attributes) $1); + p.CheckParameters (del); + + ubag.PushTypeDeclaration (del); + ubag.PopTypeDeclaration (); + + current_container.AddDelegate (del); + current_delegate = del; + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + } + SEMICOLON + { + if (doc_support) { + current_delegate.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_delegate.SetParameterInfo ((List) $11); + lbag.AddMember (current_delegate, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($13)); + + $$ = current_delegate; + + current_delegate = null; + } + ; + +opt_nullable + : /* empty */ + | INTERR_NULLABLE + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "nullable types"); + + $$ = ComposedTypeSpecifier.CreateNullable (GetLocation ($1)); + } + ; + +namespace_or_type_name + : member_name + | qualified_alias_member IDENTIFIER opt_type_argument_list + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + } + ; + +member_name + : type_name + | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + +type_name + : IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments)$2, lt.Location); + } + ; + +// +// Generics arguments (any type, without attributes) +// +opt_type_argument_list + : /* empty */ + | OP_GENERICS_LT type_arguments OP_GENERICS_GT + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + var list = locationListStack.Pop (); + list.Add (GetLocation ($1)); + list.Add (GetLocation ($2)); + lbag.AddLocation ($2, list); + + $$ = $2;; + } + | OP_GENERICS_LT error + { + Error_TypeExpected (lexer.Location); + $$ = new TypeArguments (); + } + ; + +type_arguments + : type + { + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression) $1); + $$ = type_args; + locationListStack.Push (new List ()); + } + | type_arguments COMMA type + { + TypeArguments type_args = (TypeArguments) $1; + type_args.Add ((FullNamedExpression) $3); + $$ = type_args; + locationListStack.Peek ().Add (GetLocation ($2)); + } + ; + +// +// Generics parameters (identifiers only, with attributes), used in type or method declarations +// +type_declaration_name + : IDENTIFIER + { + lexer.parsing_generic_declaration = true; + } + opt_type_parameter_list + { + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments)$3, lt.Location); + } + ; + +member_declaration_name + : method_declaration_name + { + MemberName mn = (MemberName)$1; + if (mn.TypeArguments != null) + syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", + mn.GetSignatureForError ())); + } + ; + +method_declaration_name + : type_declaration_name + | explicit_interface IDENTIFIER opt_type_parameter_list + { + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location); + } + ; + +indexer_declaration_name + : THIS + { + lexer.parsing_generic_declaration = false; + $$ = new MemberName (TypeContainer.DefaultIndexerName, GetLocation ($1)); + } + | explicit_interface THIS + { + lexer.parsing_generic_declaration = false; + $$ = new MemberName ((MemberName) $1, TypeContainer.DefaultIndexerName, null, GetLocation ($1)); + } + ; + +explicit_interface + : IDENTIFIER opt_type_argument_list DOT + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location); + lbag.AddLocation ($$, GetLocation ($3)); + } + | qualified_alias_member IDENTIFIER opt_type_argument_list DOT + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($4)); + } + | explicit_interface IDENTIFIER opt_type_argument_list DOT + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +opt_type_parameter_list + : /* empty */ + | OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + + $$ = $2; + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +type_parameters + : type_parameter + { + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression)$1); + $$ = type_args; + } + | type_parameters COMMA type_parameter + { + TypeArguments type_args = (TypeArguments) $1; + type_args.Add ((FullNamedExpression)$3); + $$ = type_args; + lbag.AddLocation ($3, GetLocation ($3)); + } + ; + +type_parameter + : opt_attributes opt_type_parameter_variance IDENTIFIER + { + var lt = (Tokenizer.LocatedToken)$3; + $$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance) $2, lt.Location); + } + | error + { + if (GetTokenName (yyToken) == "type") + report.Error (81, GetLocation ($1), "Type parameter declaration must be an identifier not a type"); + else + Error_SyntaxError (yyToken); + + $$ = new TypeParameterName ("", null, lexer.Location); + } + ; + +// +// All types where void is allowed +// +type_and_void + : type_expression_or_array + | VOID + { + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +member_type + : type_and_void + { + lexer.parsing_generic_declaration = true; + } + ; + +// +// A type which does not allow `void' to be used +// +type + : type_expression_or_array + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +simple_type + : type_expression + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +parameter_type + : type_expression_or_array + | VOID + { + report.Error (1536, GetLocation ($1), "Invalid parameter type `void'"); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +type_expression_or_array + : type_expression + | type_expression rank_specifiers + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + ; + +type_expression + : namespace_or_type_name opt_nullable + { + MemberName name = (MemberName) $1; + + if ($2 != null) { + $$ = new ComposedCast (name.GetTypeExpression (), (ComposedTypeSpecifier) $2); + } else { + if (name.Left == null && name.Name == "var") + $$ = new VarExpr (name.Location); + else + $$ = name.GetTypeExpression (); + } + } + | namespace_or_type_name pointer_stars + { + $$ = new ComposedCast (((MemberName) $1).GetTypeExpression (), (ComposedTypeSpecifier) $2); + } + | builtin_types opt_nullable + { + if ($2 != null) + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | builtin_types pointer_stars + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | VOID pointer_stars + { + $$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); + } + ; + +type_list + : base_type_name + { + var types = new List (2); + types.Add ((FullNamedExpression) $1); + $$ = types; + } + | type_list COMMA base_type_name + { + var types = (List) $1; + types.Add ((FullNamedExpression) $3); + $$ = types; + } + ; + +base_type_name + : type + { + if ($1 is ComposedCast) { + report.Error (1521, GetLocation ($1), "Invalid base type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); + } + $$ = $1; + } + | error + { + Error_TypeExpected (lexer.Location); + $$ = null; + } + ; + +/* + * replaces all the productions for isolating the various + * simple types, but we need this to reuse it easily in variable_type + */ +builtin_types + : OBJECT { $$ = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation ($1)); } + | STRING { $$ = new TypeExpression (compiler.BuiltinTypes.String, GetLocation ($1)); } + | BOOL { $$ = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation ($1)); } + | DECIMAL { $$ = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation ($1)); } + | FLOAT { $$ = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation ($1)); } + | DOUBLE { $$ = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation ($1)); } + | integral_type + ; + +integral_type + : SBYTE { $$ = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation ($1)); } + | BYTE { $$ = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation ($1)); } + | SHORT { $$ = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation ($1)); } + | USHORT { $$ = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation ($1)); } + | INT { $$ = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation ($1)); } + | UINT { $$ = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation ($1)); } + | LONG { $$ = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation ($1)); } + | ULONG { $$ = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation ($1)); } + | CHAR { $$ = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation ($1)); } + ; + +// +// Expressions, section 7.5 +// + + +primary_expression + : primary_expression_or_type + | literal + | array_creation_expression + | parenthesized_expression + | default_value_expression + | invocation_expression + | element_access + | this_access + | base_access + | post_increment_expression + | post_decrement_expression + | object_or_delegate_creation_expression + | anonymous_type_expression + | typeof_expression + | sizeof_expression + | checked_expression + | unchecked_expression + | pointer_member_access + | anonymous_method_expression + | undocumented_expressions + ; + +primary_expression_or_type + : IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new SimpleName (lt.Value, (TypeArguments)$2, lt.Location); + } + | IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); + } + | member_access + ; + +literal + : boolean_literal + | LITERAL + | NULL { $$ = new NullLiteral (GetLocation ($1)); } + ; + +boolean_literal + : TRUE { $$ = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation ($1)); } + | FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); } + ; + + +// +// Here is the trick, tokenizer may think that parens is a special but +// parser is interested in open parens only, so we merge them. +// Consider: if (a)foo (); +// +open_parens_any + : OPEN_PARENS + | OPEN_PARENS_CAST + ; + +// +// Use this production to accept closing parenthesis or +// performing completion +// +close_parens + : CLOSE_PARENS + | COMPLETE_COMPLETION + ; + + +parenthesized_expression + : OPEN_PARENS expression CLOSE_PARENS + { + $$ = new ParenthesizedExpression ((Expression) $2); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + | OPEN_PARENS expression COMPLETE_COMPLETION + { + $$ = new ParenthesizedExpression ((Expression) $2); + } + ; + +member_access + : primary_expression DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | builtin_types DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | BASE DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | qualified_alias_member IDENTIFIER opt_type_argument_list + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | primary_expression DOT GENERATE_COMPLETION { + $$ = new CompletionMemberAccess ((Expression) $1, null,GetLocation ($3)); + } + | primary_expression DOT IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); + } + | builtin_types DOT GENERATE_COMPLETION + { + $$ = new CompletionMemberAccess ((Expression) $1, null, lexer.Location); + } + | builtin_types DOT IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); + } + ; + +invocation_expression + : primary_expression open_parens_any opt_argument_list close_parens + { + $$ = new Invocation ((Expression) $1, (Arguments) $3); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +opt_object_or_collection_initializer + : /* empty */ { $$ = null; } + | object_or_collection_initializer + ; + +object_or_collection_initializer + : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion + { + if ($2 == null) { + $$ = CollectionOrObjectInitializers.Empty; + // TODO: lbag + } else { + $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + } + | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE + { + $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($4)); + } + ; + +opt_member_initializer_list + : /* empty */ { $$ = null; } + | member_initializer_list + { + $$ = $1; + } + ; + +member_initializer_list + : member_initializer + { + var a = new List (); + a.Add ((Expression) $1); + $$ = a; + } + | member_initializer_list COMMA member_initializer + { + var a = (List)$1; + a.Add ((Expression) $3); + $$ = a; + } + | member_initializer_list error { + Error_SyntaxError (yyToken); + $$ = $1; + } + ; + +member_initializer + : IDENTIFIER ASSIGN initializer_value + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | GENERATE_COMPLETION + { + $$ = new CompletionElementInitializer (null, GetLocation ($1)); + } + | non_assignment_expression opt_COMPLETE_COMPLETION { + CompletionSimpleName csn = $1 as CompletionSimpleName; + if (csn == null) + $$ = new CollectionElementInitializer ((Expression)$1); + else + $$ = new CompletionElementInitializer (csn.Prefix, csn.Location); + } + | OPEN_BRACE expression_list CLOSE_BRACE + { + if ($2 == null) + $$ = null; + else + $$ = new CollectionElementInitializer ((List)$2, GetLocation ($1)); + } + | OPEN_BRACE CLOSE_BRACE + { + report.Error (1920, GetLocation ($1), "An element initializer cannot be empty"); + $$ = null; + } + ; + +initializer_value + : expression + | object_or_collection_initializer + ; + +opt_argument_list + : /* empty */ { $$ = null; } + | argument_list + ; + +argument_list + : argument_or_named_argument + { + Arguments list = new Arguments (4); + list.Add ((Argument) $1); + $$ = list; + } + | argument_list COMMA argument + { + Arguments list = (Arguments) $1; + if (list [list.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); + + list.Add ((Argument) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | argument_list COMMA named_argument + { + Arguments list = (Arguments) $1; + NamedArgument a = (NamedArgument) $3; + for (int i = 0; i < list.Count; ++i) { + NamedArgument na = list [i] as NamedArgument; + if (na != null && na.Name == a.Name) + report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", + na.Name); + } + + list.Add (a); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | argument_list COMMA + { + report.Error (839, GetLocation ($2), "An argument is missing"); + $$ = $1; + } + | COMMA error + { + report.Error (839, GetLocation ($1), "An argument is missing"); + $$ = null; + } + ; + +argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | non_simple_argument + ; + +argument_or_named_argument + : argument + | named_argument + ; + +non_simple_argument + : REF variable_reference + { + $$ = new Argument ((Expression) $2, Argument.AType.Ref); + lbag.AddLocation ($$, GetLocation ($1)); + } + | OUT variable_reference + { + $$ = new Argument ((Expression) $2, Argument.AType.Out); + lbag.AddLocation ($$, GetLocation ($1)); + } + | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS + { + $$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1))); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | ARGLIST OPEN_PARENS CLOSE_PARENS + { + $$ = new Argument (new Arglist (GetLocation ($1))); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +variable_reference + : expression + ; + +element_access + : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + { + $$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +expression_list + : expression + { + var list = new List (4); + list.Add ((Expression) $1); + $$ = list; + } + | expression_list COMMA expression + { + var list = (List) $1; + list.Add ((Expression) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | expression_list error { + Error_SyntaxError (yyToken); + $$ = $1; + } + ; + +expression_list_arguments + : expression_list_argument + { + Arguments args = new Arguments (4); + args.Add ((Argument) $1); + $$ = args; + } + | expression_list_arguments COMMA expression_list_argument + { + Arguments args = (Arguments) $1; + if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) $3); + lbag.AppendTo (args, GetLocation ($2)); + $$ = args; + } + ; + +expression_list_argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | named_argument + ; + +this_access + : THIS + { + $$ = new This (GetLocation ($1)); + } + ; + +base_access + : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + { + $$ = new ElementAccess (new BaseThis (GetLocation ($1)), (Arguments) $3, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + | BASE OPEN_BRACKET error + { + Error_SyntaxError (yyToken); + $$ = new ElementAccess (null, null, GetLocation ($2)); + } + ; + +post_increment_expression + : primary_expression OP_INC + { + $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) $1, GetLocation ($2)); + } + ; + +post_decrement_expression + : primary_expression OP_DEC + { + $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) $1, GetLocation ($2)); + } + ; + +object_or_delegate_creation_expression + : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer + { + if ($6 != null) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "object initializers"); + + $$ = new NewInitialize ((FullNamedExpression) $2, (Arguments) $4, (CollectionOrObjectInitializers) $6, GetLocation ($1)); + } else { + $$ = new New ((FullNamedExpression) $2, (Arguments) $4, GetLocation ($1)); + } + + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | NEW new_expr_type object_or_collection_initializer + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "collection initializers"); + + $$ = new NewInitialize ((FullNamedExpression) $2, null, (CollectionOrObjectInitializers) $3, GetLocation ($1)); + } + ; + +array_creation_expression + : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET + opt_rank_specifier + opt_array_initializer + { + $$ = new ArrayCreation ((FullNamedExpression) $2, (List) $4, + new ComposedTypeSpecifier (((List) $4).Count, GetLocation ($3)) { + Next = (ComposedTypeSpecifier) $6 + }, (ArrayInitializer) $7, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | NEW new_expr_type rank_specifiers opt_array_initializer + { + if ($4 == null) + report.Error (1586, GetLocation ($1), "Array creation must have array size or array initializer"); + + $$ = new ArrayCreation ((FullNamedExpression) $2, (ComposedTypeSpecifier) $3, (ArrayInitializer) $4, GetLocation ($1)); + } + | NEW rank_specifier array_initializer + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "implicitly typed arrays"); + + $$ = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) $2, (ArrayInitializer) $3, GetLocation ($1)); + } + | NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET + { + report.Error (178, GetLocation ($6), "Invalid rank specifier, expecting `,' or `]'"); + $$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); + } + | NEW new_expr_type error + { + Error_SyntaxError (1526, yyToken, "Unexpected symbol"); + $$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); + } + ; + +new_expr_type + : { + ++lexer.parsing_type; + } + simple_type + { + --lexer.parsing_type; + $$ = $2; + } + ; + +anonymous_type_expression + : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "anonymous types"); + + $$ = new NewAnonymousType ((List) $3, current_container, GetLocation ($1)); + + // TODO: lbag comma location + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +anonymous_type_parameters_opt_comma + : anonymous_type_parameters_opt + | anonymous_type_parameters COMMA + ; + +anonymous_type_parameters_opt + : { $$ = null; } + | anonymous_type_parameters + ; + +anonymous_type_parameters + : anonymous_type_parameter + { + var a = new List (4); + a.Add ((AnonymousTypeParameter) $1); + $$ = a; + } + | anonymous_type_parameters COMMA anonymous_type_parameter + { + var a = (List) $1; + a.Add ((AnonymousTypeParameter) $3); + $$ = a; + } + ; + +anonymous_type_parameter + : IDENTIFIER ASSIGN variable_initializer + { + var lt = (Tokenizer.LocatedToken)$1; + $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | IDENTIFIER + { + var lt = (Tokenizer.LocatedToken)$1; + $$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), + lt.Value, lt.Location); + } + | member_access + { + MemberAccess ma = (MemberAccess) $1; + $$ = new AnonymousTypeParameter (ma, ma.Name, ma.Location); + } + | error + { + report.Error (746, lexer.Location, + "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); + $$ = null; + } + ; + +opt_rank_specifier + : /* empty */ + | rank_specifiers + ; + +rank_specifiers + : rank_specifier + | rank_specifier rank_specifiers + { + ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; + $$ = $1; + } + ; + +rank_specifier + : OPEN_BRACKET CLOSE_BRACKET + { + $$ = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2)); + } + | OPEN_BRACKET dim_separators CLOSE_BRACKET + { + $$ = ComposedTypeSpecifier.CreateArrayDimension ((int)$2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + ; + +dim_separators + : COMMA + { + $$ = 2; + } + | dim_separators COMMA + { + $$ = ((int) $1) + 1; + } + ; + +opt_array_initializer + : /* empty */ + { + $$ = null; + } + | array_initializer + { + $$ = $1; + } + ; + +array_initializer + : OPEN_BRACE CLOSE_BRACE + { + var ai = new ArrayInitializer (0, GetLocation ($1)); + ai.VariableDeclaration = current_variable; + lbag.AddLocation (ai, GetLocation ($2)); + $$ = ai; + } + | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE + { + var ai = new ArrayInitializer ((List) $2, GetLocation ($1)); + ai.VariableDeclaration = current_variable; + if ($3 != null) { + lbag.AddLocation (ai, GetLocation ($3), GetLocation ($4)); + } else { + lbag.AddLocation (ai, GetLocation ($4)); + } + $$ = ai; + } + ; + +variable_initializer_list + : variable_initializer + { + var list = new List (4); + list.Add ((Expression) $1); + $$ = list; + } + | variable_initializer_list COMMA variable_initializer + { + var list = (List) $1; + list.Add ((Expression) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + ; + +typeof_expression + : TYPEOF + { + lexer.TypeOfParsing = true; + } + open_parens_any typeof_type_expression CLOSE_PARENS + { + lexer.TypeOfParsing = false; + $$ = new TypeOf ((FullNamedExpression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + ; + +typeof_type_expression + : type_and_void + | unbound_type_name + | error + { + Error_TypeExpected (lexer.Location); + $$ = null; + } + ; + +unbound_type_name + : IDENTIFIER generic_dimension + { + var lt = (Tokenizer.LocatedToken) $1; + + $$ = new SimpleName (lt.Value, (int) $2, lt.Location); + } + | qualified_alias_member IDENTIFIER generic_dimension + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | unbound_type_name DOT IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location); + } + | unbound_type_name DOT IDENTIFIER generic_dimension + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location); + } + | namespace_or_type_name DOT IDENTIFIER generic_dimension + { + var te = ((MemberName) $1).GetTypeExpression (); + if (te.HasTypeArguments) + Error_TypeExpected (GetLocation ($4)); + + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (te, lt.Value, (int) $4, lt.Location); + } + ; + +generic_dimension + : GENERIC_DIMENSION + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + + $$ = $1; + } + ; + +qualified_alias_member + : IDENTIFIER DOUBLE_COLON + { + var lt = (Tokenizer.LocatedToken) $1; + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); + + $$ = lt; + } + ; + +sizeof_expression + : SIZEOF open_parens_any type CLOSE_PARENS + { + $$ = new SizeOf ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +checked_expression + : CHECKED open_parens_any expression CLOSE_PARENS + { + $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +unchecked_expression + : UNCHECKED open_parens_any expression CLOSE_PARENS + { + $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +pointer_member_access + : primary_expression OP_PTR IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (new Indirection ((Expression) $1, GetLocation ($2)), lt.Value, (TypeArguments) $4, lt.Location); + } + ; + +anonymous_method_expression + : DELEGATE opt_anonymous_method_signature + { + start_anonymous (false, (ParametersCompiled) $2, false, GetLocation ($1)); + } + block + { + $$ = end_anonymous ((ParametersBlock) $4); + if ((ParametersCompiled) $2 != ParametersCompiled.Undefined) { + lbag.AddLocation ($$, GetLocation ($1), savedOpenLocation, savedCloseLocation); + } else { + lbag.AddLocation ($$, GetLocation ($1)); + } + } + | ASYNC DELEGATE opt_anonymous_method_signature + { + start_anonymous (false, (ParametersCompiled) $3, true, GetLocation ($1)); + } + block + { + $$ = end_anonymous ((ParametersBlock) $5); + } + ; + +opt_anonymous_method_signature + : + { + $$ = ParametersCompiled.Undefined; + } + | anonymous_method_signature + ; + +anonymous_method_signature + : OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + $$ = $3; + savedOpenLocation = GetLocation ($1); + savedCloseLocation = GetLocation ($2); + } + ; + +default_value_expression + : DEFAULT open_parens_any type CLOSE_PARENS + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "default value expression"); + + $$ = new DefaultValueExpression ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +unary_expression + : primary_expression + | BANG prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, GetLocation ($1)); + } + | TILDE prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, GetLocation ($1)); + } + | cast_expression + | await_expression + ; + +cast_expression + : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression + { + $$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + ; + +await_expression + : AWAIT unary_expression + { + current_block.ParametersBlock.IsAsync = true; + $$ = new Await ((Expression) $2, GetLocation ($1)); + } + ; + + // + // The idea to split this out is from Rhys' grammar + // to solve the problem with casts. + // +prefixed_unary_expression + : unary_expression + | PLUS prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); + } + | MINUS prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); + } + | OP_INC prefixed_unary_expression + { + $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) $2, GetLocation ($1)); + } + | OP_DEC prefixed_unary_expression + { + $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) $2, GetLocation ($1)); + } + | STAR prefixed_unary_expression + { + $$ = new Indirection ((Expression) $2, GetLocation ($1)); + } + | BITWISE_AND prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, GetLocation ($1)); + } + ; + +multiplicative_expression + : prefixed_unary_expression + | multiplicative_expression STAR prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Multiply, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | multiplicative_expression DIV prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Division, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | multiplicative_expression PERCENT prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Modulus, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +additive_expression + : multiplicative_expression + | additive_expression PLUS multiplicative_expression + { + $$ = new Binary (Binary.Operator.Addition, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression MINUS multiplicative_expression + { + $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | parenthesized_expression MINUS multiplicative_expression + { + // Shift/Reduce conflict + $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression AS type + { + $$ = new As ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression IS type + { + $$ = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +shift_expression + : additive_expression + | shift_expression OP_SHIFT_LEFT additive_expression + { + $$ = new Binary (Binary.Operator.LeftShift, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | shift_expression OP_SHIFT_RIGHT additive_expression + { + $$ = new Binary (Binary.Operator.RightShift, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +relational_expression + : shift_expression + | relational_expression OP_LT shift_expression + { + $$ = new Binary (Binary.Operator.LessThan, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_GT shift_expression + { + $$ = new Binary (Binary.Operator.GreaterThan, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_LE shift_expression + { + $$ = new Binary (Binary.Operator.LessThanOrEqual, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_GE shift_expression + { + $$ = new Binary (Binary.Operator.GreaterThanOrEqual, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +equality_expression + : relational_expression + | equality_expression OP_EQ relational_expression + { + $$ = new Binary (Binary.Operator.Equality, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | equality_expression OP_NE relational_expression + { + $$ = new Binary (Binary.Operator.Inequality, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +and_expression + : equality_expression + | and_expression BITWISE_AND equality_expression + { + $$ = new Binary (Binary.Operator.BitwiseAnd, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +exclusive_or_expression + : and_expression + | exclusive_or_expression CARRET and_expression + { + $$ = new Binary (Binary.Operator.ExclusiveOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +inclusive_or_expression + : exclusive_or_expression + | inclusive_or_expression BITWISE_OR exclusive_or_expression + { + $$ = new Binary (Binary.Operator.BitwiseOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_and_expression + : inclusive_or_expression + | conditional_and_expression OP_AND inclusive_or_expression + { + $$ = new Binary (Binary.Operator.LogicalAnd, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_or_expression + : conditional_and_expression + | conditional_or_expression OP_OR conditional_and_expression + { + $$ = new Binary (Binary.Operator.LogicalOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +null_coalescing_expression + : conditional_or_expression + | conditional_or_expression OP_COALESCING null_coalescing_expression + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($2), "null coalescing operator"); + + $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_expression + : null_coalescing_expression + | null_coalescing_expression INTERR expression COLON expression + { + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +assignment_expression + : prefixed_unary_expression ASSIGN expression + { + $$ = new SimpleAssign ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_MULT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Multiply, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_DIV_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Division, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_MOD_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Modulus, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_ADD_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Addition, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SUB_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.RightShift, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_AND_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_OR_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_XOR_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +lambda_parameter_list + : lambda_parameter + { + var pars = new List (4); + pars.Add ((Parameter) $1); + + $$ = pars; + } + | lambda_parameter_list COMMA lambda_parameter + { + var pars = (List) $1; + Parameter p = (Parameter)$3; + if (pars[0].GetType () != p.GetType ()) { + report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); + } + + pars.Add (p); + $$ = pars; + } + ; + +lambda_parameter + : parameter_modifier parameter_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location); + } + | parameter_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + + $$ = new Parameter ((FullNamedExpression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location); + } + | IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); + } + ; + +opt_lambda_parameter_list + : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } + | lambda_parameter_list { + var pars_list = (List) $1; + $$ = new ParametersCompiled (pars_list.ToArray ()); + } + ; + +lambda_expression_body + : lambda_expression_body_simple + | block + ; + +lambda_expression_body_simple + : { + start_block (lexer.Location); + } + expression_or_error // Have to close block when error occurs + { + Block b = end_block (lexer.Location); + b.IsCompilerGenerated = true; + b.AddStatement (new ContextualReturn ((Expression) $2)); + $$ = b; + } + ; + +expression_or_error + : expression + | error + { + Error_SyntaxError (yyToken); + $$ = EmptyExpression.Null; + } + ; + +lambda_expression + : IDENTIFIER ARROW + { + var lt = (Tokenizer.LocatedToken) $1; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), false, lt.Location); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $4); + lbag.AddLocation ($$, GetLocation ($2)); + } + | ASYNC IDENTIFIER ARROW + { + var lt = (Tokenizer.LocatedToken) $2; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), true, lt.Location); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + | OPEN_PARENS_LAMBDA + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) $3, false, GetLocation ($1)); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $7); + lbag.AddLocation ($$, GetLocation ($4), GetLocation ($5)); + } + | ASYNC OPEN_PARENS_LAMBDA + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) $4, true, GetLocation ($1)); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $8); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($5), GetLocation ($6)); + } + ; + +expression + : assignment_expression + | non_assignment_expression + ; + +non_assignment_expression + : conditional_expression + | lambda_expression + | query_expression + | ARGLIST + { + $$ = new ArglistAccess (GetLocation ($1)); + } + ; + +undocumented_expressions + : REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS + { + $$ = new RefValueExpr ((Expression) $3, (FullNamedExpression) $5, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); + } + | REFTYPE open_parens_any expression CLOSE_PARENS + { + $$ = new RefTypeExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | MAKEREF open_parens_any expression CLOSE_PARENS + { + $$ = new MakeRefExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +constant_expression + : expression + ; + +boolean_expression + : expression + { + $$ = new BooleanExpression ((Expression) $1); + } + ; + +// +// 10 classes +// +class_declaration + : opt_attributes + opt_modifiers + opt_partial + CLASS + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + Class c = new Class (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1); + if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (c.Location, "static classes"); + } + + push_current_class (c, $3); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + OPEN_BRACE opt_class_member_declarations CLOSE_BRACE + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13), GetLocation ($15)); + $$ = pop_current_class (); + } + ; + +opt_partial + : /* empty */ + { $$ = null; } + | PARTIAL + { $$ = $1; StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($1)); } // location + ; + +opt_modifiers + : /* empty */ + { + mod_locations = null; + $$ = ModifierNone; + } + | modifiers + ; + +modifiers + : modifier + | modifiers modifier + { + var m1 = (Modifiers) $1; + var m2 = (Modifiers) $2; + + if ((m1 & m2) != 0) { + report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, + "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); + } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && + ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { + report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, + "More than one protection modifier specified"); + } + + $$ = m1 | m2; + } + ; + +modifier + : NEW + { + $$ = Modifiers.NEW; + StoreModifierLocation ($$, GetLocation ($1)); + + if (current_container == module) + report.Error (1530, GetLocation ($1), "Keyword `new' is not allowed on namespace elements"); + } + | PUBLIC + { + $$ = Modifiers.PUBLIC; + StoreModifierLocation ($$, GetLocation ($1)); + } + | PROTECTED + { + $$ = Modifiers.PROTECTED; + StoreModifierLocation ($$, GetLocation ($1)); + } + | INTERNAL + { + $$ = Modifiers.INTERNAL; + StoreModifierLocation ($$, GetLocation ($1)); + } + | PRIVATE + { + $$ = Modifiers.PRIVATE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | ABSTRACT + { + $$ = Modifiers.ABSTRACT; + StoreModifierLocation ($$, GetLocation ($1)); + } + | SEALED + { + $$ = Modifiers.SEALED; + StoreModifierLocation ($$, GetLocation ($1)); + } + | STATIC + { + $$ = Modifiers.STATIC; + StoreModifierLocation ($$, GetLocation ($1)); + } + | READONLY + { + $$ = Modifiers.READONLY; + StoreModifierLocation ($$, GetLocation ($1)); + } + | VIRTUAL + { + $$ = Modifiers.VIRTUAL; + StoreModifierLocation ($$, GetLocation ($1)); + } + | OVERRIDE + { + $$ = Modifiers.OVERRIDE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | EXTERN + { + $$ = Modifiers.EXTERN; + StoreModifierLocation ($$, GetLocation ($1)); + } + | VOLATILE + { + $$ = Modifiers.VOLATILE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | UNSAFE + { + $$ = Modifiers.UNSAFE; + StoreModifierLocation ($$, GetLocation ($1)); + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation ($1)); + } + | ASYNC + { + $$ = Modifiers.ASYNC; + StoreModifierLocation ($$, GetLocation ($1)); + } + ; + +opt_class_base + : /* empty */ + | COLON type_list + { + current_container.AddBasesForPart (current_class, (List) $2); + } + ; + +opt_type_parameter_constraints_clauses + : /* empty */ + | type_parameter_constraints_clauses + { + $$ = $1; + } + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +type_parameter_constraints_clauses + : type_parameter_constraints_clause + { + var constraints = new List (1); + constraints.Add ((Constraints) $1); + $$ = constraints; + } + | type_parameter_constraints_clauses type_parameter_constraints_clause + { + var constraints = (List) $1; + Constraints new_constraint = (Constraints)$2; + + foreach (Constraints c in constraints) { + if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { + report.Error (409, new_constraint.Location, + "A constraint clause has already been specified for type parameter `{0}'", + new_constraint.TypeParameter.Value); + } + } + + constraints.Add (new_constraint); + $$ = constraints; + } + ; + +type_parameter_constraints_clause + : WHERE IDENTIFIER COLON type_parameter_constraints + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) $4, GetLocation ($1)); + } + ; + +type_parameter_constraints + : type_parameter_constraint + { + var constraints = new List (1); + constraints.Add ((FullNamedExpression) $1); + $$ = constraints; + } + | type_parameter_constraints COMMA type_parameter_constraint + { + var constraints = (List) $1; + var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { + report.Error (401, GetLocation ($2), "The `new()' constraint must be the last constraint specified"); + } + + prev = $3 as SpecialContraintExpr; + if (prev != null) { + if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { + report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); + } else { + prev = constraints [0] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { + report.Error (451, GetLocation ($3), "The `new()' constraint cannot be used with the `struct' constraint"); + } + } + } + + constraints.Add ((FullNamedExpression) $3); + $$ = constraints; + } + ; + +type_parameter_constraint + : type + { + if ($1 is ComposedCast) + report.Error (706, GetLocation ($1), "Invalid constraint type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); + + $$ = $1; + } + | NEW OPEN_PARENS CLOSE_PARENS + { + $$ = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); + } + | CLASS + { + $$ = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation ($1)); + } + | STRUCT + { + $$ = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation ($1)); + } + ; + +opt_type_parameter_variance + : /* empty */ + { + $$ = Variance.None; + } + | type_parameter_variance + { + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (lexer.Location, "generic type variance"); + + $$ = $1; + } + ; + +type_parameter_variance + : OUT + { + $$ = Variance.Covariant; + } + | IN + { + $$ = Variance.Contravariant; + } + ; + +// +// Statements (8.2) +// + +// +// A block is "contained" on the following places: +// method_body +// property_declaration as part of the accessor body (get/set) +// operator_declaration +// constructor_declaration +// destructor_declaration +// event_declaration as part of add_accessor_declaration or remove_accessor_declaration +// +block + : OPEN_BRACE + { + ++lexer.parsing_block; + start_block (GetLocation ($1)); + } + opt_statement_list block_end + { + $$ = $4; + } + ; + +block_end + : CLOSE_BRACE + { + --lexer.parsing_block; + $$ = end_block (GetLocation ($1)); + } + | COMPLETE_COMPLETION + { + --lexer.parsing_block; + $$ = end_block (lexer.Location); + } + ; + + +block_prepared + : OPEN_BRACE + { + ++lexer.parsing_block; + current_block.StartLocation = GetLocation ($1); + } + opt_statement_list CLOSE_BRACE + { + --lexer.parsing_block; + $$ = end_block (GetLocation ($4)); + } + ; + +opt_statement_list + : /* empty */ + | statement_list + ; + +statement_list + : statement + | statement_list statement + ; + +statement + : block_variable_declaration + { + current_block.AddStatement ((Statement) $1); + } + | valid_declaration_statement + { + current_block.AddStatement ((Statement) $1); + } + | labeled_statement + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +// +// The interactive_statement and its derivatives are only +// used to provide a special version of `expression_statement' +// that has a side effect of assigning the expression to +// $retval +// +interactive_statement_list + : interactive_statement + | interactive_statement_list interactive_statement + ; + +interactive_statement + : block_variable_declaration + { + current_block.AddStatement ((Statement) $1); + } + | interactive_valid_declaration_statement + { + current_block.AddStatement ((Statement) $1); + } + | labeled_statement + ; + +valid_declaration_statement + : block + | empty_statement + | expression_statement + | selection_statement + | iteration_statement + | jump_statement + | try_statement + | checked_statement + | unchecked_statement + | lock_statement + | using_statement + | unsafe_statement + | fixed_statement + ; + +interactive_valid_declaration_statement + : block + | empty_statement + | interactive_expression_statement + | selection_statement + | iteration_statement + | jump_statement + | try_statement + | checked_statement + | unchecked_statement + | lock_statement + | using_statement + | unsafe_statement + | fixed_statement + ; + +embedded_statement + : valid_declaration_statement + | block_variable_declaration + { + report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); + $$ = null; + } + | labeled_statement + { + report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); + $$ = null; + } + | error + { + Error_SyntaxError (yyToken); + $$ = new EmptyStatement (GetLocation ($1)); + } + ; + +empty_statement + : SEMICOLON + { + // Uses lexer.Location because semicolon location is not kept in quick mode + $$ = new EmptyStatement (lexer.Location); + } + ; + +labeled_statement + : IDENTIFIER COLON + { + var lt = (Tokenizer.LocatedToken) $1; + LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); + + current_block.AddLabel (labeled); + current_block.AddStatement (labeled); + } + statement + ; + +variable_type + : variable_type_simple + | variable_type_simple rank_specifiers + { + if ($1 is VarExpr) + $1 = new SimpleName ("var", ((VarExpr) $1).Location); + + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + ; + +/* + * The following is from Rhys' grammar: + * > Types in local variable declarations must be recognized as + * > expressions to prevent reduce/reduce errors in the grammar. + * > The expressions are converted into types during semantic analysis. + */ +variable_type_simple + : primary_expression_or_type opt_nullable + { + // Ok, the above "primary_expression" is there to get rid of + // both reduce/reduce and shift/reduces in the grammar, it should + // really just be "type_name". If you use type_name, a reduce/reduce + // creeps up. If you use namespace_or_type_name (which is all we need + // really) two shift/reduces appear. + // + + // So the super-trick is that primary_expression + // can only be either a SimpleName or a MemberAccess. + // The MemberAccess case arises when you have a fully qualified type-name like : + // Foo.Bar.Blah i; + // SimpleName is when you have + // Blah i; + + Expression expr = (Expression) $1; + if ($2 == null) { + SimpleName sn = expr as SimpleName; + if (sn != null && sn.Name == "var") + $$ = new VarExpr (sn.Location); + else + $$ = $1; + } else if (expr is ATypeNameExpression) { + $$ = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) $2); + } else { + Error_ExpectingTypeName (expr); + $$ = null; + } + } + | primary_expression_or_type pointer_stars + { + ATypeNameExpression expr = $1 as ATypeNameExpression; + + if (expr != null) { + $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); + } else { + Error_ExpectingTypeName ((Expression)$1); + $$ = expr; + } + } + | builtin_types opt_nullable + { + if ($2 == null) + $$ = $1; + else + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | builtin_types pointer_stars + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | VOID pointer_stars + { + $$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); + } + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +pointer_stars + : pointer_star + | pointer_star pointer_stars + { + ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; + $$ = $1; + } + ; + +pointer_star + : STAR + { + $$ = ComposedTypeSpecifier.CreatePointer (GetLocation ($1)); + } + ; + +block_variable_declaration + : variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); + } + opt_local_variable_initializer opt_variable_declarators SEMICOLON + { + $$ = current_variable; + current_variable = null; + lbag.AppendTo ($$, GetLocation ($6)); + } + | CONST variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockConstantDeclaration ((FullNamedExpression) $2, li); + } + const_variable_initializer opt_const_declarators SEMICOLON + { + if (current_variable.Initializer != null) { + lbag.AddLocation (current_variable, GetLocation ($1), savedLocation, GetLocation ($7)); + } else { + lbag.AddLocation (current_variable, GetLocation ($1), GetLocation ($7)); + } + $$ = current_variable;; + current_variable = null; + } + ; + +opt_local_variable_initializer + : /* empty */ + | ASSIGN block_variable_initializer + { + current_variable.Initializer = (Expression) $2; + lbag.AppendTo (current_variable, GetLocation ($1)); + } + | error + { + if (yyToken == Token.OPEN_BRACKET_EXPR) { + report.Error (650, lexer.Location, + "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); + } else { + Error_SyntaxError (yyToken); + } + } + ; + +opt_variable_declarators + : /* empty */ + | variable_declarators + ; + +variable_declarators + : variable_declarator + | variable_declarators variable_declarator + ; + +variable_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, null); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN block_variable_initializer + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); + } + ; + +const_variable_initializer + : /* empty */ + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + } + | ASSIGN constant_initializer_expr + { + savedLocation = GetLocation ($1); + current_variable.Initializer = (Expression) $2; + } + ; + +opt_const_declarators + : /* empty */ + | const_declarators + ; + +const_declarators + : const_declarator + | const_declarators const_declarator + ; + +const_declarator + : COMMA IDENTIFIER ASSIGN constant_initializer_expr + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); + } + ; + +block_variable_initializer + : variable_initializer + | STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET + { + $$ = new StackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | STACKALLOC simple_type + { + report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); + $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); + } + ; + +expression_statement + : statement_expression SEMICOLON + { + $$ = $1; + lbag.AddStatement ($$, GetLocation ($2)); + } + | statement_expression COMPLETE_COMPLETION { $$ = $1; } + ; + +interactive_expression_statement + : interactive_statement_expression SEMICOLON { $$ = $1; } + | interactive_statement_expression COMPLETE_COMPLETION { $$ = $1; } + ; + + // + // We have to do the wrapping here and not in the case above, + // because statement_expression is used for example in for_statement + // +statement_expression + : expression + { + ExpressionStatement s = $1 as ExpressionStatement; + if (s == null) { + Expression.Error_InvalidExpressionStatement (report, GetLocation ($1)); + $$ = new StatementExpression (EmptyExpressionStatement.Instance); + } else { + $$ = new StatementExpression (s); + } + } + ; + +interactive_statement_expression + : expression + { + Expression expr = (Expression) $1; + ExpressionStatement s; + + s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location); + $$ = new StatementExpression (s); + } + | error + { + Error_SyntaxError (yyToken); + $$ = new EmptyStatement (GetLocation ($1)); + } + ; + +selection_statement + : if_statement + | switch_statement + ; + +if_statement + : IF open_parens_any boolean_expression CLOSE_PARENS + embedded_statement + { + if ($5 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new If ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | IF open_parens_any boolean_expression CLOSE_PARENS + embedded_statement ELSE embedded_statement + { + $$ = new If ((BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); + + if ($5 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($5)); + if ($7 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($7)); + } + ; + +switch_statement + : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE + { + start_block (GetLocation ($5)); + } + opt_switch_sections CLOSE_BRACE + { + $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, (List) $7, GetLocation ($1)); + end_block (GetLocation ($8)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($5), GetLocation ($8)); + } + ; + +opt_switch_sections + : /* empty */ + { + report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); + $$ = new List (); + } + | switch_sections + ; + +switch_sections + : switch_section + { + var sections = new List (4); + + sections.Add ((SwitchSection) $1); + $$ = sections; + } + | switch_sections switch_section + { + var sections = (List) $1; + + sections.Add ((SwitchSection) $2); + $$ = sections; + } + | error + { + Error_SyntaxError (yyToken); + $$ = new List (); + } + ; + +switch_section + : switch_labels + { + current_block = current_block.CreateSwitchBlock (lexer.Location); + } + statement_list + { + $$ = new SwitchSection ((List) $1, current_block); + } + ; + +switch_labels + : switch_label + { + var labels = new List (2); + + labels.Add ((SwitchLabel) $1); + $$ = labels; + } + | switch_labels switch_label + { + var labels = (List) ($1); + labels.Add ((SwitchLabel) $2); + + $$ = labels; + } + ; + +switch_label + : CASE constant_expression COLON + { + $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + | DEFAULT_COLON + { + $$ = new SwitchLabel (null, GetLocation ($1)); + } + ; + +iteration_statement + : while_statement + | do_statement + | for_statement + | foreach_statement + ; + +while_statement + : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new While ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +do_statement + : DO embedded_statement + WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON + { + $$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4), GetLocation ($6), GetLocation ($7)); + } + ; + +for_statement + : FOR open_parens_any + { + start_block (GetLocation ($2)); + current_block.IsCompilerGenerated = true; + } + for_statement_cont + { + $$ = $4; + } + ; + +// Has to use be extra rule to recover started block +for_statement_cont + : opt_for_initializer SEMICOLON + opt_for_condition SEMICOLON + opt_for_iterator CLOSE_PARENS + embedded_statement + { + if ($7 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($7)); + + For f = new For ((Statement) $1, (BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($-2)); + current_block.AddStatement (f); + + lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation ($4), GetLocation ($6)); + + $$ = end_block (GetLocation ($2)); + } + | error + { + Error_SyntaxError (yyToken); + $$ = end_block (current_block.StartLocation); + } + ; + +opt_for_initializer + : /* empty */ { $$ = new EmptyStatement (lexer.Location); } + | for_initializer + ; + +for_initializer + : variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); + } + opt_local_variable_initializer opt_variable_declarators + { + $$ = current_variable; + current_variable = null; + } + | statement_expression_list + ; + +opt_for_condition + : /* empty */ { $$ = null; } + | boolean_expression + ; + +opt_for_iterator + : /* empty */ { $$ = new EmptyStatement (lexer.Location); } + | for_iterator + ; + +for_iterator + : statement_expression_list + ; + +statement_expression_list + : statement_expression + | statement_expression_list COMMA statement_expression + { + var sl = $1 as StatementList; + if (sl == null) { + sl = new StatementList ((Statement) $1, (Statement) $3); + lbag.AddStatement (sl, GetLocation ($2)); + } else { + sl.Add ((Statement) $3); + lbag.AppendTo (sl, GetLocation ($2)); + } + + $$ = sl; + } + ; + +foreach_statement + : FOREACH open_parens_any type IN expression CLOSE_PARENS + { + report.Error (230, GetLocation ($1), "Type and identifier are both required in a foreach statement"); + $$ = null; + } + | FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS + { + start_block (GetLocation ($2)); + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + $$ = li; + } + embedded_statement + { + if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($9)); + + Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, GetLocation ($1)); + current_block.AddStatement (f); + + lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7)); + $$ = end_block (GetLocation ($7)); + } + ; + +jump_statement + : break_statement + | continue_statement + | goto_statement + | return_statement + | throw_statement + | yield_statement + ; + +break_statement + : BREAK SEMICOLON + { + $$ = new Break (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2)); + } + ; + +continue_statement + : CONTINUE SEMICOLON + { + $$ = new Continue (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2)); + } + ; + +goto_statement + : GOTO IDENTIFIER SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new Goto (lt.Value, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + | GOTO CASE constant_expression SEMICOLON + { + $$ = new GotoCase ((Expression) $3, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | GOTO DEFAULT SEMICOLON + { + $$ = new GotoDefault (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +return_statement + : RETURN opt_expression SEMICOLON + { + $$ = new Return ((Expression) $2, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + ; + +throw_statement + : THROW opt_expression SEMICOLON + { + $$ = new Throw ((Expression) $2, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + ; + +yield_statement + : IDENTIFIER RETURN opt_expression SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $1; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if ($3 == null) { + report.Error (1627, GetLocation ($4), "Expression expected after yield return"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + $$ = new Yield ((Expression) $3, lt.Location); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | IDENTIFIER BREAK SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $1; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + $$ = new YieldBreak (lt.Location); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +opt_expression + : /* empty */ + | expression + ; + +try_statement + : TRY block catch_clauses + { + $$ = new TryCatch ((Block) $2, (List) $3, GetLocation ($1), false); + } + | TRY block FINALLY block + { + $$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + | TRY block catch_clauses FINALLY block + { + $$ = new TryFinally (new TryCatch ((Block) $2, (List) $3, GetLocation ($1), true), (Block) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($4)); + } + | TRY block error + { + report.Error (1524, GetLocation ($1), "Expected catch or finally"); + $$ = null; + } + ; + +catch_clauses + : catch_clause + { + var l = new List (2); + + l.Add ((Catch) $1); + $$ = l; + } + | catch_clauses catch_clause + { + var l = (List) $1; + + Catch c = (Catch) $2; + if (l [0].IsGeneral) { + report.Error (1017, c.loc, "Try statement already has an empty catch block"); + } else { + if (c.IsGeneral) + l.Insert (0, c); + else + l.Add (c); + } + + $$ = l; + } + ; + +opt_identifier + : /* empty */ + | IDENTIFIER + ; + +catch_clause + : CATCH block + { + $$ = new Catch ((Block) $2, GetLocation ($1)); + } + | CATCH open_parens_any type opt_identifier CLOSE_PARENS + { + start_block (GetLocation ($2)); + var c = new Catch (current_block, GetLocation ($1)); + c.TypeExpression = (FullNamedExpression) $3; + + if ($4 != null) { + var lt = (Tokenizer.LocatedToken) $4; + c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (c.Variable); + } + + lbag.AddLocation (c, GetLocation ($2), GetLocation ($5)); + $$ = c; + } + block_prepared + { + $$ = $6; + } + | CATCH open_parens_any error + { + if (yyToken == Token.CLOSE_PARENS) { + report.Error (1015, lexer.Location, + "A type that derives from `System.Exception', `object', or `string' expected"); + } else { + Error_SyntaxError (yyToken); + } + + $$ = new Catch (null, GetLocation ($1)); + } + ; + +checked_statement + : CHECKED block + { + $$ = new Checked ((Block) $2, GetLocation ($1)); + } + ; + +unchecked_statement + : UNCHECKED block + { + $$ = new Unchecked ((Block) $2, GetLocation ($1)); + } + ; + +unsafe_statement + : UNSAFE + { + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation ($1)); + } block { + $$ = new Unsafe ((Block) $3, GetLocation ($1)); + } + ; + +lock_statement + : LOCK open_parens_any expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new Lock ((Expression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +fixed_statement + : FIXED open_parens_any variable_type IDENTIFIER + { + start_block (GetLocation ($2)); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) $3, li); + } + using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + { + $$ = current_variable; + current_variable = null; + } + embedded_statement + { + if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($10)); + + Fixed f = new Fixed ((Fixed.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); + current_block.AddStatement (f); + lbag.AddStatement (f, GetLocation ($2), GetLocation ($8)); + $$ = end_block (GetLocation ($8)); + } + ; + +using_statement + : USING open_parens_any variable_type IDENTIFIER + { + start_block (GetLocation ($2)); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); + } + using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + { + $$ = current_variable; + current_variable = null; + } + embedded_statement + { + if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($10)); + + Using u = new Using ((Using.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); + lbag.AddStatement (u, GetLocation ($2), GetLocation ($8)); + current_block.AddStatement (u); + $$ = end_block (GetLocation ($8)); + } + | USING open_parens_any expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + Using u = new Using ((Expression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement (u, GetLocation ($2), GetLocation ($4)); + $$ = u; + } + ; + +using_or_fixed_variable_initializer + : /* empty */ + { + report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + } + | ASSIGN variable_initializer + { + current_variable.Initializer = (Expression) $2; + $$ = current_variable; + } + ; + + +// LINQ + +query_expression + : first_from_clause query_body + { + lexer.query_parsing = false; + + Linq.AQueryClause from = $1 as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)$2; + $$ = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | nested_from_clause query_body + { + Linq.AQueryClause from = $1 as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)$2; + $$ = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + + // Bubble up COMPLETE_COMPLETION productions + | first_from_clause COMPLETE_COMPLETION { + lexer.query_parsing = false; + $$ = $1; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | nested_from_clause COMPLETE_COMPLETION { + $$ = $1; + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +first_from_clause + : FROM_FIRST IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $2; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1))); + } + | FROM_FIRST type IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $3; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + } + ); + } + ; + +nested_from_clause + : FROM IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $2; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1))); + } + | FROM type IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $3; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + } + ); + } + ; + +from_clause + : FROM IDENTIFIER IN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$5, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + | FROM type IDENTIFIER IN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $3; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + + $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$6, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + ; + +query_body + : opt_query_body_clauses select_or_group_clause opt_query_continuation + { + Linq.AQueryClause head = (Linq.AQueryClause)$2; + + if ($3 != null) + head.Next = (Linq.AQueryClause)$3; + + if ($1 != null) { + Linq.AQueryClause clause = (Linq.AQueryClause)$1; + clause.Tail.Next = head; + head = clause; + } + + $$ = head; + } + | opt_query_body_clauses COMPLETE_COMPLETION + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +select_or_group_clause + : SELECT + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + $$ = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | GROUP + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock)current_block); + } + expression + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + BY expression + { + $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($5)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +opt_query_body_clauses + : /* empty */ + | query_body_clauses + ; + +query_body_clauses + : query_body_clause + | query_body_clauses query_body_clause + { + ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$2; + $$ = $1; + } + ; + +query_body_clause + : from_clause + | let_clause + | where_clause + | join_clause + | orderby_clause + ; + +let_clause + : LET IDENTIFIER ASSIGN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)$5, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + ; + +where_clause + : WHERE + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + $$ = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +join_clause + : JOIN IDENTIFIER IN + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression ON + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression EQUALS + { + current_block.AddStatement (new ContextualReturn ((Expression) $8)); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression opt_join_into + { + current_block.AddStatement (new ContextualReturn ((Expression) $11)); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if ($12 == null) { + into = sn; + $$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); + } else { + // + // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions + // + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) $12; + into = new Linq.RangeVariable (lt.Value, lt.Location); + + $$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($12)); + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + | JOIN type IDENTIFIER IN + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression ON + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression EQUALS + { + current_block.AddStatement (new ContextualReturn ((Expression) $9)); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression opt_join_into + { + current_block.AddStatement (new ContextualReturn ((Expression) $12)); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) $3; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if ($13 == null) { + into = sn; + $$ = new Linq.Join (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + } else { + // + // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions + // + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) $13; + into = new Linq.RangeVariable (lt.Value, lt.Location); // TODO: + + $$ = new Linq.GroupJoin (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + ; + +opt_join_into + : /* empty */ + | INTO IDENTIFIER + { + $$ = $2; + } + ; + +orderby_clause + : ORDERBY + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + orderings + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + $$ = $3; + } + ; + +orderings + : order_by + | order_by COMMA + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + orderings_then_by + { + ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4; + $$ = $1; + } + ; + +orderings_then_by + : then_by + | orderings_then_by COMMA + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); + } + then_by + { + ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$4; + $$ = $1; + } + ; + +order_by + : expression + { + $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + } + | expression ASCENDING + { + $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + | expression DESCENDING + { + $$ = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + +then_by + : expression + { + $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + } + | expression ASCENDING + { + $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + | expression DESCENDING + { + $$ = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + + +opt_query_continuation + : /* empty */ + | INTO IDENTIFIER + { + // query continuation block is not linked with query block but with block + // before. This means each query can use same range variable names for + // different identifiers. + + current_block.SetEndLocation (GetLocation ($1)); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + query_body + { + var current_block = linq_clause_blocks.Pop (); + var lt = (Tokenizer.LocatedToken) $2; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation ($1)) { + next = (Linq.AQueryClause)$4 + }; + } + ; + +// +// Support for using the compiler as an interactive parser +// +// The INTERACTIVE_PARSER token is first sent to parse our +// productions; If the result is a Statement, the parsing +// is repeated, this time with INTERACTIVE_PARSE_WITH_BLOCK +// to setup the blocks in advance. +// +// This setup is here so that in the future we can add +// support for other constructs (type parsing, namespaces, etc) +// that do not require a block to be setup in advance +// + +interactive_parsing + : EVAL_STATEMENT_PARSER EOF + | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION + | EVAL_STATEMENT_PARSER + { + current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); + current_class = current_container; + + // (ref object retval) + Parameter [] mpar = new Parameter [1]; + mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); + + ParametersCompiled pars = new ParametersCompiled (mpar); + var mods = Modifiers.PUBLIC | Modifiers.STATIC; + if (settings.Unsafe) + mods |= Modifiers.UNSAFE; + + current_local_parameters = pars; + Method method = new Method ( + current_class, + null, // generic + new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), + mods, + new MemberName ("Host"), + pars, + null /* attributes */); + + current_container.AddMethod (method); + + oob_stack.Push (method); + ++lexer.parsing_block; + start_block (lexer.Location); + } + interactive_statement_list opt_COMPLETE_COMPLETION + { + --lexer.parsing_block; + Method method = (Method) oob_stack.Pop (); + + method.Block = (ToplevelBlock) end_block(lexer.Location); + + InteractiveResult = (Class) pop_current_class (); + current_local_parameters = null; + } + | EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit + ; + +interactive_compilation_unit + : opt_extern_alias_directives opt_using_directives + | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations + ; + +opt_COMPLETE_COMPLETION + : /* nothing */ + | COMPLETE_COMPLETION + ; + +close_brace_or_complete_completion + : CLOSE_BRACE + | COMPLETE_COMPLETION + ; + +// +// XML documentation code references micro parser +// +documentation_parsing + : DOC_SEE doc_cref + { + module.DocumentationBuilder.ParsedName = (MemberName) $2; + } + ; + +doc_cref + : doc_type_declaration_name opt_doc_method_sig + { + module.DocumentationBuilder.ParsedParameters = (List)$2; + } + | builtin_types opt_doc_method_sig + { + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; + module.DocumentationBuilder.ParsedParameters = (List)$2; + $$ = null; + } + | builtin_types DOT IDENTIFIER opt_doc_method_sig + { + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; + module.DocumentationBuilder.ParsedParameters = (List)$4; + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName (lt.Value); + } + | doc_type_declaration_name DOT THIS + { + $$ = new MemberName ((MemberName) $1, new MemberName (MemberCache.IndexerNameAlias)); + } + | doc_type_declaration_name DOT THIS OPEN_BRACKET + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_doc_parameters CLOSE_BRACKET + { + module.DocumentationBuilder.ParsedParameters = (List)$6; + $$ = new MemberName ((MemberName) $1, new MemberName (MemberCache.IndexerNameAlias)); + } + | EXPLICIT OPERATOR type opt_doc_method_sig + { + var p = (List)$4 ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) $3)); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; + $$ = null; + } + | IMPLICIT OPERATOR type opt_doc_method_sig + { + var p = (List)$4 ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) $3)); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; + $$ = null; + } + | OPERATOR overloadable_operator opt_doc_method_sig + { + var p = (List)$3 ?? new List (1); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = (Operator.OpType) $2; + $$ = null; + } + ; + +doc_type_declaration_name + : type_declaration_name + | doc_type_declaration_name DOT type_declaration_name + { + $$ = new MemberName (((MemberName) $1), (MemberName) $3); + } + ; + +opt_doc_method_sig + : /* empty */ + | OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_doc_parameters CLOSE_PARENS + { + $$ = $3; + } + ; + +opt_doc_parameters + : /* empty */ + { + $$ = new List (0); + } + | doc_parameters + ; + +doc_parameters + : doc_parameter + { + var parameters = new List (); + parameters.Add ((DocumentationParameter) $1); + $$ = parameters; + } + | doc_parameters COMMA doc_parameter + { + var parameters = $1 as List; + parameters.Add ((DocumentationParameter) $3); + $$ = parameters; + } + ; + +doc_parameter + : opt_parameter_modifier parameter_type + { + if ($1 != null) + $$ = new DocumentationParameter ((Parameter.Modifier) $1, (FullNamedExpression) $2); + else + $$ = new DocumentationParameter ((FullNamedExpression) $2); + } + ; + +%% + +// +// A class used to hold info about an operator declarator +// +class OperatorDeclaration { + public readonly Operator.OpType optype; + public readonly FullNamedExpression ret_type; + public readonly Location location; + + public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) + { + optype = op; + this.ret_type = ret_type; + this.location = location; + } +} + +void Error_ExpectingTypeName (Expression expr) +{ + if (expr is Invocation){ + report.Error (1002, expr.Location, "Expecting `;'"); + } else { + Expression.Error_InvalidExpressionStatement (report, expr.Location); + } +} + +void Error_ParameterModifierNotValid (string modifier, Location loc) +{ + report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", + modifier); +} + +void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) +{ + report.Error (1107, loc, "Duplicate parameter modifier `{0}'", + Parameter.GetModifierSignature (mod)); +} + +void Error_TypeExpected (Location loc) +{ + report.Error (1031, loc, "Type expected"); +} + +void Error_UnsafeCodeNotAllowed (Location loc) +{ + report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); +} + +void Warning_EmptyStatement (Location loc) +{ + report.Warning (642, 3, loc, "Possible mistaken empty statement"); +} + +void Error_NamedArgumentExpected (NamedArgument a) +{ + report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); +} + +void push_current_class (TypeContainer tc, object partial_token) +{ + if (module.Evaluator != null && current_container is ModuleContainer){ + tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; + if (undo == null) + undo = new Undo (); + undo.AddTypeContainer (current_container, tc); + } + + if (partial_token != null) + current_container = current_container.AddPartial (tc); + else + current_container = current_container.AddTypeContainer (tc); + + ++lexer.parsing_declaration; + current_class = tc; + ubag.PushTypeDeclaration (tc); +} + +DeclSpace pop_current_class () +{ + DeclSpace retval = current_class; + + current_class = current_class.Parent; + current_container = current_class.PartialContainer; + ubag.PopTypeDeclaration (); + + return retval; +} + +// +// Given the @class_name name, it creates a fully qualified name +// based on the containing declaration space +// +MemberName +MakeName (MemberName class_name) +{ + Namespace ns = current_namespace.NS; + + if (current_container == module) { + if (ns.Name.Length != 0) + return new MemberName (ns.MemberName, class_name); + else + return class_name; + } else { + return new MemberName (current_container.MemberName, class_name); + } +} + +[System.Diagnostics.Conditional ("FULL_AST")] +void StoreModifierLocation (object token, Location loc) +{ + if (lbag == null) + return; + + if (mod_locations == null) + mod_locations = new List> (); + + mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); +} + +List> GetModifierLocations () +{ + var result = mod_locations; + mod_locations = null; + return result; +} + +string CheckAttributeTarget (string a, Location l) +{ + switch (a) { + case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : + return a; + } + + report.Warning (658, 1, l, + "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); + return string.Empty; +} + +static bool IsUnaryOperator (Operator.OpType op) +{ + switch (op) { + + case Operator.OpType.LogicalNot: + case Operator.OpType.OnesComplement: + case Operator.OpType.Increment: + case Operator.OpType.Decrement: + case Operator.OpType.True: + case Operator.OpType.False: + case Operator.OpType.UnaryPlus: + case Operator.OpType.UnaryNegation: + return true; + } + return false; +} + +void syntax_error (Location l, string msg) +{ + report.Error (1003, l, "Syntax error, " + msg); +} + +Tokenizer lexer; + +public Tokenizer Lexer { + get { + return lexer; + } +} + +static CSharpParser () +{ + oob_stack = new Stack (); +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file) + : this (reader, file, file.NamespaceContainer.Module.Compiler.Report) +{ +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report) +{ + this.file = file; + current_namespace = file.NamespaceContainer; + + this.module = current_namespace.Module; + this.compiler = module.Compiler; + this.settings = compiler.Settings; + this.report = report; + + lang_version = settings.Version; + doc_support = settings.DocumentationFile != null; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes + oob_stack.Clear (); + lexer = new Tokenizer (reader, file, compiler); + + use_global_stacks = true; +} + +public void parse () +{ + eof_token = Token.EOF; + Tokenizer.LocatedToken.Initialize (); + + try { + if (yacc_verbose_flag > 1) + yyparse (lexer, new yydebug.yyDebugSimple ()); + else + yyparse (lexer); + + Tokenizer tokenizer = lexer as Tokenizer; + tokenizer.cleanup (); + } catch (Exception e){ + if (e is yyParser.yyUnexpectedEof) { + Error_SyntaxError (yyToken); + UnexpectedEOF = true; + return; + } + + if (e is yyParser.yyException) { + report.Error (-25, lexer.Location, "Parsing error"); + } else { + // Used by compiler-tester to test internal errors + if (yacc_verbose_flag > 0) + throw; + + report.Error (589, lexer.Location, "Internal compiler error during parsing"); + } + } +} + +void CheckToken (int error, int yyToken, string msg, Location loc) +{ + if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) + report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); + else + report.Error (error, loc, msg); +} + +string ConsumeStoredComment () +{ + string s = tmpComment; + tmpComment = null; + Lexer.doc_state = XmlCommentState.Allowed; + return s; +} + +void FeatureIsNotAvailable (Location loc, string feature) +{ + report.FeatureIsNotAvailable (compiler, loc, feature); +} + +Location GetLocation (object obj) +{ + var lt = obj as Tokenizer.LocatedToken; + if (lt != null) + return lt.Location; + + var mn = obj as MemberName; + if (mn != null) + return mn.Location; + + var expr = obj as Expression; + if (expr != null) + return expr.Location; + + return lexer.Location; +} + +public LocationsBag LocationsBag { + get { + return lbag; + } + set { + lbag = value; + } +} + +public UsingsBag UsingsBag { + get { + return ubag; + } + set { + ubag = value; + } +} + +void start_block (Location loc) +{ + if (current_block == null) { + current_block = new ToplevelBlock (compiler, current_local_parameters, loc); + parsing_anonymous_method = false; + } else if (parsing_anonymous_method) { + current_block = new ParametersBlock (current_block, current_local_parameters, loc); + parsing_anonymous_method = false; + } else { + current_block = new ExplicitBlock (current_block, loc, Location.Null); + } +} + +Block +end_block (Location loc) +{ + Block retval = current_block.Explicit; + retval.SetEndLocation (loc); + current_block = retval.Parent; + return retval; +} + +void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync, Location loc) +{ + oob_stack.Push (current_anonymous_method); + oob_stack.Push (current_local_parameters); + oob_stack.Push (current_variable); + + current_local_parameters = parameters; + if (isLambda) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (loc, "lambda expressions"); + + current_anonymous_method = new LambdaExpression (isAsync, loc); + } else { + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (loc, "anonymous methods"); + + current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); + } + + // Force the next block to be created as a ToplevelBlock + parsing_anonymous_method = true; +} + +/* + * Completes the anonymous method processing, if lambda_expr is null, this + * means that we have a Statement instead of an Expression embedded + */ +AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) +{ + AnonymousMethodExpression retval; + + current_anonymous_method.Block = anon_block; + retval = current_anonymous_method; + + current_variable = (BlockVariableDeclaration) oob_stack.Pop (); + current_local_parameters = (ParametersCompiled) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + + return retval; +} + +void Error_SyntaxError (int token) +{ + Error_SyntaxError (0, token, "Unexpected symbol"); +} + +void Error_SyntaxError (int error_code, int token, string msg) +{ + Lexer.CompleteOnEOF = false; + + // An error message has been reported by tokenizer + if (token == Token.ERROR) + return; + + string symbol = GetSymbolName (token); + string expecting = GetExpecting (); + var loc = lexer.Location - symbol.Length; + + if (error_code == 0) { + if (expecting == "`identifier'") { + if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { + report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); + return; + } + + error_code = 1001; + expecting = "identifier"; + } else if (expecting == "`)'") { + error_code = 1026; + } else { + error_code = 1525; + } + } + + if (string.IsNullOrEmpty (expecting)) + report.Error (error_code, loc, "{1} `{0}'", symbol, msg); + else + report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); +} + +string GetExpecting () +{ + int [] tokens = yyExpectingTokens (yyExpectingState); + var names = new List (tokens.Length); + bool has_type = false; + bool has_identifier = false; + for (int i = 0; i < tokens.Length; i++){ + int token = tokens [i]; + has_identifier |= token == Token.IDENTIFIER; + + string name = GetTokenName (token); + if (name == "") + continue; + + has_type |= name == "type"; + if (names.Contains (name)) + continue; + + names.Add (name); + } + + // + // Too many tokens to enumerate + // + if (names.Count > 8) + return null; + + if (has_type && has_identifier) + names.Remove ("identifier"); + + if (names.Count == 1) + return "`" + GetTokenName (tokens [0]) + "'"; + + StringBuilder sb = new StringBuilder (); + names.Sort (); + int count = names.Count; + for (int i = 0; i < count; i++){ + bool last = i + 1 == count; + if (last) + sb.Append ("or "); + sb.Append ('`'); + sb.Append (names [i]); + sb.Append (last ? "'" : count < 3 ? "' " : "', "); + } + return sb.ToString (); +} + + +string GetSymbolName (int token) +{ + switch (token){ + case Token.LITERAL: + return ((Constant)lexer.Value).GetValue ().ToString (); + case Token.IDENTIFIER: + return ((Tokenizer.LocatedToken)lexer.Value).Value; + + case Token.BOOL: + return "bool"; + case Token.BYTE: + return "byte"; + case Token.CHAR: + return "char"; + case Token.VOID: + return "void"; + case Token.DECIMAL: + return "decimal"; + case Token.DOUBLE: + return "double"; + case Token.FLOAT: + return "float"; + case Token.INT: + return "int"; + case Token.LONG: + return "long"; + case Token.SBYTE: + return "sbyte"; + case Token.SHORT: + return "short"; + case Token.STRING: + return "string"; + case Token.UINT: + return "uint"; + case Token.ULONG: + return "ulong"; + case Token.USHORT: + return "ushort"; + case Token.OBJECT: + return "object"; + + case Token.PLUS: + return "+"; + case Token.UMINUS: + case Token.MINUS: + return "-"; + case Token.BANG: + return "!"; + case Token.BITWISE_AND: + return "&"; + case Token.BITWISE_OR: + return "|"; + case Token.STAR: + return "*"; + case Token.PERCENT: + return "%"; + case Token.DIV: + return "/"; + case Token.CARRET: + return "^"; + case Token.OP_INC: + return "++"; + case Token.OP_DEC: + return "--"; + case Token.OP_SHIFT_LEFT: + return "<<"; + case Token.OP_SHIFT_RIGHT: + return ">>"; + case Token.OP_LT: + return "<"; + case Token.OP_GT: + return ">"; + case Token.OP_LE: + return "<="; + case Token.OP_GE: + return ">="; + case Token.OP_EQ: + return "=="; + case Token.OP_NE: + return "!="; + case Token.OP_AND: + return "&&"; + case Token.OP_OR: + return "||"; + case Token.OP_PTR: + return "->"; + case Token.OP_COALESCING: + return "??"; + case Token.OP_MULT_ASSIGN: + return "*="; + case Token.OP_DIV_ASSIGN: + return "/="; + case Token.OP_MOD_ASSIGN: + return "%="; + case Token.OP_ADD_ASSIGN: + return "+="; + case Token.OP_SUB_ASSIGN: + return "-="; + case Token.OP_SHIFT_LEFT_ASSIGN: + return "<<="; + case Token.OP_SHIFT_RIGHT_ASSIGN: + return ">>="; + case Token.OP_AND_ASSIGN: + return "&="; + case Token.OP_XOR_ASSIGN: + return "^="; + case Token.OP_OR_ASSIGN: + return "|="; + } + + return GetTokenName (token); +} + +static string GetTokenName (int token) +{ + switch (token){ + case Token.ABSTRACT: + return "abstract"; + case Token.AS: + return "as"; + case Token.ADD: + return "add"; + case Token.ASYNC: + return "async"; + case Token.BASE: + return "base"; + case Token.BREAK: + return "break"; + case Token.CASE: + return "case"; + case Token.CATCH: + return "catch"; + case Token.CHECKED: + return "checked"; + case Token.CLASS: + return "class"; + case Token.CONST: + return "const"; + case Token.CONTINUE: + return "continue"; + case Token.DEFAULT: + return "default"; + case Token.DELEGATE: + return "delegate"; + case Token.DO: + return "do"; + case Token.ELSE: + return "else"; + case Token.ENUM: + return "enum"; + case Token.EVENT: + return "event"; + case Token.EXPLICIT: + return "explicit"; + case Token.EXTERN: + case Token.EXTERN_ALIAS: + return "extern"; + case Token.FALSE: + return "false"; + case Token.FINALLY: + return "finally"; + case Token.FIXED: + return "fixed"; + case Token.FOR: + return "for"; + case Token.FOREACH: + return "foreach"; + case Token.GOTO: + return "goto"; + case Token.IF: + return "if"; + case Token.IMPLICIT: + return "implicit"; + case Token.IN: + return "in"; + case Token.INTERFACE: + return "interface"; + case Token.INTERNAL: + return "internal"; + case Token.IS: + return "is"; + case Token.LOCK: + return "lock"; + case Token.NAMESPACE: + return "namespace"; + case Token.NEW: + return "new"; + case Token.NULL: + return "null"; + case Token.OPERATOR: + return "operator"; + case Token.OUT: + return "out"; + case Token.OVERRIDE: + return "override"; + case Token.PARAMS: + return "params"; + case Token.PRIVATE: + return "private"; + case Token.PROTECTED: + return "protected"; + case Token.PUBLIC: + return "public"; + case Token.READONLY: + return "readonly"; + case Token.REF: + return "ref"; + case Token.RETURN: + return "return"; + case Token.REMOVE: + return "remove"; + case Token.SEALED: + return "sealed"; + case Token.SIZEOF: + return "sizeof"; + case Token.STACKALLOC: + return "stackalloc"; + case Token.STATIC: + return "static"; + case Token.STRUCT: + return "struct"; + case Token.SWITCH: + return "switch"; + case Token.THIS: + return "this"; + case Token.THROW: + return "throw"; + case Token.TRUE: + return "true"; + case Token.TRY: + return "try"; + case Token.TYPEOF: + return "typeof"; + case Token.UNCHECKED: + return "unchecked"; + case Token.UNSAFE: + return "unsafe"; + case Token.USING: + return "using"; + case Token.VIRTUAL: + return "virtual"; + case Token.VOLATILE: + return "volatile"; + case Token.WHERE: + return "where"; + case Token.WHILE: + return "while"; + case Token.ARGLIST: + return "__arglist"; + case Token.REFVALUE: + return "__refvalue"; + case Token.REFTYPE: + return "__reftype"; + case Token.MAKEREF: + return "__makeref"; + case Token.PARTIAL: + return "partial"; + case Token.ARROW: + return "=>"; + case Token.FROM: + case Token.FROM_FIRST: + return "from"; + case Token.JOIN: + return "join"; + case Token.ON: + return "on"; + case Token.EQUALS: + return "equals"; + case Token.SELECT: + return "select"; + case Token.GROUP: + return "group"; + case Token.BY: + return "by"; + case Token.LET: + return "let"; + case Token.ORDERBY: + return "orderby"; + case Token.ASCENDING: + return "ascending"; + case Token.DESCENDING: + return "descending"; + case Token.INTO: + return "into"; + case Token.GET: + return "get"; + case Token.SET: + return "set"; + case Token.OPEN_BRACE: + return "{"; + case Token.CLOSE_BRACE: + return "}"; + case Token.OPEN_BRACKET: + case Token.OPEN_BRACKET_EXPR: + return "["; + case Token.CLOSE_BRACKET: + return "]"; + case Token.OPEN_PARENS_CAST: + case Token.OPEN_PARENS_LAMBDA: + case Token.OPEN_PARENS: + return "("; + case Token.CLOSE_PARENS: + return ")"; + case Token.DOT: + return "."; + case Token.COMMA: + return ","; + case Token.DEFAULT_COLON: + return "default:"; + case Token.COLON: + return ":"; + case Token.SEMICOLON: + return ";"; + case Token.TILDE: + return "~"; + + case Token.PLUS: + case Token.UMINUS: + case Token.MINUS: + case Token.BANG: + case Token.OP_LT: + case Token.OP_GT: + case Token.BITWISE_AND: + case Token.BITWISE_OR: + case Token.STAR: + case Token.PERCENT: + case Token.DIV: + case Token.CARRET: + case Token.OP_INC: + case Token.OP_DEC: + case Token.OP_SHIFT_LEFT: + case Token.OP_SHIFT_RIGHT: + case Token.OP_LE: + case Token.OP_GE: + case Token.OP_EQ: + case Token.OP_NE: + case Token.OP_AND: + case Token.OP_OR: + case Token.OP_PTR: + case Token.OP_COALESCING: + case Token.OP_MULT_ASSIGN: + case Token.OP_DIV_ASSIGN: + case Token.OP_MOD_ASSIGN: + case Token.OP_ADD_ASSIGN: + case Token.OP_SUB_ASSIGN: + case Token.OP_SHIFT_LEFT_ASSIGN: + case Token.OP_SHIFT_RIGHT_ASSIGN: + case Token.OP_AND_ASSIGN: + case Token.OP_XOR_ASSIGN: + case Token.OP_OR_ASSIGN: + return ""; + + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.VOID: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + case Token.USHORT: + case Token.OBJECT: + return "type"; + + case Token.ASSIGN: + return "="; + case Token.OP_GENERICS_LT: + case Token.GENERIC_DIMENSION: + return "<"; + case Token.OP_GENERICS_GT: + return ">"; + case Token.INTERR: + case Token.INTERR_NULLABLE: + return "?"; + case Token.DOUBLE_COLON: + return "::"; + case Token.LITERAL: + return "value"; + case Token.IDENTIFIER: + return "identifier"; + + case Token.EOF: + return "end-of-file"; + + // All of these are internal. + case Token.NONE: + case Token.ERROR: + case Token.FIRST_KEYWORD: + case Token.EVAL_COMPILATION_UNIT_PARSER: + case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: + case Token.EVAL_STATEMENT_PARSER: + case Token.LAST_KEYWORD: + case Token.GENERATE_COMPLETION: + case Token.COMPLETE_COMPLETION: + return ""; + + // A bit more robust. + default: + return yyNames [token]; + } +} + +/* end end end */ +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs new file mode 100644 index 0000000000..6054c44625 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs @@ -0,0 +1,3584 @@ +// +// cs-tokenizer.cs: The Tokenizer for the C# compiler +// This also implements the preprocessor +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// +// +using System; +using System.Text; +using System.Collections.Generic; +using System.Globalization; +using System.Diagnostics; + +namespace Mono.CSharp +{ + /// + /// Tokenizer for C# source code. + /// + public class Tokenizer : yyParser.yyInput + { + class KeywordEntry + { + public readonly T Token; + public KeywordEntry Next; + public readonly char[] Value; + + public KeywordEntry (string value,T token) + { + this.Value = value.ToCharArray (); + this.Token = token; + } + } + + sealed class IdentifiersComparer : IEqualityComparer + { + readonly int length; + + public IdentifiersComparer (int length) + { + this.length = length; + } + + public bool Equals (char[] x, char[] y) + { + for (int i = 0; i < length; ++i) + if (x [i] != y [i]) + return false; + + return true; + } + + public int GetHashCode (char[] obj) + { + int h = 0; + for (int i = 0; i < length; ++i) + h = (h << 5) - h + obj [i]; + + return h; + } + } + + // + // This class has to be used in the parser only, it reuses token + // details after each parse + // + public class LocatedToken + { + int row, column; + string value; + static LocatedToken[] buffer; + static int pos; + + private LocatedToken () + { + } + + public static LocatedToken Create (int row, int column) + { + return Create (null, row, column); + } + + public static LocatedToken Create (string value, int row, int column) + { + // + // TODO: I am not very happy about the logic but it's the best + // what I could come up with for now. + // Ideally we should be using just tiny buffer (256 elements) which + // is enough to hold all details for currect stack and recycle elements + // poped from the stack but there is a trick needed to recycle + // them properly. + // + LocatedToken entry; + if (pos >= buffer.Length) { + entry = new LocatedToken (); + } else { + entry = buffer [pos]; + if (entry == null) { + entry = new LocatedToken (); + buffer [pos] = entry; + } + + ++pos; + } + entry.value = value; + entry.row = row; + entry.column = column; + return entry; + } + + // + // Used for token not required by expression evaluator + // + [Conditional ("FULL_AST")] + public static void CreateOptional (int row, int col, ref object token) + { + token = Create (row, col); + } + + public static void Initialize () + { + if (buffer == null) + buffer = new LocatedToken [10000]; + pos = 0; + } + + public Location Location { + get { return new Location (row, column); } + } + + public string Value { + get { return value; } + } + } + + public enum PreprocessorDirective + { + Invalid = 0, + + Region = 1, + Endregion = 2, + If = 3 | RequiresArgument, + Endif = 4, + Elif = 5 | RequiresArgument, + Else = 6, + Define = 7 | RequiresArgument, + Undef = 8 | RequiresArgument, + Error = 9, + Warning = 10, + Pragma = 11 | CustomArgumentsParsing, + Line = 12, + + CustomArgumentsParsing = 1 << 10, + RequiresArgument = 1 << 11 + } + + SeekableStreamReader reader; + SourceFile ref_name; + CompilationSourceFile file_name; + CompilerContext context; + bool hidden = false; + int ref_line = 1; + int line = 1; + int col = 0; + int previous_col; + int current_token; + int tab_size; + bool handle_get_set = false; + bool handle_remove_add = false; + bool handle_where = false; + bool handle_typeof = false; + bool lambda_arguments_parsing; + List escaped_identifiers; + int parsing_generic_less_than; + readonly bool doc_processing; + + // + // Used mainly for parser optimizations. Some expressions for instance + // can appear only in block (including initializer, base initializer) + // scope only + // + public int parsing_block; + internal bool query_parsing; + + // + // When parsing type only, useful for ambiguous nullable types + // + public int parsing_type; + + // + // Set when parsing generic declaration (type or method header) + // + public bool parsing_generic_declaration; + public bool parsing_generic_declaration_doc; + + // + // The value indicates that we have not reach any declaration or + // namespace yet + // + public int parsing_declaration; + public bool parsing_attribute_section; + + // + // The special characters to inject on streams to run the unit parser + // in the special expression mode. Using private characters from + // Plane Sixteen (U+100000 to U+10FFFD) + // + // This character is only tested just before the tokenizer is about to report + // an error; So on the regular operation mode, this addition will have no + // impact on the tokenizer's performance. + // + + public const int EvalStatementParserCharacter = 0x100000; + public const int EvalCompilationUnitParserCharacter = 0x100001; + public const int EvalUsingDeclarationsParserCharacter = 0x100002; + public const int DocumentationXref = 0x100003; + + // + // XML documentation buffer. The save point is used to divide + // comments on types and comments on members. + // + StringBuilder xml_comment_buffer; + + // + // See comment on XmlCommentState enumeration. + // + XmlCommentState xml_doc_state = XmlCommentState.Allowed; + + // + // Whether tokens have been seen on this line + // + bool tokens_seen = false; + + // + // Set to true once the GENERATE_COMPLETION token has bee + // returned. This helps produce one GENERATE_COMPLETION, + // as many COMPLETE_COMPLETION as necessary to complete the + // AST tree and one final EOF. + // + bool generated; + + // + // Whether a token has been seen on the file + // This is needed because `define' is not allowed to be used + // after a token has been seen. + // + bool any_token_seen; + + // + // Class variables + // + static readonly KeywordEntry[][] keywords; + static readonly KeywordEntry[][] keywords_preprocessor; + static readonly Dictionary keyword_strings; // TODO: HashSet + static readonly NumberStyles styles; + static readonly NumberFormatInfo csharp_format_info; + + // Pragma arguments + static readonly char[] pragma_warning = "warning".ToCharArray (); + static readonly char[] pragma_warning_disable = "disable".ToCharArray (); + static readonly char[] pragma_warning_restore = "restore".ToCharArray (); + static readonly char[] pragma_checksum = "checksum".ToCharArray (); + static readonly char[] simple_whitespaces = new char[] { ' ', '\t' }; + bool startsLine = true; + internal SpecialsBag sbag; + + public bool PropertyParsing { + get { return handle_get_set; } + set { handle_get_set = value; } + } + + public bool EventParsing { + get { return handle_remove_add; } + set { handle_remove_add = value; } + } + + public bool ConstraintsParsing { + get { return handle_where; } + set { handle_where = value; } + } + + public bool TypeOfParsing { + get { return handle_typeof; } + set { handle_typeof = value; } + } + + public int TabSize { + get { return tab_size; } + set { tab_size = value; } + } + + public XmlCommentState doc_state { + get { return xml_doc_state; } + set { + if (value == XmlCommentState.Allowed) { + check_incorrect_doc_comment (); + reset_doc_comment (); + } + xml_doc_state = value; + } + } + + // + // This is used to trigger completion generation on the parser + public bool CompleteOnEOF; + + void AddEscapedIdentifier (Location loc) + { + if (escaped_identifiers == null) + escaped_identifiers = new List (); + + escaped_identifiers.Add (loc); + } + + public bool IsEscapedIdentifier (MemberName name) + { + return escaped_identifiers != null && escaped_identifiers.Contains (name.Location); + } + + // + // Values for the associated token returned + // + internal int putback_char; // Used by repl only + object val; + + // + // Pre-processor + // + const int TAKING = 1; + const int ELSE_SEEN = 4; + const int PARENT_TAKING = 8; + const int REGION = 16; + + // + // pre-processor if stack state: + // + Stack ifstack; + + static System.Text.StringBuilder string_builder; + const int max_id_size = 512; + static readonly char[] id_builder = new char [max_id_size]; + public static Dictionary[] identifiers = new Dictionary[max_id_size + 1]; + const int max_number_size = 512; + static char[] number_builder = new char [max_number_size]; + static int number_pos; + static char[] value_builder = new char[256]; + + public int Line { + get { + return ref_line; + } + } + + // + // This is used when the tokenizer needs to save + // the current position as it needs to do some parsing + // on its own to deamiguate a token in behalf of the + // parser. + // + Stack position_stack = new Stack (2); + + class Position + { + public int position; + public int line; + public int ref_line; + public int col; + public bool hidden; + public int putback_char; + public int previous_col; + public Stack ifstack; + public int parsing_generic_less_than; + public int current_token; + public object val; + + public Position (Tokenizer t) + { + position = t.reader.Position; + line = t.line; + ref_line = t.ref_line; + col = t.col; + hidden = t.hidden; + putback_char = t.putback_char; + previous_col = t.previous_col; + if (t.ifstack != null && t.ifstack.Count != 0) { + // There is no simple way to clone Stack all + // methods reverse the order + var clone = t.ifstack.ToArray (); + Array.Reverse (clone); + ifstack = new Stack (clone); + } + parsing_generic_less_than = t.parsing_generic_less_than; + current_token = t.current_token; + val = t.val; + } + } + + public Tokenizer (SeekableStreamReader input, CompilationSourceFile file, CompilerContext ctx) + { + this.ref_name = file; + this.file_name = file; + this.context = ctx; + reader = input; + + putback_char = -1; + + xml_comment_buffer = new StringBuilder (); + doc_processing = ctx.Settings.DocumentationFile != null; + + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + tab_size = 4; + else + tab_size = 8; + + // + // FIXME: This could be `Location.Push' but we have to + // find out why the MS compiler allows this + // + Mono.CSharp.Location.Push (file, file); + } + + public void PushPosition () + { + position_stack.Push (new Position (this)); + } + + public void PopPosition () + { + Position p = position_stack.Pop (); + + reader.Position = p.position; + ref_line = p.ref_line; + line = p.line; + col = p.col; + hidden = p.hidden; + putback_char = p.putback_char; + previous_col = p.previous_col; + ifstack = p.ifstack; + parsing_generic_less_than = p.parsing_generic_less_than; + current_token = p.current_token; + val = p.val; + } + + // Do not reset the position, ignore it. + public void DiscardPosition () + { + position_stack.Pop (); + } + + static void AddKeyword (string kw, int token) + { + keyword_strings.Add (kw, null); + + AddKeyword (keywords, kw, token); +} + + static void AddPreprocessorKeyword (string kw, PreprocessorDirective directive) + { + AddKeyword (keywords_preprocessor, kw, directive); + } + + static void AddKeyword (KeywordEntry[][] keywords, string kw, T token) + { + int length = kw.Length; + if (keywords[length] == null) { + keywords[length] = new KeywordEntry['z' - '_' + 1]; + } + + int char_index = kw[0] - '_'; + var kwe = keywords[length][char_index]; + if (kwe == null) { + keywords[length][char_index] = new KeywordEntry (kw, token); + return; + } + + while (kwe.Next != null) { + kwe = kwe.Next; + } + + kwe.Next = new KeywordEntry (kw, token); + } + + // + // Class initializer + // + static Tokenizer () + { + keyword_strings = new Dictionary (); + + // 11 is the length of the longest keyword for now + keywords = new KeywordEntry[11][]; + + AddKeyword ("__arglist", Token.ARGLIST); + AddKeyword ("__makeref", Token.MAKEREF); + AddKeyword ("__reftype", Token.REFTYPE); + AddKeyword ("__refvalue", Token.REFVALUE); + AddKeyword ("abstract", Token.ABSTRACT); + AddKeyword ("as", Token.AS); + AddKeyword ("add", Token.ADD); + AddKeyword ("base", Token.BASE); + AddKeyword ("bool", Token.BOOL); + AddKeyword ("break", Token.BREAK); + AddKeyword ("byte", Token.BYTE); + AddKeyword ("case", Token.CASE); + AddKeyword ("catch", Token.CATCH); + AddKeyword ("char", Token.CHAR); + AddKeyword ("checked", Token.CHECKED); + AddKeyword ("class", Token.CLASS); + AddKeyword ("const", Token.CONST); + AddKeyword ("continue", Token.CONTINUE); + AddKeyword ("decimal", Token.DECIMAL); + AddKeyword ("default", Token.DEFAULT); + AddKeyword ("delegate", Token.DELEGATE); + AddKeyword ("do", Token.DO); + AddKeyword ("double", Token.DOUBLE); + AddKeyword ("else", Token.ELSE); + AddKeyword ("enum", Token.ENUM); + AddKeyword ("event", Token.EVENT); + AddKeyword ("explicit", Token.EXPLICIT); + AddKeyword ("extern", Token.EXTERN); + AddKeyword ("false", Token.FALSE); + AddKeyword ("finally", Token.FINALLY); + AddKeyword ("fixed", Token.FIXED); + AddKeyword ("float", Token.FLOAT); + AddKeyword ("for", Token.FOR); + AddKeyword ("foreach", Token.FOREACH); + AddKeyword ("goto", Token.GOTO); + AddKeyword ("get", Token.GET); + AddKeyword ("if", Token.IF); + AddKeyword ("implicit", Token.IMPLICIT); + AddKeyword ("in", Token.IN); + AddKeyword ("int", Token.INT); + AddKeyword ("interface", Token.INTERFACE); + AddKeyword ("internal", Token.INTERNAL); + AddKeyword ("is", Token.IS); + AddKeyword ("lock", Token.LOCK); + AddKeyword ("long", Token.LONG); + AddKeyword ("namespace", Token.NAMESPACE); + AddKeyword ("new", Token.NEW); + AddKeyword ("null", Token.NULL); + AddKeyword ("object", Token.OBJECT); + AddKeyword ("operator", Token.OPERATOR); + AddKeyword ("out", Token.OUT); + AddKeyword ("override", Token.OVERRIDE); + AddKeyword ("params", Token.PARAMS); + AddKeyword ("private", Token.PRIVATE); + AddKeyword ("protected", Token.PROTECTED); + AddKeyword ("public", Token.PUBLIC); + AddKeyword ("readonly", Token.READONLY); + AddKeyword ("ref", Token.REF); + AddKeyword ("remove", Token.REMOVE); + AddKeyword ("return", Token.RETURN); + AddKeyword ("sbyte", Token.SBYTE); + AddKeyword ("sealed", Token.SEALED); + AddKeyword ("set", Token.SET); + AddKeyword ("short", Token.SHORT); + AddKeyword ("sizeof", Token.SIZEOF); + AddKeyword ("stackalloc", Token.STACKALLOC); + AddKeyword ("static", Token.STATIC); + AddKeyword ("string", Token.STRING); + AddKeyword ("struct", Token.STRUCT); + AddKeyword ("switch", Token.SWITCH); + AddKeyword ("this", Token.THIS); + AddKeyword ("throw", Token.THROW); + AddKeyword ("true", Token.TRUE); + AddKeyword ("try", Token.TRY); + AddKeyword ("typeof", Token.TYPEOF); + AddKeyword ("uint", Token.UINT); + AddKeyword ("ulong", Token.ULONG); + AddKeyword ("unchecked", Token.UNCHECKED); + AddKeyword ("unsafe", Token.UNSAFE); + AddKeyword ("ushort", Token.USHORT); + AddKeyword ("using", Token.USING); + AddKeyword ("virtual", Token.VIRTUAL); + AddKeyword ("void", Token.VOID); + AddKeyword ("volatile", Token.VOLATILE); + AddKeyword ("while", Token.WHILE); + AddKeyword ("partial", Token.PARTIAL); + AddKeyword ("where", Token.WHERE); + + // LINQ keywords + AddKeyword ("from", Token.FROM); + AddKeyword ("join", Token.JOIN); + AddKeyword ("on", Token.ON); + AddKeyword ("equals", Token.EQUALS); + AddKeyword ("select", Token.SELECT); + AddKeyword ("group", Token.GROUP); + AddKeyword ("by", Token.BY); + AddKeyword ("let", Token.LET); + AddKeyword ("orderby", Token.ORDERBY); + AddKeyword ("ascending", Token.ASCENDING); + AddKeyword ("descending", Token.DESCENDING); + AddKeyword ("into", Token.INTO); + + // Contextual async keywords + AddKeyword ("async", Token.ASYNC); + AddKeyword ("await", Token.AWAIT); + + keywords_preprocessor = new KeywordEntry[10][]; + + AddPreprocessorKeyword ("region", PreprocessorDirective.Region); + AddPreprocessorKeyword ("endregion", PreprocessorDirective.Endregion); + AddPreprocessorKeyword ("if", PreprocessorDirective.If); + AddPreprocessorKeyword ("endif", PreprocessorDirective.Endif); + AddPreprocessorKeyword ("elif", PreprocessorDirective.Elif); + AddPreprocessorKeyword ("else", PreprocessorDirective.Else); + AddPreprocessorKeyword ("define", PreprocessorDirective.Define); + AddPreprocessorKeyword ("undef", PreprocessorDirective.Undef); + AddPreprocessorKeyword ("error", PreprocessorDirective.Error); + AddPreprocessorKeyword ("warning", PreprocessorDirective.Warning); + AddPreprocessorKeyword ("pragma", PreprocessorDirective.Pragma); + AddPreprocessorKeyword ("line", PreprocessorDirective.Line); + + csharp_format_info = NumberFormatInfo.InvariantInfo; + styles = NumberStyles.Float; + + string_builder = new System.Text.StringBuilder (); + } + + int GetKeyword (char[] id, int id_len) + { + // + // Keywords are stored in an array of arrays grouped by their + // length and then by the first character + // + if (id_len >= keywords.Length || keywords [id_len] == null) + return -1; + + int first_index = id [0] - '_'; + if (first_index > 'z' - '_') + return -1; + + var kwe = keywords [id_len] [first_index]; + if (kwe == null) + return -1; + + int res; + do { + res = kwe.Token; + for (int i = 1; i < id_len; ++i) { + if (id [i] != kwe.Value [i]) { + res = 0; + kwe = kwe.Next; + break; + } + } + } while (res == 0 && kwe != null); + + if (res == 0) + return -1; + + int next_token; + switch (res) { + case Token.GET: + case Token.SET: + if (!handle_get_set) + res = -1; + break; + case Token.REMOVE: + case Token.ADD: + if (!handle_remove_add) + res = -1; + break; + case Token.EXTERN: + if (parsing_declaration == 0) + res = Token.EXTERN_ALIAS; + break; + case Token.DEFAULT: + if (peek_token () == Token.COLON) { + token (); + res = Token.DEFAULT_COLON; + } + break; + case Token.WHERE: + if (!handle_where && !query_parsing) + res = -1; + break; + case Token.FROM: + // + // A query expression is any expression that starts with `from identifier' + // followed by any token except ; , = + // + if (!query_parsing) { + if (lambda_arguments_parsing) { + res = -1; + break; + } + + PushPosition (); + // HACK: to disable generics micro-parser, because PushPosition does not + // store identifiers array + parsing_generic_less_than = 1; + switch (xtoken ()) { + case Token.IDENTIFIER: + case Token.INT: + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.DECIMAL: + case Token.FLOAT: + case Token.LONG: + case Token.OBJECT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + next_token = xtoken (); + if (next_token == Token.SEMICOLON || next_token == Token.COMMA || next_token == Token.EQUALS) + goto default; + + res = Token.FROM_FIRST; + query_parsing = true; + if (context.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (context, Location, "query expressions"); + break; + case Token.VOID: + Expression.Error_VoidInvalidInTheContext (Location, Report); + break; + default: + PopPosition (); + // HACK: A token is not a keyword so we need to restore identifiers buffer + // which has been overwritten before we grabbed the identifier + id_builder [0] = 'f'; id_builder [1] = 'r'; id_builder [2] = 'o'; id_builder [3] = 'm'; + return -1; + } + PopPosition (); + } + break; + case Token.JOIN: + case Token.ON: + case Token.EQUALS: + case Token.SELECT: + case Token.GROUP: + case Token.BY: + case Token.LET: + case Token.ORDERBY: + case Token.ASCENDING: + case Token.DESCENDING: + case Token.INTO: + if (!query_parsing) + res = -1; + break; + + case Token.USING: + case Token.NAMESPACE: + // TODO: some explanation needed + check_incorrect_doc_comment (); + break; + + case Token.PARTIAL: + if (parsing_block > 0) { + res = -1; + break; + } + + // Save current position and parse next token. + PushPosition (); + + next_token = token (); + bool ok = (next_token == Token.CLASS) || + (next_token == Token.STRUCT) || + (next_token == Token.INTERFACE) || + (next_token == Token.VOID); + + PopPosition (); + + if (ok) { + if (next_token == Token.VOID) { + if (context.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (context, Location, "partial methods"); + } else if (context.Settings.Version == LanguageVersion.ISO_1) + Report.FeatureIsNotAvailable (context, Location, "partial types"); + + return res; + } + + if (next_token < Token.LAST_KEYWORD) { + Report.Error (267, Location, + "The `partial' modifier can be used only immediately before `class', `struct', `interface', or `void' keyword"); + return token (); + } + + res = -1; + break; + + // TODO: async, it's modifiers context only + case Token.ASYNC: + if (context.Settings.Version != LanguageVersion.Future) { + res = -1; + } + break; + + // TODO: async, it's async block context only + case Token.AWAIT: + if (context.Settings.Version != LanguageVersion.Future) { + res = -1; + } + + break; + } + + return res; + return res; + } + + static PreprocessorDirective GetPreprocessorDirective (char[] id, int id_len) + { + // + // Keywords are stored in an array of arrays grouped by their + // length and then by the first character + // + if (id_len >= keywords_preprocessor.Length || keywords_preprocessor[id_len] == null) + return PreprocessorDirective.Invalid; + + int first_index = id[0] - '_'; + if (first_index > 'z' - '_') + return PreprocessorDirective.Invalid; + + var kwe = keywords_preprocessor[id_len][first_index]; + if (kwe == null) + return PreprocessorDirective.Invalid; + + PreprocessorDirective res = PreprocessorDirective.Invalid; + do { + res = kwe.Token; + for (int i = 1; i < id_len; ++i) { + if (id[i] != kwe.Value[i]) { + res = 0; + kwe = kwe.Next; + break; + } + } + } while (res == PreprocessorDirective.Invalid && kwe != null); + + return res; + } + + public Location Location { + get { + return new Location (ref_line, hidden ? -1 : col); + } + } + + static bool is_identifier_start_character (int c) + { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter ((char)c); + } + + static bool is_identifier_part_character (char c) + { + if (c >= 'a' && c <= 'z') + return true; + + if (c >= 'A' && c <= 'Z') + return true; + + if (c == '_' || (c >= '0' && c <= '9')) + return true; + + if (c < 0x80) + return false; + + return Char.IsLetter (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation; + } + + public static bool IsKeyword (string s) + { + return keyword_strings.ContainsKey (s); + } + + // + // Open parens micro parser. Detects both lambda and cast ambiguity. + // + int TokenizeOpenParens () + { + int ptoken; + current_token = -1; + + int bracket_level = 0; + bool is_type = false; + bool can_be_type = false; + + while (true) { + ptoken = current_token; + token (); + + switch (current_token) { + case Token.CLOSE_PARENS: + token (); + + // + // Expression inside parens is lambda, (int i) => + // + if (current_token == Token.ARROW) + return Token.OPEN_PARENS_LAMBDA; + + // + // Expression inside parens is single type, (int[]) + // + if (is_type) + return Token.OPEN_PARENS_CAST; + + // + // Expression is possible cast, look at next token, (T)null + // + if (can_be_type) { + switch (current_token) { + case Token.OPEN_PARENS: + case Token.BANG: + case Token.TILDE: + case Token.IDENTIFIER: + case Token.LITERAL: + case Token.BASE: + case Token.CHECKED: + case Token.DELEGATE: + case Token.FALSE: + case Token.FIXED: + case Token.NEW: + case Token.NULL: + case Token.SIZEOF: + case Token.THIS: + case Token.THROW: + case Token.TRUE: + case Token.TYPEOF: + case Token.UNCHECKED: + case Token.UNSAFE: + case Token.DEFAULT: + + // + // These can be part of a member access + // + case Token.INT: + case Token.UINT: + case Token.SHORT: + case Token.USHORT: + case Token.LONG: + case Token.ULONG: + case Token.DOUBLE: + case Token.FLOAT: + case Token.CHAR: + case Token.BYTE: + case Token.DECIMAL: + case Token.BOOL: + return Token.OPEN_PARENS_CAST; + } + } + return Token.OPEN_PARENS; + + case Token.DOT: + case Token.DOUBLE_COLON: + if (ptoken != Token.IDENTIFIER && ptoken != Token.OP_GENERICS_GT) + goto default; + + continue; + + case Token.IDENTIFIER: + switch (ptoken) { + case Token.DOT: + if (bracket_level == 0) { + is_type = false; + can_be_type = true; + } + + continue; + case Token.OP_GENERICS_LT: + case Token.COMMA: + case Token.DOUBLE_COLON: + case -1: + if (bracket_level == 0) + can_be_type = true; + continue; + default: + can_be_type = is_type = false; + continue; + } + + case Token.OBJECT: + case Token.STRING: + case Token.BOOL: + case Token.DECIMAL: + case Token.FLOAT: + case Token.DOUBLE: + case Token.SBYTE: + case Token.BYTE: + case Token.SHORT: + case Token.USHORT: + case Token.INT: + case Token.UINT: + case Token.LONG: + case Token.ULONG: + case Token.CHAR: + case Token.VOID: + if (bracket_level == 0) + is_type = true; + continue; + + case Token.COMMA: + if (bracket_level == 0) { + bracket_level = 100; + can_be_type = is_type = false; + } + continue; + + case Token.OP_GENERICS_LT: + case Token.OPEN_BRACKET: + if (bracket_level++ == 0) + is_type = true; + continue; + + case Token.OP_GENERICS_GT: + case Token.CLOSE_BRACKET: + --bracket_level; + continue; + + case Token.INTERR_NULLABLE: + case Token.STAR: + if (bracket_level == 0) + is_type = true; + continue; + + case Token.REF: + case Token.OUT: + can_be_type = is_type = false; + continue; + + default: + return Token.OPEN_PARENS; + } + } + } + + public static bool IsValidIdentifier (string s) + { + if (s == null || s.Length == 0) + return false; + + if (!is_identifier_start_character (s [0])) + return false; + + for (int i = 1; i < s.Length; i ++) + if (! is_identifier_part_character (s [i])) + return false; + + return true; + } + + bool parse_less_than () + { + start: + int the_token = token (); + if (the_token == Token.OPEN_BRACKET) { + do { + the_token = token (); + } while (the_token != Token.CLOSE_BRACKET); + the_token = token (); + } else if (the_token == Token.IN || the_token == Token.OUT) { + the_token = token (); + } + switch (the_token) { + case Token.IDENTIFIER: + case Token.OBJECT: + case Token.STRING: + case Token.BOOL: + case Token.DECIMAL: + case Token.FLOAT: + case Token.DOUBLE: + case Token.SBYTE: + case Token.BYTE: + case Token.SHORT: + case Token.USHORT: + case Token.INT: + case Token.UINT: + case Token.LONG: + case Token.ULONG: + case Token.CHAR: + case Token.VOID: + break; + case Token.OP_GENERICS_GT: + case Token.IN: + case Token.OUT: + return true; + + default: + return false; + } + again: + the_token = token (); + + if (the_token == Token.OP_GENERICS_GT) + return true; + else if (the_token == Token.COMMA || the_token == Token.DOT || the_token == Token.DOUBLE_COLON) + goto start; + else if (the_token == Token.INTERR_NULLABLE || the_token == Token.STAR) + goto again; + else if (the_token == Token.OP_GENERICS_LT) { + if (!parse_less_than ()) + return false; + goto again; + } else if (the_token == Token.OPEN_BRACKET) { + rank_specifiers: + the_token = token (); + if (the_token == Token.CLOSE_BRACKET) + goto again; + else if (the_token == Token.COMMA) + goto rank_specifiers; + return false; + } + + return false; + } + + bool parse_generic_dimension (out int dimension) + { + dimension = 1; + + again: + int the_token = token (); + if (the_token == Token.OP_GENERICS_GT) + return true; + else if (the_token == Token.COMMA) { + dimension++; + goto again; + } + + return false; + } + + public int peek_token () + { + int the_token; + + PushPosition (); + the_token = token (); + PopPosition (); + + return the_token; + } + + // + // Tonizes `?' using custom disambiguous rules to return one + // of following tokens: INTERR_NULLABLE, OP_COALESCING, INTERR + // + // Tricky expression look like: + // + // Foo ? a = x ? b : c; + // + int TokenizePossibleNullableType () + { + if (parsing_block == 0 || parsing_type > 0) + return Token.INTERR_NULLABLE; + + int d = peek_char (); + if (d == '?') { + get_char (); + return Token.OP_COALESCING; + } + + switch (current_token) { + case Token.CLOSE_PARENS: + case Token.TRUE: + case Token.FALSE: + case Token.NULL: + case Token.LITERAL: + return Token.INTERR; + } + + if (d != ' ') { + if (d == ',' || d == ';' || d == '>') + return Token.INTERR_NULLABLE; + if (d == '*' || (d >= '0' && d <= '9')) + return Token.INTERR; + } + + PushPosition (); + current_token = Token.NONE; + int next_token; + switch (xtoken ()) { + case Token.LITERAL: + case Token.TRUE: + case Token.FALSE: + case Token.NULL: + case Token.THIS: + case Token.NEW: + next_token = Token.INTERR; + break; + + case Token.SEMICOLON: + case Token.COMMA: + case Token.CLOSE_PARENS: + case Token.OPEN_BRACKET: + case Token.OP_GENERICS_GT: + case Token.INTERR: + next_token = Token.INTERR_NULLABLE; + break; + + default: + next_token = -1; + break; + } + + if (next_token == -1) { + switch (xtoken ()) { + case Token.COMMA: + case Token.SEMICOLON: + case Token.OPEN_BRACE: + case Token.CLOSE_PARENS: + case Token.IN: + next_token = Token.INTERR_NULLABLE; + break; + + case Token.COLON: + next_token = Token.INTERR; + break; + + default: + int ntoken; + int interrs = 1; + int colons = 0; + // + // All shorcuts failed, do it hard way + // + while ((ntoken = xtoken ()) != Token.EOF) { + if (ntoken == Token.SEMICOLON) + break; + + if (ntoken == Token.COLON) { + if (++colons == interrs) + break; + continue; + } + + if (ntoken == Token.INTERR) { + ++interrs; + continue; + } + } + + next_token = colons != interrs ? Token.INTERR_NULLABLE : Token.INTERR; + break; + } + } + + PopPosition (); + return next_token; + } + + bool decimal_digits (int c) + { + int d; + bool seen_digits = false; + + if (c != -1){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) c; + } + + // + // We use peek_char2, because decimal_digits needs to do a + // 2-character look-ahead (5.ToString for example). + // + while ((d = peek_char2 ()) != -1){ + if (d >= '0' && d <= '9'){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) d; + get_char (); + seen_digits = true; + } else + break; + } + + return seen_digits; + } + + static bool is_hex (int e) + { + return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } + + static TypeCode real_type_suffix (int c) + { + switch (c){ + case 'F': case 'f': + return TypeCode.Single; + case 'D': case 'd': + return TypeCode.Double; + case 'M': case 'm': + return TypeCode.Decimal; + default: + return TypeCode.Empty; + } + } + + ILiteralConstant integer_type_suffix (ulong ul, int c, Location loc) + { + bool is_unsigned = false; + bool is_long = false; + + if (c != -1){ + bool scanning = true; + do { + switch (c){ + case 'U': case 'u': + if (is_unsigned) + scanning = false; + is_unsigned = true; + get_char (); + break; + + case 'l': + if (!is_unsigned){ + // + // if we have not seen anything in between + // report this error + // + Report.Warning (78, 4, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)"); + } + + goto case 'L'; + + case 'L': + if (is_long) + scanning = false; + is_long = true; + get_char (); + break; + + default: + scanning = false; + break; + } + c = peek_char (); + } while (scanning); + } + + if (is_long && is_unsigned){ + return new ULongLiteral (context.BuiltinTypes, ul, loc); + } + + if (is_unsigned){ + // uint if possible, or ulong else. + + if ((ul & 0xffffffff00000000) == 0) + return new UIntLiteral (context.BuiltinTypes, (uint) ul, loc); + else + return new ULongLiteral (context.BuiltinTypes, ul, loc); + } else if (is_long){ + // long if possible, ulong otherwise + if ((ul & 0x8000000000000000) != 0) + return new ULongLiteral (context.BuiltinTypes, ul, loc); + else + return new LongLiteral (context.BuiltinTypes, (long) ul, loc); + } else { + // int, uint, long or ulong in that order + if ((ul & 0xffffffff00000000) == 0){ + uint ui = (uint) ul; + + if ((ui & 0x80000000) != 0) + return new UIntLiteral (context.BuiltinTypes, ui, loc); + else + return new IntLiteral (context.BuiltinTypes, (int) ui, loc); + } else { + if ((ul & 0x8000000000000000) != 0) + return new ULongLiteral (context.BuiltinTypes, ul, loc); + else + return new LongLiteral (context.BuiltinTypes, (long) ul, loc); + } + } + } + + // + // given `c' as the next char in the input decide whether + // we need to convert to a special type, and then choose + // the best representation for the integer + // + ILiteralConstant adjust_int (int c, Location loc) + { + try { + if (number_pos > 9){ + ulong ul = (uint) (number_builder [0] - '0'); + + for (int i = 1; i < number_pos; i++){ + ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0'))); + } + + return integer_type_suffix (ul, c, loc); + } else { + uint ui = (uint) (number_builder [0] - '0'); + + for (int i = 1; i < number_pos; i++){ + ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0'))); + } + + return integer_type_suffix (ui, c, loc); + } + } catch (OverflowException) { + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + catch (FormatException) { + Report.Error (1013, Location, "Invalid number"); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } + + ILiteralConstant adjust_real (TypeCode t, Location loc) + { + string s = new string (number_builder, 0, number_pos); + const string error_details = "Floating-point constant is outside the range of type `{0}'"; + + switch (t){ + case TypeCode.Decimal: + try { + return new DecimalLiteral (context.BuiltinTypes, decimal.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, Location, error_details, "decimal"); + return new DecimalLiteral (context.BuiltinTypes, 0, loc); + } + case TypeCode.Single: + try { + return new FloatLiteral (context.BuiltinTypes, float.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, Location, error_details, "float"); + return new FloatLiteral (context.BuiltinTypes, 0, loc); + } + default: + try { + return new DoubleLiteral (context.BuiltinTypes, double.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, loc, error_details, "double"); + return new DoubleLiteral (context.BuiltinTypes, 0, loc); + } + } + } + + ILiteralConstant handle_hex (Location loc) + { + int d; + ulong ul; + + get_char (); + while ((d = peek_char ()) != -1){ + if (is_hex (d)){ + number_builder [number_pos++] = (char) d; + get_char (); + } else + break; + } + + string s = new String (number_builder, 0, number_pos); + + try { + if (number_pos <= 8) + ul = System.UInt32.Parse (s, NumberStyles.HexNumber); + else + ul = System.UInt64.Parse (s, NumberStyles.HexNumber); + + return integer_type_suffix (ul, peek_char (), loc); + } catch (OverflowException){ + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + catch (FormatException) { + Report.Error (1013, Location, "Invalid number"); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } + + // + // Invoked if we know we have .digits or digits + // + int is_number (int c) + { + ILiteralConstant res; + +#if FULL_AST + int read_start = reader.Position - 1; +#endif + number_pos = 0; + var loc = Location; + + if (c >= '0' && c <= '9'){ + if (c == '0'){ + int peek = peek_char (); + + if (peek == 'x' || peek == 'X') { + val = res = handle_hex (loc); +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1); +#endif + + return Token.LITERAL; + } + } + decimal_digits (c); + c = get_char (); + } + + // + // We need to handle the case of + // "1.1" vs "1.string" (LITERAL_FLOAT vs NUMBER DOT IDENTIFIER) + // + bool is_real = false; + if (c == '.'){ + if (decimal_digits ('.')){ + is_real = true; + c = get_char (); + } else { + putback ('.'); + number_pos--; + val = res = adjust_int (-1, loc); + +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1); +#endif + return Token.LITERAL; + } + } + + if (c == 'e' || c == 'E'){ + is_real = true; + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) c; + c = get_char (); + + if (c == '+'){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '+'; + c = -1; + } else if (c == '-') { + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '-'; + c = -1; + } else { + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '+'; + } + + decimal_digits (c); + c = get_char (); + } + + var type = real_type_suffix (c); + if (type == TypeCode.Empty && !is_real) { + putback (c); + res = adjust_int (c, loc); + } else { + is_real = true; + + if (type == TypeCode.Empty) { + putback (c); + } + + res = adjust_real (type, loc); + } + + val = res; + +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - (type == TypeCode.Empty ? 1 : 0)); +#endif + + return Token.LITERAL; + } + + // + // Accepts exactly count (4 or 8) hex, no more no less + // + int getHex (int count, out int surrogate, out bool error) + { + int i; + int total = 0; + int c; + int top = count != -1 ? count : 4; + + get_char (); + error = false; + surrogate = 0; + for (i = 0; i < top; i++){ + c = get_char (); + + if (c >= '0' && c <= '9') + c = (int) c - (int) '0'; + else if (c >= 'A' && c <= 'F') + c = (int) c - (int) 'A' + 10; + else if (c >= 'a' && c <= 'f') + c = (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + total = (total * 16) + c; + if (count == -1){ + int p = peek_char (); + if (p == -1) + break; + if (!is_hex ((char)p)) + break; + } + } + + if (top == 8) { + if (total > 0x0010FFFF) { + error = true; + return 0; + } + + if (total >= 0x00010000) { + surrogate = ((total - 0x00010000) % 0x0400 + 0xDC00); + total = ((total - 0x00010000) / 0x0400 + 0xD800); + } + } + + return total; + } + + int escape (int c, out int surrogate) + { + bool error; + int d; + int v; + + d = peek_char (); + if (c != '\\') { + surrogate = 0; + return c; + } + + switch (d){ + case 'a': + v = '\a'; break; + case 'b': + v = '\b'; break; + case 'n': + v = '\n'; break; + case 't': + v = '\t'; break; + case 'v': + v = '\v'; break; + case 'r': + v = '\r'; break; + case '\\': + v = '\\'; break; + case 'f': + v = '\f'; break; + case '0': + v = 0; break; + case '"': + v = '"'; break; + case '\'': + v = '\''; break; + case 'x': + v = getHex (-1, out surrogate, out error); + if (error) + goto default; + return v; + case 'u': + case 'U': + return EscapeUnicode (d, out surrogate); + default: + surrogate = 0; + Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", ((char)d).ToString ()); + return d; + } + + get_char (); + surrogate = 0; + return v; + } + + int EscapeUnicode (int ch, out int surrogate) + { + bool error; + if (ch == 'U') { + ch = getHex (8, out surrogate, out error); + } else { + ch = getHex (4, out surrogate, out error); + } + + if (error) + Report.Error (1009, Location, "Unrecognized escape sequence"); + + return ch; + } + + int get_char () + { + int x; + if (putback_char != -1) { + x = putback_char; + putback_char = -1; + } else { + x = reader.Read (); + } + + if (x == '\r') { + if (peek_char () == '\n') { + putback_char = -1; + } + + x = '\n'; + advance_line (); + } else if (x == '\n') { + advance_line (); + } else { + col++; + } + return x; + } + + void advance_line () + { + line++; + ref_line++; + previous_col = col; + col = 0; + startsLine = true; + } + + int peek_char () + { + if (putback_char == -1) + putback_char = reader.Read (); + return putback_char; + } + + int peek_char2 () + { + if (putback_char != -1) + return putback_char; + return reader.Peek (); + } + + void putback (int c) + { + if (putback_char != -1){ + Console.WriteLine ("Col: " + col); + Console.WriteLine ("Row: " + line); + Console.WriteLine ("Name: " + ref_name.Name); + Console.WriteLine ("Current [{0}] putting back [{1}] ", putback_char, c); + throw new Exception ("This should not happen putback on putback"); + } + if (c == '\n' || col == 0) { + // It won't happen though. + line--; + ref_line--; + col = previous_col; + } + else + col--; + putback_char = c; + } + + public bool advance () + { + return peek_char () != -1 || CompleteOnEOF; + } + + public Object Value { + get { + return val; + } + } + + public Object value () + { + return val; + } + + public int token () + { + current_token = xtoken (); + return current_token; + } + + int TokenizePreprocessorIdentifier (out int c) + { + int endLine, endCol; + return TokenizePreprocessorIdentifier (out c, out endLine, out endCol); + } + + int TokenizePreprocessorIdentifier (out int c, out int endLine, out int endCol) + { + // skip over white space + do { + c = get_char (); + } while (c == ' ' || c == '\t'); + + endLine = line; + endCol = col; + int pos = 0; + while (c != -1 && c >= 'a' && c <= 'z') { + id_builder[pos++] = (char) c; + endCol = col + 1; + c = get_char (); + if (c == '\\') { + int peek = peek_char (); + if (peek == 'U' || peek == 'u') { + int surrogate; + c = EscapeUnicode (c, out surrogate); + if (surrogate != 0) { + if (is_identifier_part_character ((char) c)) { + id_builder[pos++] = (char) c; + } + c = surrogate; + } + } + } + } + + return pos; + } + + PreprocessorDirective get_cmd_arg (out string arg) + { + int c; + int startLine = line, startCol = col; + + tokens_seen = false; + arg = ""; + + int endLine, endCol; + var cmd = GetPreprocessorDirective (id_builder, TokenizePreprocessorIdentifier (out c, out endLine, out endCol)); + + if ((cmd & PreprocessorDirective.CustomArgumentsParsing) != 0) { + sbag.AddPreProcessorDirective (startLine, startCol, line, col, cmd, null); + return cmd; + } + + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + int has_identifier_argument = (int)(cmd & PreprocessorDirective.RequiresArgument); + + int pos = 0; + + while (c != -1 && c != '\n' && c != '\r') { + if (c == '\\' && has_identifier_argument >= 0) { + if (has_identifier_argument != 0) { + has_identifier_argument = 1; + + int peek = peek_char (); + if (peek == 'U' || peek == 'u') { + int surrogate; + c = EscapeUnicode (c, out surrogate); + if (surrogate != 0) { + if (is_identifier_part_character ((char)c)) { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder [pos++] = (char)c; + } + c = surrogate; + } + } + } else { + has_identifier_argument = -1; + } + } else if (c == '/' && peek_char () == '/') { + // + // Eat single-line comments + // + get_char (); + do { + c = get_char (); + } while (c != -1 && c != '\n'); + + break; + } + + endLine = line; + endCol = col; + + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + c = get_char (); + } + + if (pos != 0) { + if (pos > max_id_size) + arg = new string (value_builder, 0, pos); + else + arg = InternIdentifier (value_builder, pos); + + // Eat any trailing whitespaces + arg = arg.Trim (simple_whitespaces); + } + sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol, cmd, arg); + + return cmd; + } + + // + // Handles the #line directive + // + bool PreProcessLine (string arg) + { + if (arg.Length == 0) + return false; + + if (arg == "default"){ + ref_line = line; + ref_name = file_name; + hidden = false; + Location.Push (file_name, ref_name); + return true; + } else if (arg == "hidden"){ + hidden = true; + return true; + } + + try { + int pos; + + if ((pos = arg.IndexOf (' ')) != -1 && pos != 0){ + ref_line = System.Int32.Parse (arg.Substring (0, pos)); + pos++; + + char [] quotes = { '\"' }; + + string name = arg.Substring (pos). Trim (quotes); + ref_name = context.LookupFile (file_name, name); + file_name.AddIncludeFile (ref_name); + hidden = false; + Location.Push (file_name, ref_name); + } else { + ref_line = System.Int32.Parse (arg); + hidden = false; + } + } catch { + return false; + } + + return true; + } + + // + // Handles #define and #undef + // + void PreProcessDefinition (bool is_define, string ident, bool caller_is_taking) + { + if (ident.Length == 0 || ident == "true" || ident == "false"){ + Report.Error (1001, Location, "Missing identifier to pre-processor directive"); + return; + } + + if (ident.IndexOfAny (simple_whitespaces) != -1){ + Error_EndLineExpected (); + return; + } + + if (!is_identifier_start_character (ident [0])) + Report.Error (1001, Location, "Identifier expected: {0}", ident); + + foreach (char c in ident.Substring (1)){ + if (!is_identifier_part_character (c)){ + Report.Error (1001, Location, "Identifier expected: {0}", ident); + return; + } + } + + if (!caller_is_taking) + return; + + if (is_define) { + // + // #define ident + // + if (context.Settings.IsConditionalSymbolDefined (ident)) + return; + + file_name.AddDefine (ident); + } else { + // + // #undef ident + // + file_name.AddUndefine (ident); + } + } + + byte read_hex (out bool error) + { + int total; + int c = get_char (); + + if ((c >= '0') && (c <= '9')) + total = (int) c - (int) '0'; + else if ((c >= 'A') && (c <= 'F')) + total = (int) c - (int) 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + total = (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + total *= 16; + c = get_char (); + + if ((c >= '0') && (c <= '9')) + total += (int) c - (int) '0'; + else if ((c >= 'A') && (c <= 'F')) + total += (int) c - (int) 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + total += (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + error = false; + return (byte) total; + } + + // + // Parses #pragma checksum + // + bool ParsePragmaChecksum () + { + // + // The syntax is ` "foo.txt" "{guid}" "hash"' + // + int c = get_char (); + + if (c != '"') + return false; + + string_builder.Length = 0; + while (c != -1 && c != '\n') { + c = get_char (); + if (c == '"') { + c = get_char (); + break; + } + + string_builder.Append ((char) c); + } + + if (string_builder.Length == 0) { + Report.Warning (1709, 1, Location, "Filename specified for preprocessor directive is empty"); + } + + // TODO: Any white-spaces count + if (c != ' ') + return false; + + SourceFile file = context.LookupFile (file_name, string_builder.ToString ()); + + if (get_char () != '"' || get_char () != '{') + return false; + + bool error; + byte[] guid_bytes = new byte [16]; + int i = 0; + + for (; i < 4; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + } + + if (get_char () != '-') + return false; + + for (; i < 10; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + + guid_bytes [i++] = read_hex (out error); + if (error) + return false; + + if (get_char () != '-') + return false; + } + + for (; i < 16; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + } + + if (get_char () != '}' || get_char () != '"') + return false; + + // TODO: Any white-spaces count + c = get_char (); + if (c != ' ') + return false; + + if (get_char () != '"') + return false; + + // Any length of checksum + List checksum_bytes = new List (16); + + c = peek_char (); + while (c != '"' && c != -1) { + checksum_bytes.Add (read_hex (out error)); + if (error) + return false; + + c = peek_char (); + } + + if (c == '/') { + ReadSingleLineComment (); + } else if (get_char () != '"') { + return false; + } + + file.SetChecksum (guid_bytes, checksum_bytes.ToArray ()); + ref_name.AutoGenerated = true; + return true; + } + + bool IsTokenIdentifierEqual (char[] identifier) + { + for (int i = 0; i < identifier.Length; ++i) { + if (identifier[i] != id_builder[i]) + return false; + } + + return true; + } + + int TokenizePragmaNumber (ref int c) + { + number_pos = 0; + + int number; + + if (c >= '0' && c <= '9') { + decimal_digits (c); + uint ui = (uint) (number_builder[0] - '0'); + + try { + for (int i = 1; i < number_pos; i++) { + ui = checked ((ui * 10) + ((uint) (number_builder[i] - '0'))); + } + + number = (int) ui; + } catch (OverflowException) { + Error_NumericConstantTooLong (); + number = -1; + } + + + c = get_char (); + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + if (c == ',') { + c = get_char (); + } + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + } else { + number = -1; + if (c == '/') { + ReadSingleLineComment (); + } else { + Report.Warning (1692, 1, Location, "Invalid number"); + + // Read everything till the end of the line or file + do { + c = get_char (); + } while (c != -1 && c != '\n'); + } + } + + return number; + } + + + void ReadSingleLineComment () + { + if (peek_char () != '/') + Report.Warning (1696, 1, Location, "Single-line comment or end-of-line expected"); + sbag.StartComment (SpecialsBag.CommentType.Single, startsLine, line, col - 1); + // Read everything till the end of the line or file + int c; + do { + c = get_char (); + sbag.PushCommentChar (c); + var pc = peek_char (); + if (pc == '\n' || pc == -1) + sbag.EndComment (line, col + 1); + } while (c != -1 && c != '\n'); + } + + /// + /// Handles #pragma directive + /// + void ParsePragmaDirective (string arg) + { + int c; + int length = TokenizePreprocessorIdentifier (out c); + if (length == pragma_warning.Length && IsTokenIdentifierEqual (pragma_warning)) { + length = TokenizePreprocessorIdentifier (out c); + + // + // #pragma warning disable + // #pragma warning restore + // + if (length == pragma_warning_disable.Length) { + bool disable = IsTokenIdentifierEqual (pragma_warning_disable); + if (disable || IsTokenIdentifierEqual (pragma_warning_restore)) { + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + var loc = Location; + + if (c == '\n' || c == '/') { + if (c == '/') + ReadSingleLineComment (); + + // + // Disable/Restore all warnings + // + if (disable) { + Report.RegisterWarningRegion (loc).WarningDisable (loc.Row); + } else { + Report.RegisterWarningRegion (loc).WarningEnable (loc.Row); + } + } else { + // + // Disable/Restore a warning or group of warnings + // + int code; + do { + code = TokenizePragmaNumber (ref c); + if (code > 0) { + if (disable) { + Report.RegisterWarningRegion (loc).WarningDisable (loc, code, Report); + } else { + Report.RegisterWarningRegion (loc).WarningEnable (loc, code, Report); + } + } + } while (code >= 0 && c != '\n' && c != -1); + } + + return; + } + } + + Report.Warning (1634, 1, Location, "Expected disable or restore"); + return; + } + + // + // #pragma checksum + // + if (length == pragma_checksum.Length && IsTokenIdentifierEqual (pragma_checksum)) { + if (c != ' ' || !ParsePragmaChecksum ()) { + Report.Warning (1695, 1, Location, + "Invalid #pragma checksum syntax. Expected \"filename\" \"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\" \"XXXX...\""); + } + + return; + } + + Report.Warning (1633, 1, Location, "Unrecognized #pragma directive"); + } + + bool eval_val (string s) + { + if (s == "true") + return true; + if (s == "false") + return false; + + return file_name.IsConditionalDefined (context, s); + } + + bool pp_primary (ref string s) + { + s = s.Trim (); + int len = s.Length; + + if (len > 0){ + char c = s [0]; + + if (c == '('){ + s = s.Substring (1); + bool val = pp_expr (ref s, false); + if (s.Length > 0 && s [0] == ')'){ + s = s.Substring (1); + return val; + } + Error_InvalidDirective (); + return false; + } + + if (is_identifier_start_character (c)){ + int j = 1; + + while (j < len){ + c = s [j]; + + if (is_identifier_part_character (c)){ + j++; + continue; + } + bool v = eval_val (s.Substring (0, j)); + s = s.Substring (j); + return v; + } + bool vv = eval_val (s); + s = ""; + return vv; + } + } + Error_InvalidDirective (); + return false; + } + + bool pp_unary (ref string s) + { + s = s.Trim (); + int len = s.Length; + + if (len > 0){ + if (s [0] == '!'){ + if (len > 1 && s [1] == '='){ + Error_InvalidDirective (); + return false; + } + s = s.Substring (1); + return ! pp_primary (ref s); + } else + return pp_primary (ref s); + } else { + Error_InvalidDirective (); + return false; + } + } + + bool pp_eq (ref string s) + { + bool va = pp_unary (ref s); + + s = s.Trim (); + int len = s.Length; + if (len > 0){ + if (s [0] == '='){ + if (len > 2 && s [1] == '='){ + s = s.Substring (2); + return va == pp_unary (ref s); + } else { + Error_InvalidDirective (); + return false; + } + } else if (s [0] == '!' && len > 1 && s [1] == '='){ + s = s.Substring (2); + + return va != pp_unary (ref s); + + } + } + + return va; + + } + + bool pp_and (ref string s) + { + bool va = pp_eq (ref s); + + s = s.Trim (); + int len = s.Length; + if (len > 0){ + if (s [0] == '&'){ + if (len > 2 && s [1] == '&'){ + s = s.Substring (2); + return (va & pp_and (ref s)); + } else { + Error_InvalidDirective (); + return false; + } + } + } + return va; + } + + // + // Evaluates an expression for `#if' or `#elif' + // + bool pp_expr (ref string s, bool isTerm) + { + bool va = pp_and (ref s); + s = s.Trim (); + int len = s.Length; + if (len > 0){ + char c = s [0]; + + if (c == '|'){ + if (len > 2 && s [1] == '|'){ + s = s.Substring (2); + return va | pp_expr (ref s, isTerm); + } else { + Error_InvalidDirective (); + return false; + } + } + if (isTerm) { + Error_EndLineExpected (); + return false; + } + } + + return va; + } + + bool eval (string s) + { + bool v = pp_expr (ref s, true); + s = s.Trim (); + if (s.Length != 0){ + return false; + } + + return v; + } + + void Error_NumericConstantTooLong () + { + Report.Error (1021, Location, "Integral constant is too large"); + } + + void Error_InvalidDirective () + { + Report.Error (1517, Location, "Invalid preprocessor directive"); + } + + void Error_UnexpectedDirective (string extra) + { + Report.Error ( + 1028, Location, + "Unexpected processor directive ({0})", extra); + } + + void Error_TokensSeen () + { + Report.Error (1032, Location, + "Cannot define or undefine preprocessor symbols after first token in file"); + } + + void Eror_WrongPreprocessorLocation () + { + Report.Error (1040, Location, + "Preprocessor directives must appear as the first non-whitespace character on a line"); + } + + void Error_EndLineExpected () + { + Report.Error (1025, Location, "Single-line comment or end-of-line expected"); + } + + // + // Raises a warning when tokenizer found documentation comment + // on unexpected place + // + void WarningMisplacedComment (Location loc) + { + if (doc_state != XmlCommentState.Error) { + doc_state = XmlCommentState.Error; + Report.Warning (1587, 2, loc, "XML comment is not placed on a valid language element"); + } + } + + // + // if true, then the code continues processing the code + // if false, the code stays in a loop until another directive is + // reached. + // When caller_is_taking is false we ignore all directives except the ones + // which can help us to identify where the #if block ends + bool ParsePreprocessingDirective (bool caller_is_taking) + { + string arg; + bool region_directive = false; + + var directive = get_cmd_arg (out arg); + + // + // The first group of pre-processing instructions is always processed + // + switch (directive) { + case PreprocessorDirective.Region: + region_directive = true; + arg = "true"; + goto case PreprocessorDirective.If; + + case PreprocessorDirective.Endregion: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #region for this #endregion"); + return true; + } + int pop = ifstack.Pop (); + + if ((pop & REGION) == 0) + Report.Error (1027, Location, "Expected `#endif' directive"); + + return caller_is_taking; + + case PreprocessorDirective.If: + if (ifstack == null) + ifstack = new Stack (2); + + int flags = region_directive ? REGION : 0; + if (ifstack.Count == 0){ + flags |= PARENT_TAKING; + } else { + int state = ifstack.Peek (); + if ((state & TAKING) != 0) { + flags |= PARENT_TAKING; + } + } + + if (eval (arg) && caller_is_taking) { + ifstack.Push (flags | TAKING); + return true; + } + ifstack.Push (flags); + return false; + + case PreprocessorDirective.Endif: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #endif"); + return true; + } else { + pop = ifstack.Pop (); + + if ((pop & REGION) != 0) + Report.Error (1038, Location, "#endregion directive expected"); + + if (arg.Length != 0) { + Error_EndLineExpected (); + } + + if (ifstack.Count == 0) + return true; + + int state = ifstack.Peek (); + return (state & TAKING) != 0; + } + + case PreprocessorDirective.Elif: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #elif"); + return true; + } else { + int state = ifstack.Pop (); + + if ((state & REGION) != 0) { + Report.Error (1038, Location, "#endregion directive expected"); + return true; + } + + if ((state & ELSE_SEEN) != 0){ + Error_UnexpectedDirective ("#elif not valid after #else"); + return true; + } + + if ((state & TAKING) != 0) { + ifstack.Push (0); + return false; + } + + if (eval (arg) && ((state & PARENT_TAKING) != 0)){ + ifstack.Push (state | TAKING); + return true; + } + + ifstack.Push (state); + return false; + } + + case PreprocessorDirective.Else: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #else"); + return true; + } else { + int state = ifstack.Peek (); + + if ((state & REGION) != 0) { + Report.Error (1038, Location, "#endregion directive expected"); + return true; + } + + if ((state & ELSE_SEEN) != 0){ + Error_UnexpectedDirective ("#else within #else"); + return true; + } + + ifstack.Pop (); + + if (arg.Length != 0) { + Error_EndLineExpected (); + return true; + } + + bool ret = false; + if ((state & PARENT_TAKING) != 0) { + ret = (state & TAKING) == 0; + + if (ret) + state |= TAKING; + else + state &= ~TAKING; + } + + ifstack.Push (state | ELSE_SEEN); + + return ret; + } + case PreprocessorDirective.Define: + if (any_token_seen){ + Error_TokensSeen (); + return caller_is_taking; + } + PreProcessDefinition (true, arg, caller_is_taking); + return caller_is_taking; + + case PreprocessorDirective.Undef: + if (any_token_seen){ + Error_TokensSeen (); + return caller_is_taking; + } + PreProcessDefinition (false, arg, caller_is_taking); + return caller_is_taking; + + case PreprocessorDirective.Invalid: + Report.Error (1024, Location, "Wrong preprocessor directive"); + return true; + } + + // + // These are only processed if we are in a `taking' block + // + if (!caller_is_taking) + return false; + + switch (directive){ + case PreprocessorDirective.Error: + Report.Error (1029, Location, "#error: '{0}'", arg); + return true; + + case PreprocessorDirective.Warning: + Report.Warning (1030, 1, Location, "#warning: `{0}'", arg); + return true; + + case PreprocessorDirective.Pragma: + if (context.Settings.Version == LanguageVersion.ISO_1) { + Report.FeatureIsNotAvailable (context, Location, "#pragma"); + } + + ParsePragmaDirective (arg); + return true; + + case PreprocessorDirective.Line: + if (!PreProcessLine (arg)) + Report.Error ( + 1576, Location, + "The line number specified for #line directive is missing or invalid"); + return caller_is_taking; + } + + throw new NotImplementedException (directive.ToString ()); + } + + private int consume_string (bool quoted) + { + int c; + int pos = 0; + Location start_location = Location; + if (quoted) + start_location = start_location - 1; + +#if FULL_AST + int reader_pos = reader.Position; +#endif + + while (true){ + c = get_char (); + if (c == '"') { + if (quoted && peek_char () == '"') { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + get_char (); + continue; + } + + string s; + if (pos == 0) + s = string.Empty; + else if (pos <= 4) + s = InternIdentifier (value_builder, pos); + else + s = new string (value_builder, 0, pos); + + ILiteralConstant res = new StringLiteral (context.BuiltinTypes, s, start_location); + val = res; +#if FULL_AST + res.ParsedValue = quoted ? + reader.ReadChars (reader_pos - 2, reader.Position - 1) : + reader.ReadChars (reader_pos - 1, reader.Position); +#endif + + return Token.LITERAL; + } + + if (c == '\n') { + if (!quoted) { + Report.Error (1010, Location, "Newline in constant"); + val = new StringLiteral (context.BuiltinTypes, new string (value_builder, 0, pos), start_location); + return Token.LITERAL; + } + } else if (c == '\\' && !quoted) { + int surrogate; + c = escape (c, out surrogate); + if (c == -1) + return Token.ERROR; + if (surrogate != 0) { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + c = surrogate; + } + } else if (c == -1) { + Report.Error (1039, Location, "Unterminated string literal"); + return Token.EOF; + } + + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + } + } + + private int consume_identifier (int s) + { + int res = consume_identifier (s, false); + + if (doc_state == XmlCommentState.Allowed) + doc_state = XmlCommentState.NotAllowed; + startsLine = false; + return res; + } + + int consume_identifier (int c, bool quoted) + { + // + // This method is very performance sensitive. It accounts + // for approximately 25% of all parser time + // + + int pos = 0; + int column = col; + if (quoted) + --column; + + if (c == '\\') { + int surrogate; + c = escape (c, out surrogate); + if (surrogate != 0) { + id_builder [pos++] = (char) c; + c = surrogate; + } + } + + id_builder [pos++] = (char) c; + + try { + while (true) { + c = reader.Read (); + + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9')) { + id_builder [pos++] = (char) c; + continue; + } + + if (c < 0x80) { + if (c == '\\') { + int surrogate; + c = escape (c, out surrogate); + if (is_identifier_part_character ((char) c)) + id_builder[pos++] = (char) c; + + if (surrogate != 0) { + c = surrogate; + } + + continue; + } + } else if (Char.IsLetter ((char) c) || Char.GetUnicodeCategory ((char) c) == UnicodeCategory.ConnectorPunctuation) { + id_builder [pos++] = (char) c; + continue; + } + + putback_char = c; + break; + } + } catch (IndexOutOfRangeException) { + Report.Error (645, Location, "Identifier too long (limit is 512 chars)"); + --pos; + col += pos; + } + + col += pos - 1; + + // + // Optimization: avoids doing the keyword lookup + // on uppercase letters + // + if (id_builder [0] >= '_' && !quoted) { + int keyword = GetKeyword (id_builder, pos); + if (keyword != -1) { + val = LocatedToken.Create (null, ref_line, column); + return keyword; + } + } + + string s = InternIdentifier (id_builder, pos); +#if FULL_AST + if (quoted) { + val = LocatedToken.Create ("@" + s, ref_line, column - 1); + } else { + val = LocatedToken.Create (s, ref_line, column); + } +#else + val = LocatedToken.Create (s, ref_line, column); +#endif + if (quoted && parsing_attribute_section) + AddEscapedIdentifier (((LocatedToken) val).Location); + + return Token.IDENTIFIER; + } + + static string InternIdentifier (char[] charBuffer, int length) + { + // + // Keep identifiers in an array of hashtables to avoid needless + // allocations + // + var identifiers_group = identifiers [length]; + string s; + if (identifiers_group != null) { + if (identifiers_group.TryGetValue (charBuffer, out s)) { + return s; + } + } else { + // TODO: this should be number of files dependant + // corlib compilation peaks at 1000 and System.Core at 150 + int capacity = length > 20 ? 10 : 100; + identifiers_group = new Dictionary (capacity, new IdentifiersComparer (length)); + identifiers [length] = identifiers_group; + } + + char[] chars = new char[length]; + Array.Copy (charBuffer, chars, length); + + s = new string (charBuffer, 0, length); + identifiers_group.Add (chars, s); + + return s; + } + + public int xtoken () + { + int d, c; + + // Whether we have seen comments on the current line + bool comments_seen = false; + while ((c = get_char ()) != -1) { + switch (c) { + case '\t': + col = ((col - 1 + tab_size) / tab_size) * tab_size; + continue; + + case ' ': + case '\f': + case '\v': + case 0xa0: + case 0: + case 0xFEFF: // Ignore BOM anywhere in the file + continue; + +/* This is required for compatibility with .NET + case 0xEF: + if (peek_char () == 0xBB) { + PushPosition (); + get_char (); + if (get_char () == 0xBF) + continue; + PopPosition (); + } + break; +*/ + case '\\': + tokens_seen = true; + return consume_identifier (c); + + case '{': + val = LocatedToken.Create (ref_line, col); + return Token.OPEN_BRACE; + case '}': + val = LocatedToken.Create (ref_line, col); + return Token.CLOSE_BRACE; + case '[': + // To block doccomment inside attribute declaration. + if (doc_state == XmlCommentState.Allowed) + doc_state = XmlCommentState.NotAllowed; + + val = LocatedToken.Create (ref_line, col); + + if (parsing_block == 0 || lambda_arguments_parsing) + return Token.OPEN_BRACKET; + + int next = peek_char (); + switch (next) { + case ']': + case ',': + return Token.OPEN_BRACKET; + + case ' ': + case '\f': + case '\v': + case '\r': + case '\n': + case '/': + next = peek_token (); + if (next == Token.COMMA || next == Token.CLOSE_BRACKET) + return Token.OPEN_BRACKET; + + return Token.OPEN_BRACKET_EXPR; + default: + return Token.OPEN_BRACKET_EXPR; + } + case ']': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.CLOSE_BRACKET; + case '(': + val = LocatedToken.Create (ref_line, col); + // + // An expression versions of parens can appear in block context only + // + if (parsing_block != 0 && !lambda_arguments_parsing) { + + // + // Optmize most common case where we know that parens + // is not special + // + switch (current_token) { + case Token.IDENTIFIER: + case Token.IF: + case Token.FOR: + case Token.FOREACH: + case Token.TYPEOF: + case Token.WHILE: + case Token.USING: + case Token.DEFAULT: + case Token.DELEGATE: + case Token.OP_GENERICS_GT: + return Token.OPEN_PARENS; + } + + // Optimize using peek + int xx = peek_char (); + switch (xx) { + case '(': + case '\'': + case '"': + case '0': + case '1': + return Token.OPEN_PARENS; + } + + lambda_arguments_parsing = true; + PushPosition (); + d = TokenizeOpenParens (); + PopPosition (); + lambda_arguments_parsing = false; + return d; + } + + return Token.OPEN_PARENS; + case ')': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.CLOSE_PARENS; + case ',': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.COMMA; + case ';': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.SEMICOLON; + case '~': + val = LocatedToken.Create (ref_line, col); + return Token.TILDE; + case '?': + val = LocatedToken.Create (ref_line, col); + return TokenizePossibleNullableType (); + case '<': + val = LocatedToken.Create (ref_line, col); + if (parsing_generic_less_than++ > 0) + return Token.OP_GENERICS_LT; + + return TokenizeLessThan (); + + case '>': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_GE; + } + + if (parsing_generic_less_than > 1 || (parsing_generic_less_than == 1 && d != '>')) { + parsing_generic_less_than--; + return Token.OP_GENERICS_GT; + } + + if (d == '>') { + get_char (); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_SHIFT_RIGHT_ASSIGN; + } + return Token.OP_SHIFT_RIGHT; + } + + return Token.OP_GT; + + case '+': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '+') { + d = Token.OP_INC; + } else if (d == '=') { + d = Token.OP_ADD_ASSIGN; + } else { + return Token.PLUS; + } + get_char (); + return d; + + case '-': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '-') { + d = Token.OP_DEC; + } else if (d == '=') + d = Token.OP_SUB_ASSIGN; + else if (d == '>') + d = Token.OP_PTR; + else { + return Token.MINUS; + } + get_char (); + return d; + + case '!': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '=') { + get_char (); + return Token.OP_NE; + } + return Token.BANG; + + case '=': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '=') { + get_char (); + return Token.OP_EQ; + } + if (d == '>') { + get_char (); + return Token.ARROW; + } + + return Token.ASSIGN; + + case '&': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '&') { + get_char (); + return Token.OP_AND; + } + if (d == '=') { + get_char (); + return Token.OP_AND_ASSIGN; + } + return Token.BITWISE_AND; + + case '|': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '|') { + get_char (); + return Token.OP_OR; + } + if (d == '=') { + get_char (); + return Token.OP_OR_ASSIGN; + } + return Token.BITWISE_OR; + + case '*': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '=') { + get_char (); + return Token.OP_MULT_ASSIGN; + } + return Token.STAR; + + case '/': + d = peek_char (); + if (d == '=') { + val = LocatedToken.Create (ref_line, col); + get_char (); + return Token.OP_DIV_ASSIGN; + } + + // Handle double-slash comments. + if (d == '/') { + get_char (); + if (doc_processing) { + if (peek_char () == '/') { + sbag.StartComment (SpecialsBag.CommentType.Documentation, startsLine, line, col - 1); + get_char (); + // Don't allow ////. + if ((d = peek_char ()) != '/') { + sbag.PushCommentChar (d); + if (doc_state == XmlCommentState.Allowed) + handle_one_line_xml_comment (); + else if (doc_state == XmlCommentState.NotAllowed) + WarningMisplacedComment (Location - 3); + } + } else { + if (xml_comment_buffer.Length > 0) + doc_state = XmlCommentState.NotAllowed; + } + } else { + bool isDoc = peek_char () == '/'; + sbag.StartComment (isDoc ? SpecialsBag.CommentType.Documentation : SpecialsBag.CommentType.Single, startsLine, line, col - 1); + if (isDoc) + get_char (); + } + + d = peek_char (); + if (d == '\n' || d == '\r') + sbag.EndComment (line, col + 1); + + while ((d = get_char ()) != -1 && (d != '\n') && d != '\r') { + sbag.PushCommentChar (d); + var pc = peek_char (); + if (pc == -1 || pc == '\n' || pc == '\r') { + sbag.EndComment (line, col + 1); + } + } + + any_token_seen |= tokens_seen; + tokens_seen = false; + comments_seen = false; + continue; + } else if (d == '*'){ + sbag.StartComment (SpecialsBag.CommentType.Multi, startsLine, line, col); + get_char (); + bool docAppend = false; + if (doc_processing && peek_char () == '*') { + int ch = get_char (); + sbag.PushCommentChar (ch); + // But when it is /**/, just do nothing. + if (peek_char () == '/') { + ch = get_char (); + sbag.PushCommentChar (ch); + sbag.EndComment (line, col + 1); + continue; + } + if (doc_state == XmlCommentState.Allowed) + docAppend = true; + else if (doc_state == XmlCommentState.NotAllowed) { + WarningMisplacedComment (Location - 2); + } + } + + int current_comment_start = 0; + if (docAppend) { + current_comment_start = xml_comment_buffer.Length; + xml_comment_buffer.Append (Environment.NewLine); + } + + while ((d = get_char ()) != -1){ + sbag.PushCommentChar (d); + if (d == '*' && peek_char () == '/'){ + sbag.PushCommentChar ('/'); + get_char (); + sbag.EndComment (line, col + 1); + comments_seen = true; + break; + } + if (docAppend) + xml_comment_buffer.Append ((char) d); + + if (d == '\n'){ + any_token_seen |= tokens_seen; + tokens_seen = false; + // + // Reset 'comments_seen' just to be consistent. + // It doesn't matter either way, here. + // + comments_seen = false; + } + } + + if (!comments_seen) + Report.Error (1035, Location, "End-of-file found, '*/' expected"); + + if (docAppend) + update_formatted_doc_comment (current_comment_start); + continue; + } + val = LocatedToken.Create (ref_line, col); + return Token.DIV; + + case '%': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '='){ + get_char (); + return Token.OP_MOD_ASSIGN; + } + return Token.PERCENT; + + case '^': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '='){ + get_char (); + return Token.OP_XOR_ASSIGN; + } + return Token.CARRET; + + case ':': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == ':') { + get_char (); + return Token.DOUBLE_COLON; + } + return Token.COLON; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + tokens_seen = true; + return is_number (c); + + case '\n': // white space + any_token_seen |= tokens_seen; + tokens_seen = false; + comments_seen = false; + continue; + + case '.': + tokens_seen = true; + d = peek_char (); + if (d >= '0' && d <= '9') + return is_number (c); + + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.DOT; + + case '#': + if (tokens_seen || comments_seen) { + Eror_WrongPreprocessorLocation (); + return Token.ERROR; + } + + if (ParsePreprocessingDirective (true)) + continue; + + bool directive_expected = false; + while ((c = get_char ()) != -1) { + if (col == 1) { + directive_expected = true; + } else if (!directive_expected) { + // TODO: Implement comment support for disabled code and uncomment this code +// if (c == '#') { +// Eror_WrongPreprocessorLocation (); +// return Token.ERROR; +// } + continue; + } + + if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' ) + continue; + + if (c == '#') { + if (ParsePreprocessingDirective (false)) + break; + } + directive_expected = false; + } + + if (c != -1) { + tokens_seen = false; + continue; + } + + return Token.EOF; + + case '"': + return consume_string (false); + + case '\'': + return TokenizeBackslash (); + + case '@': + c = get_char (); + if (c == '"') { + tokens_seen = true; + return consume_string (true); + } + + if (is_identifier_start_character (c)){ + return consume_identifier (c, true); + } + + Report.Error (1646, Location, "Keyword, identifier, or string expected after verbatim specifier: @"); + return Token.ERROR; + + case EvalStatementParserCharacter: + return Token.EVAL_STATEMENT_PARSER; + case EvalCompilationUnitParserCharacter: + return Token.EVAL_COMPILATION_UNIT_PARSER; + case EvalUsingDeclarationsParserCharacter: + return Token.EVAL_USING_DECLARATIONS_UNIT_PARSER; + case DocumentationXref: + return Token.DOC_SEE; + } + + if (is_identifier_start_character (c)) { + tokens_seen = true; + return consume_identifier (c); + } + + if (char.IsWhiteSpace ((char) c)) + continue; + + Report.Error (1056, Location, "Unexpected character `{0}'", ((char) c).ToString ()); + } + + if (CompleteOnEOF){ + if (generated) + return Token.COMPLETE_COMPLETION; + + generated = true; + return Token.GENERATE_COMPLETION; + } + + + return Token.EOF; + } + + int TokenizeBackslash () + { + int c = get_char (); + tokens_seen = true; + if (c == '\'') { + val = new CharLiteral (context.BuiltinTypes, (char) c, Location); + Report.Error (1011, Location, "Empty character literal"); + return Token.LITERAL; + } + + if (c == '\n') { + Report.Error (1010, Location, "Newline in constant"); + return Token.ERROR; + } + + int d; + c = escape (c, out d); + if (c == -1) + return Token.ERROR; + if (d != 0) + throw new NotImplementedException (); + + val = new CharLiteral (context.BuiltinTypes, (char) c, Location); + c = get_char (); + + if (c != '\'') { + Report.Error (1012, Location, "Too many characters in character literal"); + + // Try to recover, read until newline or next "'" + while ((c = get_char ()) != -1) { + if (c == '\n' || c == '\'') + break; + } + } + + return Token.LITERAL; + } + + int TokenizeLessThan () + { + int d; + if (handle_typeof) { + PushPosition (); + if (parse_generic_dimension (out d)) { + val = d; + DiscardPosition (); + return Token.GENERIC_DIMENSION; + } + PopPosition (); + } + + // Save current position and parse next token. + PushPosition (); + if (parse_less_than ()) { + if (parsing_generic_declaration && (parsing_generic_declaration_doc || token () != Token.DOT)) { + d = Token.OP_GENERICS_LT_DECL; + } else { + d = Token.OP_GENERICS_LT; + } + PopPosition (); + return d; + } + + PopPosition (); + parsing_generic_less_than = 0; + + d = peek_char (); + if (d == '<') { + get_char (); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_SHIFT_LEFT_ASSIGN; + } + return Token.OP_SHIFT_LEFT; + } + + if (d == '=') { + get_char (); + return Token.OP_LE; + } + return Token.OP_LT; + } + + // + // Handles one line xml comment + // + private void handle_one_line_xml_comment () + { + int c; + while ((c = peek_char ()) == ' ') { + sbag.PushCommentChar (c); + get_char (); // skip heading whitespaces. + } + while ((c = peek_char ()) != -1 && c != '\n' && c != '\r') { + sbag.PushCommentChar (c); + xml_comment_buffer.Append ((char) get_char ()); + } + if (c == '\r' || c == '\n') + xml_comment_buffer.Append (Environment.NewLine); + } + + // + // Remove heading "*" in Javadoc-like xml documentation. + // + private void update_formatted_doc_comment (int current_comment_start) + { + int length = xml_comment_buffer.Length - current_comment_start; + string [] lines = xml_comment_buffer.ToString ( + current_comment_start, + length).Replace ("\r", "").Split ('\n'); + + // The first line starts with /**, thus it is not target + // for the format check. + for (int i = 1; i < lines.Length; i++) { + string s = lines [i]; + int idx = s.IndexOf ('*'); + string head = null; + if (idx < 0) { + if (i < lines.Length - 1) + return; + head = s; + } else + head = s.Substring (0, idx); + foreach (char c in head) + if (c != ' ') + return; + lines [i] = s.Substring (idx + 1); + } + xml_comment_buffer.Remove (current_comment_start, length); + xml_comment_buffer.Insert (current_comment_start, String.Join (Environment.NewLine, lines)); + } + + // + // Checks if there was incorrect doc comments and raise + // warnings. + // + public void check_incorrect_doc_comment () + { + if (xml_comment_buffer.Length > 0) + WarningMisplacedComment (Location); + } + + // + // Consumes the saved xml comment lines (if any) + // as for current target member or type. + // + public string consume_doc_comment () + { + if (xml_comment_buffer.Length > 0) { + string ret = xml_comment_buffer.ToString (); + reset_doc_comment (); + return ret; + } + return null; + } + + Report Report { + get { return context.Report; } + } + + void reset_doc_comment () + { + xml_comment_buffer.Length = 0; + } + + public void cleanup () + { + if (ifstack != null && ifstack.Count >= 1) { + int state = ifstack.Pop (); + if ((state & REGION) != 0) + Report.Error (1038, Location, "#endregion directive expected"); + else + Report.Error (1027, Location, "Expected `#endif' directive"); + } + } + } + + // + // Indicates whether it accepts XML documentation or not. + // + public enum XmlCommentState { + // comment is allowed in this state. + Allowed, + // comment is not allowed in this state. + NotAllowed, + // once comments appeared when it is NotAllowed, then the + // state is changed to it, until the state is changed to + // .Allowed. + Error + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs new file mode 100644 index 0000000000..0329cf6a50 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs @@ -0,0 +1,1557 @@ +// +// decl.cs: Declaration base class for structs, classes, enums and interfaces. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +#if NET_2_1 +using XmlElement = System.Object; +#else +using System.Xml; +#endif + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +using Mono.Collections.Generic; +#endif + +namespace Mono.CSharp { + + // + // Better name would be DottenName + // + [DebuggerDisplay ("{GetSignatureForError()}")] + public class MemberName { + public readonly string Name; + public TypeArguments TypeArguments; + + public readonly MemberName Left; + public readonly Location Location; + + public static readonly MemberName Null = new MemberName (""); + + bool is_double_colon; + + public bool IsDoubleColon { get { return is_double_colon; } } + + private MemberName (MemberName left, string name, bool is_double_colon, + Location loc) + { + this.Name = name; + this.Location = loc; + this.is_double_colon = is_double_colon; + this.Left = left; + } + + private MemberName (MemberName left, string name, bool is_double_colon, + TypeArguments args, Location loc) + : this (left, name, is_double_colon, loc) + { + if (args != null && args.Count > 0) + this.TypeArguments = args; + } + + public MemberName (string name) + : this (name, Location.Null) + { } + + public MemberName (string name, Location loc) + : this (null, name, false, loc) + { } + + public MemberName (string name, TypeArguments args, Location loc) + : this (null, name, false, args, loc) + { } + + public MemberName (MemberName left, string name) + : this (left, name, left != null ? left.Location : Location.Null) + { } + + public MemberName (MemberName left, string name, Location loc) + : this (left, name, false, loc) + { } + + public MemberName (MemberName left, string name, TypeArguments args, Location loc) + : this (left, name, false, args, loc) + { } + + public MemberName (string alias, string name, TypeArguments args, Location loc) + : this (new MemberName (alias, loc), name, true, args, loc) + { } + + public MemberName (MemberName left, MemberName right) + : this (left, right, right.Location) + { } + + public MemberName (MemberName left, MemberName right, Location loc) + : this (null, right.Name, false, right.TypeArguments, loc) + { + if (right.is_double_colon) + throw new InternalErrorException ("Cannot append double_colon member name"); + this.Left = (right.Left == null) ? left : new MemberName (left, right.Left); + } + + // TODO: Remove + public string GetName () + { + return GetName (false); + } + + public int Arity { + get { + return TypeArguments == null ? 0 : TypeArguments.Count; + } + } + + public bool IsGeneric { + get { + if (TypeArguments != null) + return true; + else if (Left != null) + return Left.IsGeneric; + else + return false; + } + } + + public string GetName (bool is_generic) + { + string name = is_generic ? Basename : Name; + if (Left != null) + return Left.GetName (is_generic) + (is_double_colon ? "::" : ".") + name; + + return name; + } + + public ATypeNameExpression GetTypeExpression () + { + if (Left == null) { + if (TypeArguments != null) + return new SimpleName (Name, TypeArguments, Location); + + return new SimpleName (Name, Location); + } + + if (is_double_colon) { + if (Left.Left != null) + throw new InternalErrorException ("The left side of a :: should be an identifier"); + return new QualifiedAliasMember (Left.Name, Name, TypeArguments, Location); + } + + Expression lexpr = Left.GetTypeExpression (); + return new MemberAccess (lexpr, Name, TypeArguments, Location); + } + + public MemberName Clone () + { + MemberName left_clone = Left == null ? null : Left.Clone (); + return new MemberName (left_clone, Name, is_double_colon, TypeArguments, Location); + } + + public string Basename { + get { + if (TypeArguments != null) + return MakeName (Name, TypeArguments); + return Name; + } + } + + public string GetSignatureForError () + { + string append = TypeArguments == null ? "" : "<" + TypeArguments.GetSignatureForError () + ">"; + if (Left == null) + return Name + append; + string connect = is_double_colon ? "::" : "."; + return Left.GetSignatureForError () + connect + Name + append; + } + + public override bool Equals (object other) + { + return Equals (other as MemberName); + } + + public bool Equals (MemberName other) + { + if (this == other) + return true; + if (other == null || Name != other.Name) + return false; + if (is_double_colon != other.is_double_colon) + return false; + + if ((TypeArguments != null) && + (other.TypeArguments == null || TypeArguments.Count != other.TypeArguments.Count)) + return false; + + if ((TypeArguments == null) && (other.TypeArguments != null)) + return false; + + if (Left == null) + return other.Left == null; + + return Left.Equals (other.Left); + } + + public override int GetHashCode () + { + int hash = Name.GetHashCode (); + for (MemberName n = Left; n != null; n = n.Left) + hash ^= n.Name.GetHashCode (); + if (is_double_colon) + hash ^= 0xbadc01d; + + if (TypeArguments != null) + hash ^= TypeArguments.Count << 5; + + return hash & 0x7FFFFFFF; + } + + public int CountTypeArguments { + get { + if (TypeArguments != null) + return TypeArguments.Count; + else if (Left != null) + return Left.CountTypeArguments; + else + return 0; + } + } + + public static string MakeName (string name, TypeArguments args) + { + if (args == null) + return name; + + return name + "`" + args.Count; + } + + public static string MakeName (string name, int count) + { + return name + "`" + count; + } + } + + public class SimpleMemberName + { + public string Value; + public Location Location; + + public SimpleMemberName (string name, Location loc) + { + this.Value = name; + this.Location = loc; + } + } + + /// + /// Base representation for members. This is used to keep track + /// of Name, Location and Modifier flags, and handling Attributes. + /// + [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")] + public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition + { + /// + /// Public name + /// + + protected string cached_name; + // TODO: Remove in favor of MemberName + public string Name { + get { + if (cached_name == null) + cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method)); + return cached_name; + } + } + + string IMemberDefinition.Name { + get { + return member_name.Name; + } + } + + // Is not readonly because of IndexerName attribute + private MemberName member_name; + public MemberName MemberName { + get { return member_name; } + } + + /// + /// Modifier flags that the user specified in the source code + /// + private Modifiers mod_flags; + public Modifiers ModFlags { + set { + mod_flags = value; + if ((value & Modifiers.COMPILER_GENERATED) != 0) + caching_flags = Flags.IsUsed | Flags.IsAssigned; + } + get { + return mod_flags; + } + } + + public virtual ModuleContainer Module { + get { + return Parent.Module; + } + } + + public /*readonly*/ TypeContainer Parent; + + /// + /// Location where this declaration happens + /// + public Location Location { + get { return member_name.Location; } + } + + /// + /// XML documentation comment + /// + protected string comment; + + /// + /// Represents header string for documentation comment + /// for each member types. + /// + public abstract string DocCommentHeader { get; } + + [Flags] + public enum Flags { + Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet + Obsolete = 1 << 1, // Type has obsolete attribute + ClsCompliance_Undetected = 1 << 2, // CLS Compliance has not been detected yet + ClsCompliant = 1 << 3, // Type is CLS Compliant + CloseTypeCreated = 1 << 4, // Tracks whether we have Closed the type + HasCompliantAttribute_Undetected = 1 << 5, // Presence of CLSCompliantAttribute has not been detected + HasClsCompliantAttribute = 1 << 6, // Type has CLSCompliantAttribute + ClsCompliantAttributeFalse = 1 << 7, // Member has CLSCompliant(false) + Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet + Excluded = 1 << 9, // Method is conditional + MethodOverloadsExist = 1 << 10, // Test for duplication must be performed + IsUsed = 1 << 11, + IsAssigned = 1 << 12, // Field is assigned + HasExplicitLayout = 1 << 13, + PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists + HasStructLayout = 1 << 15 // Has StructLayoutAttribute + } + + /// + /// MemberCore flags at first detected then cached + /// + internal Flags caching_flags; + + public MemberCore (DeclSpace parent, MemberName name, Attributes attrs) + { + this.Parent = parent as TypeContainer; + member_name = name; + caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected; + AddAttributes (attrs, this); + } + + protected virtual void SetMemberName (MemberName new_name) + { + member_name = new_name; + cached_name = null; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + protected bool CheckAbstractAndExtern (bool has_block) + { + if (Parent.PartialContainer.Kind == MemberKind.Interface) + return true; + + if (has_block) { + if ((ModFlags & Modifiers.EXTERN) != 0) { + Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern", + GetSignatureForError ()); + return false; + } + + if ((ModFlags & Modifiers.ABSTRACT) != 0) { + Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract", + GetSignatureForError ()); + return false; + } + } else { + if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) { + if (Compiler.Settings.Version >= LanguageVersion.V_3) { + Property.PropertyMethod pm = this as Property.PropertyMethod; + if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod) + pm = null; + + if (pm != null && pm.Property.AccessorSecond == null) { + Report.Error (840, Location, + "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors", + GetSignatureForError ()); + return false; + } + } + + Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial", + GetSignatureForError ()); + return false; + } + } + + return true; + } + + protected void CheckProtectedModifier () + { + if ((ModFlags & Modifiers.PROTECTED) == 0) + return; + + if (Parent.PartialContainer.Kind == MemberKind.Struct) { + Report.Error (666, Location, "`{0}': Structs cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.STATIC) != 0) { + Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 && + !(this is Destructor)) { + Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", + GetSignatureForError ()); + return; + } + } + + public abstract bool Define (); + + public virtual string DocComment { + get { + return comment; + } + set { + comment = value; + } + } + + // + // Returns full member name for error message + // + public virtual string GetSignatureForError () + { + if (Parent == null || Parent.Parent == null) + return member_name.GetSignatureForError (); + + return Parent.GetSignatureForError () + "." + member_name.GetSignatureForError (); + } + + /// + /// Base Emit method. This is also entry point for CLS-Compliant verification. + /// + public virtual void Emit () + { + if (!Compiler.Settings.VerifyClsCompliance) + return; + + VerifyClsCompliance (); + } + + public bool IsCompilerGenerated { + get { + if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0) + return true; + + return Parent == null ? false : Parent.IsCompilerGenerated; + } + } + + public bool IsImported { + get { + return false; + } + } + + public virtual bool IsUsed { + get { + return (caching_flags & Flags.IsUsed) != 0; + } + } + + protected Report Report { + get { + return Compiler.Report; + } + } + + public void SetIsUsed () + { + caching_flags |= Flags.IsUsed; + } + + public void SetIsAssigned () + { + caching_flags |= Flags.IsAssigned; + } + + /// + /// Returns instance of ObsoleteAttribute for this MemberCore + /// + public virtual ObsoleteAttribute GetAttributeObsolete () + { + if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) + return null; + + caching_flags &= ~Flags.Obsolete_Undetected; + + if (OptAttributes == null) + return null; + + Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete); + if (obsolete_attr == null) + return null; + + caching_flags |= Flags.Obsolete; + + ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (); + if (obsolete == null) + return null; + + return obsolete; + } + + /// + /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements + /// + public virtual void CheckObsoleteness (Location loc) + { + ObsoleteAttribute oa = GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, Report); + } + + // + // Checks whether the type P is as accessible as this member + // + public bool IsAccessibleAs (TypeSpec p) + { + // + // if M is private, its accessibility is the same as this declspace. + // we already know that P is accessible to T before this method, so we + // may return true. + // + if ((mod_flags & Modifiers.PRIVATE) != 0) + return true; + + while (TypeManager.HasElementType (p)) + p = TypeManager.GetElementType (p); + + if (p.IsGenericParameter) + return true; + + for (TypeSpec p_parent; p != null; p = p_parent) { + p_parent = p.DeclaringType; + + if (p.IsGeneric) { + foreach (TypeSpec t in p.TypeArguments) { + if (!IsAccessibleAs (t)) + return false; + } + } + + var pAccess = p.Modifiers & Modifiers.AccessibilityMask; + if (pAccess == Modifiers.PUBLIC) + continue; + + bool same_access_restrictions = false; + for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) { + var al = mc.ModFlags & Modifiers.AccessibilityMask; + switch (pAccess) { + case Modifiers.INTERNAL: + if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL) + same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + + break; + + case Modifiers.PROTECTED: + if (al == Modifiers.PROTECTED) { + same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent); + break; + } + + if (al == Modifiers.PRIVATE) { + // + // When type is private and any of its parents derives from + // protected type then the type is accessible + // + while (mc.Parent != null) { + if (mc.Parent.IsBaseTypeDefinition (p_parent)) + same_access_restrictions = true; + mc = mc.Parent; + } + } + + break; + + case Modifiers.PROTECTED | Modifiers.INTERNAL: + if (al == Modifiers.INTERNAL) + same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL)) + same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + else + goto case Modifiers.PROTECTED; + + break; + + case Modifiers.PRIVATE: + // + // Both are private and share same parent + // + if (al == Modifiers.PRIVATE) { + var decl = mc.Parent; + do { + same_access_restrictions = decl.CurrentType == p_parent; + } while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null); + } + + break; + + default: + throw new InternalErrorException (al.ToString ()); + } + } + + if (!same_access_restrictions) + return false; + } + + return true; + } + + /// + /// Analyze whether CLS-Compliant verification must be execute for this MemberCore. + /// + public override bool IsClsComplianceRequired () + { + if ((caching_flags & Flags.ClsCompliance_Undetected) == 0) + return (caching_flags & Flags.ClsCompliant) != 0; + + caching_flags &= ~Flags.ClsCompliance_Undetected; + + if (HasClsCompliantAttribute) { + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) + return false; + + caching_flags |= Flags.ClsCompliant; + return true; + } + + if (Parent.PartialContainer.IsClsComplianceRequired ()) { + caching_flags |= Flags.ClsCompliant; + return true; + } + + return false; + } + + public virtual string[] ConditionalConditions () + { + return null; + } + + /// + /// Returns true when MemberCore is exposed from assembly. + /// + public bool IsExposedFromAssembly () + { + if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + return false; + + DeclSpace parentContainer = Parent.PartialContainer; + while (parentContainer != null && parentContainer.ModFlags != 0) { + if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + return false; + parentContainer = parentContainer.Parent; + } + return true; + } + + public virtual IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public virtual FullNamedExpression LookupNamespaceAlias (string name) + { + return Parent.NamespaceEntry.LookupNamespaceAlias (name); + } + + public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + return Parent.LookupNamespaceOrType (name, arity, mode, loc); + } + + /// + /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute. + /// If no is attribute exists then assembly CLSCompliantAttribute is returned. + /// + public bool? CLSAttributeValue { + get { + if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) { + if ((caching_flags & Flags.HasClsCompliantAttribute) == 0) + return null; + + return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0; + } + + caching_flags &= ~Flags.HasCompliantAttribute_Undetected; + + if (OptAttributes != null) { + Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + if (cls_attribute != null) { + caching_flags |= Flags.HasClsCompliantAttribute; + if (cls_attribute.GetClsCompliantAttributeValue ()) + return true; + + caching_flags |= Flags.ClsCompliantAttributeFalse; + return false; + } + } + + return null; + } + } + + /// + /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute + /// + protected bool HasClsCompliantAttribute { + get { + return CLSAttributeValue.HasValue; + } + } + + /// + /// Returns true when a member supports multiple overloads (methods, indexers, etc) + /// + public virtual bool EnableOverloadChecks (MemberCore overload) + { + return false; + } + + /// + /// The main virtual method for CLS-Compliant verifications. + /// The method returns true if member is CLS-Compliant and false if member is not + /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it + /// and add their extra verifications. + /// + protected virtual bool VerifyClsCompliance () + { + if (HasClsCompliantAttribute) { + if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { + Report.Warning (3021, 2, a.Location, + "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", + GetSignatureForError ()); + } else { + Report.Warning (3014, 1, a.Location, + "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant", + GetSignatureForError ()); + } + return false; + } + + if (!IsExposedFromAssembly ()) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); + return false; + } + + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { + if (Parent.Kind == MemberKind.Interface && Parent.IsClsComplianceRequired ()) { + Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ()); + } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) { + Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ()); + } + + return false; + } + + if (Parent.Parent != null && !Parent.IsClsComplianceRequired ()) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", + GetSignatureForError (), Parent.GetSignatureForError ()); + return false; + } + } else { + if (!IsExposedFromAssembly ()) + return false; + + if (!Parent.PartialContainer.IsClsComplianceRequired ()) + return false; + } + + if (member_name.Name [0] == '_') { + Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () ); + } + + return true; + } + + // + // Returns a string that represents the signature for this + // member which should be used in XML documentation. + // + public abstract string GetSignatureForDocumentation (); + + // + // Generates xml doc comments (if any), and if required, + // handle warning report. + // + internal virtual void GenerateDocComment (DocumentationBuilder builder) + { + if (DocComment == null) { + if (IsExposedFromAssembly ()) { + Constructor c = this as Constructor; + if (c == null || !c.IsDefault ()) + Report.Warning (1591, 4, Location, + "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ()); + } + + return; + } + + try { + builder.GenerateDocumentationForMember (this); + } catch (Exception e) { + throw new InternalErrorException (this, e); + } + } + + #region IMemberContext Members + + public virtual CompilerContext Compiler { + get { return Parent.Compiler; } + } + + public virtual TypeSpec CurrentType { + get { return Parent.CurrentType; } + } + + public MemberCore CurrentMemberDefinition { + get { return this; } + } + + public virtual TypeParameter[] CurrentTypeParameters { + get { return null; } + } + + public bool IsObsolete { + get { + if (GetAttributeObsolete () != null) + return true; + + return Parent == null ? false : Parent.IsObsolete; + } + } + + public bool IsUnsafe { + get { + if ((ModFlags & Modifiers.UNSAFE) != 0) + return true; + + return Parent == null ? false : Parent.IsUnsafe; + } + } + + public bool IsStatic { + get { + return (ModFlags & Modifiers.STATIC) != 0; + } + } + + #endregion + } + + // + // Base member specification. A member specification contains + // member details which can alter in the context (e.g. generic instances) + // + public abstract class MemberSpec + { + [Flags] + public enum StateFlags + { + Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet + Obsolete = 1 << 1, // Member has obsolete attribute + CLSCompliant_Undetected = 1 << 2, // CLSCompliant attribute has not been detected yet + CLSCompliant = 1 << 3, // Member is CLS Compliant + MissingDependency_Undetected = 1 << 4, + MissingDependency = 1 << 5, + HasDynamicElement = 1 << 6, + ConstraintsChecked = 1 << 7, + + IsAccessor = 1 << 9, // Method is an accessor + IsGeneric = 1 << 10, // Member contains type arguments + + PendingMetaInflate = 1 << 12, + PendingMakeMethod = 1 << 13, + PendingMemberCacheMembers = 1 << 14, + PendingBaseTypeInflate = 1 << 15, + InterfacesExpanded = 1 << 16, + IsNotCSharpCompatible = 1 << 17, + SpecialRuntimeType = 1 << 18, + InflatedExpressionType = 1 << 19, + InflatedNullableType = 1 << 20, + GenericIterateInterface = 1 << 21, + GenericTask = 1 << 22 + } + + protected Modifiers modifiers; + public StateFlags state; + protected IMemberDefinition definition; + public readonly MemberKind Kind; + protected TypeSpec declaringType; + +#if DEBUG + static int counter; + public int ID = counter++; +#endif + + protected MemberSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, Modifiers modifiers) + { + this.Kind = kind; + this.declaringType = declaringType; + this.definition = definition; + this.modifiers = modifiers; + + state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected; + } + + #region Properties + + public virtual int Arity { + get { + return 0; + } + } + + public TypeSpec DeclaringType { + get { + return declaringType; + } + set { + declaringType = value; + } + } + + public IMemberDefinition MemberDefinition { + get { + return definition; + } + } + + public Modifiers Modifiers { + get { + return modifiers; + } + set { + modifiers = value; + } + } + + public virtual string Name { + get { + return definition.Name; + } + } + + public bool IsAbstract { + get { return (modifiers & Modifiers.ABSTRACT) != 0; } + } + + public bool IsAccessor { + get { + return (state & StateFlags.IsAccessor) != 0; + } + set { + state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor; + } + } + + // + // Return true when this member is a generic in C# terms + // A nested non-generic type of generic type will return false + // + public bool IsGeneric { + get { + return (state & StateFlags.IsGeneric) != 0; + } + set { + state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric; + } + } + + // + // Returns true for imported members which are not compatible with C# language + // + public bool IsNotCSharpCompatible { + get { + return (state & StateFlags.IsNotCSharpCompatible) != 0; + } + set { + state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible; + } + } + + public bool IsPrivate { + get { return (modifiers & Modifiers.PRIVATE) != 0; } + } + + public bool IsPublic { + get { return (modifiers & Modifiers.PUBLIC) != 0; } + } + + public bool IsStatic { + get { + return (modifiers & Modifiers.STATIC) != 0; + } + } + + #endregion + + public virtual ObsoleteAttribute GetAttributeObsolete () + { + if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0) + return null; + + state &= ~StateFlags.Obsolete_Undetected; + + var oa = definition.GetAttributeObsolete (); + if (oa != null) + state |= StateFlags.Obsolete; + + return oa; + } + + // + // Returns a list of missing dependencies of this member. The list + // will contain types only but it can have numerous values for members + // like methods where both return type and all parameters are checked + // + public List GetMissingDependencies () + { + if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0) + return null; + + state &= ~StateFlags.MissingDependency_Undetected; + + var imported = definition as ImportedDefinition; + List missing; + if (imported != null) { + missing = ResolveMissingDependencies (); + } else if (this is ElementTypeSpec) { + missing = ((ElementTypeSpec) this).Element.GetMissingDependencies (); + } else { + missing = null; + } + + if (missing != null) { + state |= StateFlags.MissingDependency; + } + + return missing; + } + + public abstract List ResolveMissingDependencies (); + + protected virtual bool IsNotCLSCompliant (out bool attrValue) + { + var cls = MemberDefinition.CLSAttributeValue; + attrValue = cls ?? false; + return cls == false; + } + + public virtual string GetSignatureForDocumentation () + { + return DeclaringType.GetSignatureForDocumentation () + "." + Name; + } + + public virtual string GetSignatureForError () + { + var bf = MemberDefinition as Property.BackingField; + var name = bf == null ? Name : bf.OriginalName; + return DeclaringType.GetSignatureForError () + "." + name; + } + + public virtual MemberSpec InflateMember (TypeParameterInflator inflator) + { + var inflated = (MemberSpec) MemberwiseClone (); + inflated.declaringType = inflator.TypeInstance; + if (DeclaringType.IsGenericOrParentIsGeneric) + inflated.state |= StateFlags.PendingMetaInflate; +#if DEBUG + inflated.ID += 1000000; +#endif + return inflated; + } + + // + // Is this member accessible from invocation context + // + public bool IsAccessible (IMemberContext ctx) + { + var ma = Modifiers & Modifiers.AccessibilityMask; + if (ma == Modifiers.PUBLIC) + return true; + + var parentType = /* this as TypeSpec ?? */ DeclaringType; + var ctype = ctx.CurrentType; + + if (ma == Modifiers.PRIVATE) { + if (ctype == null) + return false; + // + // It's only accessible to the current class or children + // + if (parentType.MemberDefinition == ctype.MemberDefinition) + return true; + + return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition); + } + + if ((ma & Modifiers.INTERNAL) != 0) { + bool b; + var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly; + + if (parentType == null) { + b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly); + } else { + b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly); + } + + if (b || ma == Modifiers.INTERNAL) + return b; + } + + // + // Checks whether `ctype' is a subclass or nested child of `parentType'. + // + while (ctype != null) { + if (TypeManager.IsFamilyAccessible (ctype, parentType)) + return true; + + // Handle nested types. + ctype = ctype.DeclaringType; // TODO: Untested ??? + } + + return false; + } + + // + // Returns member CLS compliance based on full member hierarchy + // + public bool IsCLSCompliant () + { + if ((state & StateFlags.CLSCompliant_Undetected) != 0) { + state &= ~StateFlags.CLSCompliant_Undetected; + + bool compliant; + if (IsNotCLSCompliant (out compliant)) + return false; + + if (!compliant) { + if (DeclaringType != null) { + compliant = DeclaringType.IsCLSCompliant (); + } else { + compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant; + } + } + + if (compliant) + state |= StateFlags.CLSCompliant; + } + + return (state & StateFlags.CLSCompliant) != 0; + } + + public bool IsConditionallyExcluded (CompilerContext ctx, Location loc) + { + if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0) + return false; + + var conditions = MemberDefinition.ConditionalConditions (); + if (conditions == null) + return false; + + foreach (var condition in conditions) { + if (loc.CompilationUnit.IsConditionalDefined (ctx, condition)) + return false; + } + + return true; + } + + public override string ToString () + { + return GetSignatureForError (); + } + } + + // + // Member details which are same between all member + // specifications + // + public interface IMemberDefinition + { + bool? CLSAttributeValue { get; } + string Name { get; } + bool IsImported { get; } + + string[] ConditionalConditions (); + ObsoleteAttribute GetAttributeObsolete (); + void SetIsAssigned (); + void SetIsUsed (); + } + + public interface IParametersMember : IInterfaceMemberSpec + { + AParametersCollection Parameters { get; } + } + + public interface IInterfaceMemberSpec + { + TypeSpec MemberType { get; } + } + + // + // Base type container declaration. It exists to handle partial types + // which share same definition (PartialContainer) but have different + // resolve scopes + // + public abstract class DeclSpace : MemberCore { + /// + /// This points to the actual definition that is being + /// created with System.Reflection.Emit + /// + public TypeBuilder TypeBuilder; + + // + // This is the namespace in which this typecontainer + // was declared. We use this to resolve names. + // + public NamespaceContainer NamespaceEntry; + + public readonly string Basename; + + protected Dictionary defined_names; + + public TypeContainer PartialContainer; + + protected readonly bool is_generic; + readonly int count_type_params; + protected TypeParameter[] type_params; + TypeParameter[] type_param_list; + + // + // Whether we are Generic + // + public bool IsGeneric { + get { + if (is_generic) + return true; + else if (Parent != null) + return Parent.IsGeneric; + else + return false; + } + } + + static readonly string[] attribute_targets = new string [] { "type" }; + + public DeclSpace (NamespaceContainer ns, DeclSpace parent, MemberName name, + Attributes attrs) + : base (parent, name, attrs) + { + NamespaceEntry = ns; + Basename = name.Basename; + defined_names = new Dictionary (); + PartialContainer = null; + if (name.TypeArguments != null) { + is_generic = true; + count_type_params = name.TypeArguments.Count; + } + if (parent != null) + count_type_params += parent.count_type_params; + } + + /// + /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts + /// + protected virtual bool AddToContainer (MemberCore symbol, string name) + { + MemberCore mc; + if (!defined_names.TryGetValue (name, out mc)) { + defined_names.Add (name, symbol); + return true; + } + + if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0) + return true; + + if (symbol.EnableOverloadChecks (mc)) + return true; + + InterfaceMemberBase im = mc as InterfaceMemberBase; + if (im != null && im.IsExplicitImpl) + return true; + + Report.SymbolRelatedToPreviousError (mc); + if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) { + Error_MissingPartialModifier (symbol); + return false; + } + + if (symbol is TypeParameter) { + Report.Error (692, symbol.Location, + "Duplicate type parameter `{0}'", symbol.GetSignatureForError ()); + } else { + Report.Error (102, symbol.Location, + "The type `{0}' already contains a definition for `{1}'", + GetSignatureForError (), symbol.MemberName.Name); + } + + return false; + } + + protected void RemoveFromContainer (string name) + { + defined_names.Remove (name); + } + + /// + /// Returns the MemberCore associated with a given name in the declaration + /// space. It doesn't return method based symbols !! + /// + /// + public MemberCore GetDefinition (string name) + { + MemberCore mc = null; + defined_names.TryGetValue (name, out mc); + return mc; + } + + // + // root_types contains all the types. All TopLevel types + // hence have a parent that points to `root_types', that is + // why there is a non-obvious test down here. + // + public bool IsTopLevel { + get { return (Parent != null && Parent.Parent == null); } + } + + public virtual bool IsUnmanagedType () + { + return false; + } + + protected abstract TypeAttributes TypeAttr { get; } + + /// + /// Should be overriten by the appropriate declaration space + /// + public abstract void DefineType (); + + protected void Error_MissingPartialModifier (MemberCore type) + { + Report.Error (260, type.Location, + "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists", + type.GetSignatureForError ()); + } + + public override string GetSignatureForDocumentation () + { + return Name; + } + + public override string GetSignatureForError () + { + return MemberName.GetSignatureForError (); + } + + TypeParameter[] initialize_type_params () + { + if (type_param_list != null) + return type_param_list; + + DeclSpace the_parent = Parent; + if (this is GenericMethod) + the_parent = null; + + var list = new List (); + if (the_parent != null && the_parent.IsGeneric) { + // FIXME: move generics info out of DeclSpace + TypeParameter[] parent_params = the_parent.TypeParameters; + list.AddRange (parent_params); + } + + int count = type_params != null ? type_params.Length : 0; + for (int i = 0; i < count; i++) { + TypeParameter param = type_params [i]; + list.Add (param); + if (Parent.CurrentTypeParameters != null) { + foreach (TypeParameter tp in Parent.CurrentTypeParameters) { + if (tp.Name != param.Name) + continue; + + Report.SymbolRelatedToPreviousError (tp.Location, null); + Report.Warning (693, 3, param.Location, + "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'", + param.Name, Parent.GetSignatureForError ()); + } + } + } + + type_param_list = new TypeParameter [list.Count]; + list.CopyTo (type_param_list, 0); + return type_param_list; + } + +#if FULL_AST + public List PlainConstraints { + get; + private set; + } +#endif + + public List Constraints { + get; + private set; + } + + public virtual void SetParameterInfo (List constraints_list) + { +#if FULL_AST + if (constraints_list != null) { + this.PlainConstraints = constraints_list; + constraints_list = this.Constraints = new List (constraints_list); + } +#else + this.Constraints = constraints_list; +#endif + if (!is_generic) { + if (constraints_list != null) { + Report.Error ( + 80, Location, "Constraints are not allowed " + + "on non-generic declarations"); + } + + return; + } + + TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations (); + type_params = new TypeParameter [names.Length]; + + // + // Register all the names + // + for (int i = 0; i < type_params.Length; i++) { + TypeParameterName name = names [i]; + + Constraints constraints = null; + if (constraints_list != null) { + int total = constraints_list.Count; + for (int ii = 0; ii < total; ++ii) { + Constraints constraints_at = (Constraints)constraints_list[ii]; + // TODO: it is used by iterators only + if (constraints_at == null) { + constraints_list.RemoveAt (ii); + --total; + continue; + } + if (constraints_at.TypeParameter.Value == name.Name) { + constraints = constraints_at; + constraints_list.RemoveAt(ii); + break; + } + } + } + + Variance variance = name.Variance; + if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) { + Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates"); + variance = Variance.None; + } + + type_params [i] = new TypeParameter ( + Parent, i, new MemberName (name.Name, Location), constraints, name.OptAttributes, variance); + + AddToContainer (type_params [i], name.Name); + } + + if (constraints_list != null && constraints_list.Count > 0) { + foreach (Constraints constraint in constraints_list) { + Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", + GetSignatureForError (), constraint.TypeParameter.Value); + } + } + } + + protected TypeParameter[] TypeParameters { + get { + if (!IsGeneric) + throw new InvalidOperationException (); + if ((PartialContainer != null) && (PartialContainer != this)) + return PartialContainer.TypeParameters; + if (type_param_list == null) + initialize_type_params (); + + return type_param_list; + } + } + + public int CountTypeParameters { + get { + return count_type_params; + } + } + + public override string[] ValidAttributeTargets { + get { return attribute_targets; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + if (type_params != null) { + foreach (TypeParameter tp in type_params) { + tp.VerifyClsCompliance (); + } + } + + return true; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs new file mode 100644 index 0000000000..8752aebc19 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs @@ -0,0 +1,774 @@ +// +// delegate.cs: Delegate Handler +// +// Authors: +// Ravi Pratap (ravi@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2009 Novell, Inc (http://www.novell.com) +// + +using System; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + // + // Delegate container implementation + // + public class Delegate : TypeContainer, IParametersMember + { + public FullNamedExpression ReturnType; + readonly ParametersCompiled parameters; + + Constructor Constructor; + Method InvokeBuilder; + Method BeginInvokeBuilder; + Method EndInvokeBuilder; + + static readonly string[] attribute_targets = new string [] { "type", "return" }; + + public static readonly string InvokeMethodName = "Invoke"; + + Expression instance_expr; + ReturnParameter return_attributes; + + const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Delegate (NamespaceContainer ns, DeclSpace parent, FullNamedExpression type, + Modifiers mod_flags, MemberName name, ParametersCompiled param_list, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Delegate) + + { + this.ReturnType = type; + ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, + IsTopLevel ? Modifiers.INTERNAL : + Modifiers.PRIVATE, name.Location, Report); + parameters = param_list; + spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED); + } + + #region Properties + public TypeSpec MemberType { + get { + return ReturnType.Type; + } + } + + public AParametersCollection Parameters { + get { + return parameters; + } + } + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Delegate; + } + } + + protected override bool DoDefineMembers () + { + var builtin_types = Compiler.BuiltinTypes; + + var ctor_parameters = ParametersCompiled.CreateFullyResolved ( + new [] { + new Parameter (new TypeExpression (builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location) + }, + new [] { + builtin_types.Object, + builtin_types.IntPtr + } + ); + + Constructor = new Constructor (this, Constructor.ConstructorName, + Modifiers.PUBLIC, null, ctor_parameters, null, Location); + Constructor.Define (); + + // + // Here the various methods like Invoke, BeginInvoke etc are defined + // + // First, call the `out of band' special method for + // defining recursively any types we need: + // + var p = parameters; + + if (!p.Resolve (this)) + return false; + + // + // Invoke method + // + + // Check accessibility + foreach (var partype in p.Types) { + if (!IsAccessibleAs (partype)) { + Report.SymbolRelatedToPreviousError (partype); + Report.Error (59, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", + TypeManager.CSharpName (partype), GetSignatureForError ()); + } + } + + var ret_type = ReturnType.ResolveAsType (this); + if (ret_type == null) + return false; + + // + // We don't have to check any others because they are all + // guaranteed to be accessible - they are standard types. + // + if (!IsAccessibleAs (ret_type)) { + Report.SymbolRelatedToPreviousError (ret_type); + Report.Error (58, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (ret_type) + "' is less " + + "accessible than delegate `" + GetSignatureForError () + "'"); + return false; + } + + CheckProtectedModifier (); + + if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) { + Method.Error1599 (Location, ret_type, Report); + return false; + } + + TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); + + InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null); + InvokeBuilder.Define (); + + // + // Don't emit async method for compiler generated delegates (e.g. dynamic site containers) + // + if (!IsCompilerGenerated) { + DefineAsyncMethods (Parameters.CallingConvention); + } + + return true; + } + + void DefineAsyncMethods (CallingConventions cc) + { + var iasync_result = Module.PredefinedTypes.IAsyncResult; + var async_callback = Module.PredefinedTypes.AsyncCallback; + + // + // It's ok when async types don't exist, the delegate will have Invoke method only + // + if (!iasync_result.Define () || !async_callback.Define ()) + return; + + // + // BeginInvoke + // + ParametersCompiled async_parameters; + if (Parameters.Count == 0) { + async_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } else { + var compiled = new Parameter[Parameters.Count]; + for (int i = 0; i < compiled.Length; ++i) { + var p = parameters[i]; + compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location), + p.Name, + p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); + } + + async_parameters = new ParametersCompiled (compiled); + } + + async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false, + new Parameter[] { + new Parameter (new TypeExpression (async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location) + }, + new [] { + async_callback.TypeSpec, + Compiler.BuiltinTypes.Object + } + ); + + BeginInvokeBuilder = new Method (this, null, + new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers, + new MemberName ("BeginInvoke"), async_parameters, null); + BeginInvokeBuilder.Define (); + + // + // EndInvoke is a bit more interesting, all the parameters labeled as + // out or ref have to be duplicated here. + // + + // + // Define parameters, and count out/ref parameters + // + ParametersCompiled end_parameters; + int out_params = 0; + + foreach (Parameter p in Parameters.FixedParameters) { + if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) + ++out_params; + } + + if (out_params > 0) { + Parameter[] end_params = new Parameter[out_params]; + + int param = 0; + for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { + Parameter p = parameters [i]; + if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) + continue; + + end_params [param++] = new Parameter (new TypeExpression (p.Type, Location), + p.Name, + p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); + } + + end_parameters = new ParametersCompiled (end_params); + } else { + end_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + + end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false, + new Parameter ( + new TypeExpression (iasync_result.TypeSpec, Location), + "result", Parameter.Modifier.NONE, null, Location), + iasync_result.TypeSpec); + + // + // Create method, define parameters, register parameters with type system + // + EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null); + EndInvokeBuilder.Define (); + } + + public override void DefineConstants () + { + if (!Parameters.IsEmpty) { + parameters.ResolveDefaultValues (this); + } + } + + public override void EmitType () + { + if (ReturnType.Type != null) { + if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.Type.HasDynamicElement) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location); + } + + ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location); + } + + Constructor.ParameterInfo.ApplyAttributes (this, Constructor.ConstructorBuilder); + Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + + parameters.CheckConstraints (this); + parameters.ApplyAttributes (this, InvokeBuilder.MethodBuilder); + InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + + if (BeginInvokeBuilder != null) { + BeginInvokeBuilder.ParameterInfo.ApplyAttributes (this, BeginInvokeBuilder.MethodBuilder); + EndInvokeBuilder.ParameterInfo.ApplyAttributes (this, EndInvokeBuilder.MethodBuilder); + + BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + } + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + base.Emit (); + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_type = Compiler.BuiltinTypes.MulticastDelegate; + base_class = null; + return null; + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | + TypeAttributes.Class | TypeAttributes.Sealed | + base.TypeAttr; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + //TODO: duplicate + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + parameters.VerifyClsCompliance (this); + + if (!InvokeBuilder.MemberType.IsCLSCompliant ()) { + Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + + + public static MethodSpec GetConstructor (TypeSpec delType) + { + var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly); + return (MethodSpec) ctor; + } + + // + // Returns the "Invoke" from a delegate type + // + public static MethodSpec GetInvokeMethod (TypeSpec delType) + { + var invoke = MemberCache.FindMember (delType, + MemberFilter.Method (InvokeMethodName, 0, null, null), + BindingRestriction.DeclaredOnly); + + return (MethodSpec) invoke; + } + + public static AParametersCollection GetParameters (TypeSpec delType) + { + var invoke_mb = GetInvokeMethod (delType); + return invoke_mb.Parameters; + } + + // + // 15.2 Delegate compatibility + // + public static bool IsTypeCovariant (ResolveContext rc, TypeSpec a, TypeSpec b) + { + // + // For each value parameter (a parameter with no ref or out modifier), an + // identity conversion or implicit reference conversion exists from the + // parameter type in D to the corresponding parameter type in M + // + if (a == b) + return true; + + if (rc.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) + return false; + + if (a.IsGenericParameter && b.IsGenericParameter) + return a == b; + + return Convert.ImplicitReferenceConversionExists (a, b); + } + + public static string FullDelegateDesc (MethodSpec invoke_method) + { + return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", ""); + } + + public Expression InstanceExpression { + get { + return instance_expr; + } + set { + instance_expr = value; + } + } + } + + // + // Base class for `NewDelegate' and `ImplicitDelegateCreation' + // + public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler + { + protected MethodSpec constructor_method; + protected MethodGroupExpr method_group; + + public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc) + { + Arguments delegate_arguments = new Arguments (pd.Count); + for (int i = 0; i < pd.Count; ++i) { + Argument.AType atype_modifier; + switch (pd.FixedParameters [i].ModFlags) { + case Parameter.Modifier.REF: + atype_modifier = Argument.AType.Ref; + break; + case Parameter.Modifier.OUT: + atype_modifier = Argument.AType.Out; + break; + default: + atype_modifier = 0; + break; + } + + delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier)); + } + + return delegate_arguments; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc); + + Arguments args = new Arguments (3); + args.Add (new Argument (new TypeOf (type, loc))); + + if (method_group.InstanceExpression == null) + args.Add (new Argument (new NullLiteral (loc))); + else + args.Add (new Argument (method_group.InstanceExpression)); + + args.Add (new Argument (method_group.CreateExpressionTree (ec))); + Expression e = new Invocation (ma, args).Resolve (ec); + if (e == null) + return null; + + e = Convert.ExplicitConversion (ec, e, type, loc); + if (e == null) + return null; + + return e.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + constructor_method = Delegate.GetConstructor (type); + + var invoke_method = Delegate.GetInvokeMethod (type); + + Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc); + method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); + if (method_group == null) + return null; + + var delegate_method = method_group.BestCandidate; + + if (delegate_method.DeclaringType.IsNullableType) { + ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable type", + delegate_method.GetSignatureForError ()); + return null; + } + + Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); + + ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; + if (emg != null) { + method_group.InstanceExpression = emg.ExtensionExpression; + TypeSpec e_type = emg.ExtensionExpression.Type; + if (TypeSpec.IsValueType (e_type)) { + ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", + delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type)); + } + } + + TypeSpec rt = delegate_method.ReturnType; + if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) { + Expression ret_expr = new TypeExpression (rt, loc); + Error_ConversionFailed (ec, delegate_method, ret_expr); + } + + if (delegate_method.IsConditionallyExcluded (ec.Module.Compiler, loc)) { + ec.Report.SymbolRelatedToPreviousError (delegate_method); + MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; + if (m != null && m.IsPartialDefinition) { + ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", + delegate_method.GetSignatureForError ()); + } else { + ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", + TypeManager.CSharpSignature (delegate_method)); + } + } + + var expr = method_group.InstanceExpression; + if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type))) + method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object); + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + if (method_group.InstanceExpression == null) + ec.Emit (OpCodes.Ldnull); + else + method_group.InstanceExpression.Emit (ec); + + var delegate_method = method_group.BestCandidate; + + // Any delegate must be sealed + if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) { + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldvirtftn, delegate_method); + } else { + ec.Emit (OpCodes.Ldftn, delegate_method); + } + + ec.Emit (OpCodes.Newobj, constructor_method); + } + + void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type) + { + var invoke_method = Delegate.GetInvokeMethod (type); + string member_name = method_group.InstanceExpression != null ? + Delegate.FullDelegateDesc (method) : + TypeManager.GetFullNameSignature (method); + + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.SymbolRelatedToPreviousError (method); + if (ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { + ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type", + TypeManager.CSharpName (method.ReturnType), member_name, + TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); + return; + } + + if (return_type == null) { + ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters", + member_name, Delegate.FullDelegateDesc (invoke_method)); + return; + } + + ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type", + return_type.GetSignatureForError (), member_name, + TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); + } + + public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type) + { +// if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type) +// return false; + + var invoke = Delegate.GetInvokeMethod (target_type); + + Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location); + return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + return false; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + Error_ConversionFailed (rc, best as MethodSpec, null); + return true; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + Error_ConversionFailed (rc, best as MethodSpec, null); + return true; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + // + // Created from the conversion code + // + public class ImplicitDelegateCreation : DelegateCreation + { + ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l) + { + type = t; + this.method_group = mg; + loc = l; + } + + static public Expression Create (ResolveContext ec, MethodGroupExpr mge, + TypeSpec target_type, Location loc) + { + ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc); + return d.DoResolve (ec); + } + } + + // + // A delegate-creation-expression, invoked from the `New' class + // + public class NewDelegate : DelegateCreation + { + public Arguments Arguments; + + // + // This constructor is invoked from the `New' expression + // + public NewDelegate (TypeSpec type, Arguments Arguments, Location loc) + { + this.type = type; + this.Arguments = Arguments; + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (Arguments == null || Arguments.Count != 1) { + ec.Report.Error (149, loc, "Method name expected"); + return null; + } + + Argument a = Arguments [0]; + if (!a.ResolveMethodGroup (ec)) + return null; + + Expression e = a.Expr; + + AnonymousMethodExpression ame = e as AnonymousMethodExpression; + if (ame != null && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) { + e = ame.Compatible (ec, type); + if (e == null) + return null; + + return e.Resolve (ec); + } + + method_group = e as MethodGroupExpr; + if (method_group == null) { + if (e.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + e = Convert.ImplicitConversionRequired (ec, e, type, loc); + } else if (!e.Type.IsDelegate) { + e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc); + return null; + } + + // + // An argument is not a method but another delegate + // + method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (e.Type), e.Type, loc); + method_group.InstanceExpression = e; + } + + return base.DoResolve (ec); + } + } + + // + // Invocation converted to delegate Invoke call + // + class DelegateInvocation : ExpressionStatement + { + readonly Expression InstanceExpr; + Arguments arguments; + MethodSpec method; + + public DelegateInvocation (Expression instance_expr, Arguments args, Location loc) + { + this.InstanceExpr = instance_expr; + this.arguments = args; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments, + InstanceExpr.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "Invoke", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + TypeSpec del_type = InstanceExpr.Type; + if (del_type == null) + return null; + + // + // Do only core overload resolution the rest of the checks has been + // done on primary expression + // + method = Delegate.GetInvokeMethod (del_type); + var res = new OverloadResolver (new MemberSpec[] { method }, OverloadResolver.Restrictions.DelegateInvoke, loc); + var valid = res.ResolveMember (ec, ref arguments); + if (valid == null && !res.BestCandidateIsDynamic) + return null; + + type = method.ReturnType; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + // + // Invocation on delegates call the virtual Invoke member + // so we are always `instance' calls + // + Invocation.EmitCall (ec, InstanceExpr, method, arguments, loc); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + // + // Pop the return value if there is one + // + if (type.Kind != MemberKind.Void) + ec.Emit (OpCodes.Pop); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj new file mode 100644 index 0000000000..154cad4949 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj @@ -0,0 +1,154 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56} + Exe + Properties + dmcs + dmcs + v4.0 + 512 + x86 + + + true + full + false + .\ + TRACE;DEBUG;NET_4_0;MS_COMPATIBLE + prompt + 4 + true + + + pdbonly + true + TRACE;NET_2_0;MS_COMPATIBLE;GMCS_SOURCE + prompt + prompt + 4 + .\ + + + + + + + + + + CryptoConvert.cs + + + MonoSymbolFile.cs + + + MonoSymbolTable.cs + + + MonoSymbolWriter.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + outline.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config new file mode 100644 index 0000000000..cab6cf8fa5 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources new file mode 100644 index 0000000000..71a658ad1f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources @@ -0,0 +1,55 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc.cs +driver.cs +dynamic.cs +ecore.cs +enum.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +visit.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs +../tools/monop/outline.cs diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln new file mode 100644 index 0000000000..ac8d1f1ad2 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dmcs", "dmcs.csproj", "{D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs new file mode 100644 index 0000000000..f81f7e86aa --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs @@ -0,0 +1,59 @@ +// +// doc-bootstrap.cs: Stub support for XML documentation. +// +// Author: +// Raja R Harinath +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2004 Novell, Inc. +// +// + +#if BOOTSTRAP_WITH_OLDLIB || NET_2_1 + +using XmlElement = System.Object; + +namespace Mono.CSharp { + public class DocUtil + { + internal static void GenerateTypeDocComment (TypeContainer t, DeclSpace ds, Report r) + { + } + + internal static void GenerateDocComment (MemberCore mc, DeclSpace ds, Report r) + { + } + + public static string GetMethodDocCommentName (MemberCore mc, ParametersCompiled p, DeclSpace ds) + { + return ""; + } + + internal static void OnMethodGenerateDocComment (MethodCore mc, XmlElement el, Report r) + { + } + + public static void GenerateEnumDocComment (Enum e, DeclSpace ds) + { + } + } + + public class Documentation + { + public Documentation (string xml_output_filename) + { + } + + public bool OutputDocComment (string asmfilename, Report r) + { + return true; + } + + public void GenerateDocComment () + { + } + } +} + +#endif diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs new file mode 100644 index 0000000000..769154d691 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs @@ -0,0 +1,645 @@ +// +// doc.cs: Support for XML documentation comment. +// +// Authors: +// Atsushi Enomoto +// Marek Safar (marek.safar@gmail.com> +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2004 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Linq; + +namespace Mono.CSharp +{ + // + // Implements XML documentation generation. + // + class DocumentationBuilder + { + // + // Used to create element which helps well-formedness checking. + // + readonly XmlDocument XmlDocumentation; + + readonly ModuleContainer module; + + // + // The output for XML documentation. + // + XmlWriter XmlCommentOutput; + + static readonly string line_head = Environment.NewLine + " "; + + // + // Stores XmlDocuments that are included in XML documentation. + // Keys are included filenames, values are XmlDocuments. + // + Dictionary StoredDocuments = new Dictionary (); + + public DocumentationBuilder (ModuleContainer module) + { + this.module = module; + XmlDocumentation = new XmlDocument (); + XmlDocumentation.PreserveWhitespace = false; + } + + Report Report { + get { + return module.Compiler.Report; + } + } + + public MemberName ParsedName { + get; set; + } + + public List ParsedParameters { + get; set; + } + + public TypeExpression ParsedBuiltinType { + get; set; + } + + public Operator.OpType? ParsedOperator { + get; set; + } + + XmlNode GetDocCommentNode (MemberCore mc, string name) + { + // FIXME: It could be even optimizable as not + // to use XmlDocument. But anyways the nodes + // are not kept in memory. + XmlDocument doc = XmlDocumentation; + try { + XmlElement el = doc.CreateElement ("member"); + el.SetAttribute ("name", name); + string normalized = mc.DocComment; + el.InnerXml = normalized; + // csc keeps lines as written in the sources + // and inserts formatting indentation (which + // is different from XmlTextWriter.Formatting + // one), but when a start tag contains an + // endline, it joins the next line. We don't + // have to follow such a hacky behavior. + string [] split = + normalized.Split ('\n'); + int j = 0; + for (int i = 0; i < split.Length; i++) { + string s = split [i].TrimEnd (); + if (s.Length > 0) + split [j++] = s; + } + el.InnerXml = line_head + String.Join ( + line_head, split, 0, j); + return el; + } catch (Exception ex) { + Report.Warning (1570, 1, mc.Location, "XML documentation comment on `{0}' is not well-formed XML markup ({1})", + mc.GetSignatureForError (), ex.Message); + + return doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name)); + } + } + + // + // Generates xml doc comments (if any), and if required, + // handle warning report. + // + internal void GenerateDocumentationForMember (MemberCore mc) + { + string name = mc.DocCommentHeader + mc.GetSignatureForDocumentation (); + + XmlNode n = GetDocCommentNode (mc, name); + + XmlElement el = n as XmlElement; + if (el != null) { + var pm = mc as IParametersMember; + if (pm != null) { + CheckParametersComments (mc, pm, el); + } + + // FIXME: it could be done with XmlReader + XmlNodeList nl = n.SelectNodes (".//include"); + if (nl.Count > 0) { + // It could result in current node removal, so prepare another list to iterate. + var al = new List (nl.Count); + foreach (XmlNode inc in nl) + al.Add (inc); + foreach (XmlElement inc in al) + if (!HandleInclude (mc, inc)) + inc.ParentNode.RemoveChild (inc); + } + + // FIXME: it could be done with XmlReader + DeclSpace ds_target = mc as DeclSpace; + if (ds_target == null) + ds_target = mc.Parent; + + foreach (XmlElement see in n.SelectNodes (".//see")) + HandleSee (mc, ds_target, see); + foreach (XmlElement seealso in n.SelectNodes (".//seealso")) + HandleSeeAlso (mc, ds_target, seealso); + foreach (XmlElement see in n.SelectNodes (".//exception")) + HandleException (mc, ds_target, see); + foreach (XmlElement node in n.SelectNodes (".//typeparam")) + HandleTypeParam (mc, node); + foreach (XmlElement node in n.SelectNodes (".//typeparamref")) + HandleTypeParamRef (mc, node); + } + + n.WriteTo (XmlCommentOutput); + } + + // + // Processes "include" element. Check included file and + // embed the document content inside this documentation node. + // + bool HandleInclude (MemberCore mc, XmlElement el) + { + bool keep_include_node = false; + string file = el.GetAttribute ("file"); + string path = el.GetAttribute ("path"); + if (file == "") { + Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `file' attribute"); + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el); + keep_include_node = true; + } + else if (path.Length == 0) { + Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `path' attribute"); + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el); + keep_include_node = true; + } + else { + XmlDocument doc; + if (!StoredDocuments.TryGetValue (file, out doc)) { + try { + doc = new XmlDocument (); + doc.Load (file); + StoredDocuments.Add (file, doc); + } catch (Exception) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file `{0}': cannot be included ", file)), el); + Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- `{0}'", file); + } + } + if (doc != null) { + try { + XmlNodeList nl = doc.SelectNodes (path); + if (nl.Count == 0) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el); + + keep_include_node = true; + } + foreach (XmlNode n in nl) + el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el); + } catch (Exception ex) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el); + Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment `{0}' of file `{1}' ({2})", path, file, ex.Message); + } + } + } + return keep_include_node; + } + + // + // Handles elements. + // + void HandleSee (MemberCore mc, DeclSpace ds, XmlElement see) + { + HandleXrefCommon (mc, ds, see); + } + + // + // Handles elements. + // + void HandleSeeAlso (MemberCore mc, DeclSpace ds, XmlElement seealso) + { + HandleXrefCommon (mc, ds, seealso); + } + + // + // Handles elements. + // + void HandleException (MemberCore mc, DeclSpace ds, XmlElement seealso) + { + HandleXrefCommon (mc, ds, seealso); + } + + // + // Handles node + // + void HandleTypeParam (MemberCore mc, XmlElement node) + { + if (!node.HasAttribute ("name")) + return; + + string tp_name = node.GetAttribute ("name"); + if (mc.CurrentTypeParameters != null) { + foreach (var tp in mc.CurrentTypeParameters) { + if (tp.Name == tp_name) + return; + } + } + + // TODO: CS1710, CS1712 + + mc.Compiler.Report.Warning (1711, 2, mc.Location, + "XML comment on `{0}' has a typeparam name `{1}' but there is no type parameter by that name", + mc.GetSignatureForError (), tp_name); + } + + // + // Handles node + // + void HandleTypeParamRef (MemberCore mc, XmlElement node) + { + if (!node.HasAttribute ("name")) + return; + + string tp_name = node.GetAttribute ("name"); + var member = mc; + do { + if (member.CurrentTypeParameters != null) { + foreach (var tp in member.CurrentTypeParameters) { + if (tp.Name == tp_name) + return; + } + } + + member = member.Parent; + } while (member != null); + + mc.Compiler.Report.Warning (1735, 2, mc.Location, + "XML comment on `{0}' has a typeparamref name `{1}' that could not be resolved", + mc.GetSignatureForError (), tp_name); + } + + FullNamedExpression ResolveMemberName (IMemberContext context, MemberName mn) + { + if (mn.Left == null) + return context.LookupNamespaceOrType (mn.Name, mn.Arity, LookupMode.Probing, Location.Null); + + var left = ResolveMemberName (context, mn.Left); + var ns = left as Namespace; + if (ns != null) + return ns.LookupTypeOrNamespace (context, mn.Name, mn.Arity, LookupMode.Probing, Location.Null); + + TypeExpr texpr = left as TypeExpr; + if (texpr != null) { + var found = MemberCache.FindNestedType (texpr.Type, ParsedName.Name, ParsedName.Arity); + if (found != null) + return new TypeExpression (found, Location.Null); + + return null; + } + + return left; + } + + // + // Processes "see" or "seealso" elements from cref attribute. + // + void HandleXrefCommon (MemberCore mc, DeclSpace ds, XmlElement xref) + { + string cref = xref.GetAttribute ("cref"); + // when, XmlReader, "if (cref == null)" + if (!xref.HasAttribute ("cref")) + return; + + // Nothing to be resolved the reference is marked explicitly + if (cref.Length > 2 && cref [1] == ':') + return; + + // Additional symbols for < and > are allowed for easier XML typing + cref = cref.Replace ('{', '<').Replace ('}', '>'); + + var encoding = module.Compiler.Settings.Encoding; + var s = new MemoryStream (encoding.GetBytes (cref)); + SeekableStreamReader seekable = new SeekableStreamReader (s, encoding); + + var source_file = new CompilationSourceFile ("{documentation}", "", 1); + var doc_module = new ModuleContainer (module.Compiler); + doc_module.DocumentationBuilder = this; + source_file.NamespaceContainer = new NamespaceContainer (null, doc_module, null, source_file); + + Report parse_report = new Report (new NullReportPrinter ()); + var parser = new CSharpParser (seekable, source_file, parse_report); + ParsedParameters = null; + ParsedName = null; + ParsedBuiltinType = null; + ParsedOperator = null; + parser.Lexer.putback_char = Tokenizer.DocumentationXref; + parser.Lexer.parsing_generic_declaration_doc = true; + parser.parse (); + if (parse_report.Errors > 0) { + Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'", + mc.GetSignatureForError (), cref); + + xref.SetAttribute ("cref", "!:" + cref); + return; + } + + MemberSpec member; + string prefix = null; + FullNamedExpression fne = null; + + // + // Try built-in type first because we are using ParsedName as identifier of + // member names on built-in types + // + if (ParsedBuiltinType != null && (ParsedParameters == null || ParsedName != null)) { + member = ParsedBuiltinType.Type; + } else { + member = null; + } + + if (ParsedName != null || ParsedOperator.HasValue) { + TypeSpec type = null; + string member_name = null; + + if (member == null) { + if (ParsedOperator.HasValue) { + type = mc.CurrentType; + } else if (ParsedName.Left != null) { + fne = ResolveMemberName (mc, ParsedName.Left); + if (fne != null) { + var ns = fne as Namespace; + if (ns != null) { + fne = ns.LookupTypeOrNamespace (mc, ParsedName.Name, ParsedName.Arity, LookupMode.Probing, Location.Null); + if (fne != null) { + member = fne.Type; + } + } else { + type = fne.Type; + } + } + } else { + fne = ResolveMemberName (mc, ParsedName); + if (fne == null) { + type = mc.CurrentType; + } else if (ParsedParameters == null) { + member = fne.Type; + } else if (fne.Type.MemberDefinition == mc.CurrentType.MemberDefinition) { + member_name = Constructor.ConstructorName; + type = fne.Type; + } + } + } else { + type = (TypeSpec) member; + member = null; + } + + if (ParsedParameters != null) { + var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ()); + foreach (var pp in ParsedParameters) { + pp.Resolve (mc); + } + mc.Module.Compiler.Report.SetPrinter (old_printer); + } + + if (type != null) { + if (member_name == null) + member_name = ParsedOperator.HasValue ? + Operator.GetMetadataName (ParsedOperator.Value) : ParsedName.Name; + + int parsed_param_count; + if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) { + parsed_param_count = ParsedParameters.Count - 1; + } else if (ParsedParameters != null) { + parsed_param_count = ParsedParameters.Count; + } else { + parsed_param_count = 0; + } + + int parameters_match = -1; + do { + var members = MemberCache.FindMembers (type, member_name, true); + if (members != null) { + foreach (var m in members) { + if (ParsedName != null && m.Arity != ParsedName.Arity) + continue; + + if (ParsedParameters != null) { + IParametersMember pm = m as IParametersMember; + if (pm == null) + continue; + + if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue) + continue; + + int i; + for (i = 0; i < parsed_param_count; ++i) { + var pparam = ParsedParameters[i]; + + if (i >= pm.Parameters.Count || pparam == null || + pparam.TypeSpec != pm.Parameters.Types[i] || + (pparam.Modifier & Parameter.Modifier.SignatureMask) != (pm.Parameters.FixedParameters[i].ModFlags & Parameter.Modifier.SignatureMask)) { + + if (i > parameters_match) { + parameters_match = i; + } + + i = -1; + break; + } + } + + if (i < 0) + continue; + + if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) { + if (pm.MemberType != ParsedParameters[parsed_param_count].TypeSpec) { + parameters_match = parsed_param_count + 1; + continue; + } + } else { + if (parsed_param_count != pm.Parameters.Count) + continue; + } + } + + if (member != null) { + Report.Warning (419, 3, mc.Location, + "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched", + cref, member.GetSignatureForError (), m.GetSignatureForError ()); + + break; + } + + member = m; + } + } + + // Continue with parent type for nested types + if (member == null) { + type = type.DeclaringType; + } else { + type = null; + } + } while (type != null); + + if (member == null && parameters_match >= 0) { + for (int i = parameters_match; i < parsed_param_count; ++i) { + Report.Warning (1580, 1, mc.Location, "Invalid type for parameter `{0}' in XML comment cref attribute `{1}'", + (i + 1).ToString (), cref); + } + + if (parameters_match == parsed_param_count + 1) { + Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref); + } + } + } + } + + if (member == null) { + Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved", + mc.GetSignatureForError (), cref); + cref = "!:" + cref; + } else if (member == InternalType.Namespace) { + cref = "N:" + fne.GetSignatureForError (); + } else { + prefix = GetMemberDocHead (member); + cref = prefix + member.GetSignatureForDocumentation (); + } + + xref.SetAttribute ("cref", cref); + } + + // + // Get a prefix from member type for XML documentation (used + // to formalize cref target name). + // + static string GetMemberDocHead (MemberSpec type) + { + if (type is FieldSpec) + return "F:"; + if (type is MethodSpec) + return "M:"; + if (type is EventSpec) + return "E:"; + if (type is PropertySpec) + return "P:"; + if (type is TypeSpec) + return "T:"; + + throw new NotImplementedException (type.GetType ().ToString ()); + } + + // + // Raised (and passed an XmlElement that contains the comment) + // when GenerateDocComment is writing documentation expectedly. + // + // FIXME: with a few effort, it could be done with XmlReader, + // that means removal of DOM use. + // + void CheckParametersComments (MemberCore member, IParametersMember paramMember, XmlElement el) + { + HashSet found_tags = null; + foreach (XmlElement pelem in el.SelectNodes ("param")) { + string xname = pelem.GetAttribute ("name"); + if (xname.Length == 0) + continue; // really? but MS looks doing so + + if (found_tags == null) { + found_tags = new HashSet (); + } + + if (xname != "" && paramMember.Parameters.GetParameterIndexByName (xname) < 0) { + Report.Warning (1572, 2, member.Location, + "XML comment on `{0}' has a param tag for `{1}', but there is no parameter by that name", + member.GetSignatureForError (), xname); + continue; + } + + if (found_tags.Contains (xname)) { + Report.Warning (1571, 2, member.Location, + "XML comment on `{0}' has a duplicate param tag for `{1}'", + member.GetSignatureForError (), xname); + continue; + } + + found_tags.Add (xname); + } + + if (found_tags != null) { + foreach (Parameter p in paramMember.Parameters.FixedParameters) { + if (!found_tags.Contains (p.Name) && !(p is ArglistParameter)) + Report.Warning (1573, 4, member.Location, + "Parameter `{0}' has no matching param tag in the XML comment for `{1}'", + p.Name, member.GetSignatureForError ()); + } + } + } + + // + // Outputs XML documentation comment from tokenized comments. + // + public bool OutputDocComment (string asmfilename, string xmlFileName) + { + XmlTextWriter w = null; + try { + w = new XmlTextWriter (xmlFileName, null); + w.Indentation = 4; + w.Formatting = Formatting.Indented; + w.WriteStartDocument (); + w.WriteStartElement ("doc"); + w.WriteStartElement ("assembly"); + w.WriteStartElement ("name"); + w.WriteString (Path.GetFileNameWithoutExtension (asmfilename)); + w.WriteEndElement (); // name + w.WriteEndElement (); // assembly + w.WriteStartElement ("members"); + XmlCommentOutput = w; + module.GenerateDocComment (this); + w.WriteFullEndElement (); // members + w.WriteEndElement (); + w.WriteWhitespace (Environment.NewLine); + w.WriteEndDocument (); + return true; + } catch (Exception ex) { + Report.Error (1569, "Error generating XML documentation file `{0}' (`{1}')", xmlFileName, ex.Message); + return false; + } finally { + if (w != null) + w.Close (); + } + } + } + + class DocumentationParameter + { + public readonly Parameter.Modifier Modifier; + public FullNamedExpression Type; + TypeSpec type; + + public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type) + : this (type) + { + this.Modifier = modifier; + } + + public DocumentationParameter (FullNamedExpression type) + { + this.Type = type; + } + + public TypeSpec TypeSpec { + get { + return type; + } + } + + public void Resolve (IMemberContext context) + { + type = Type.ResolveAsType (context); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs new file mode 100644 index 0000000000..de220c3e79 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs @@ -0,0 +1,472 @@ +// +// driver.cs: The compiler command line driver. +// +// Authors: +// Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc +// + +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Globalization; +using System.Diagnostics; + +namespace Mono.CSharp +{ + /// + /// The compiler driver. + /// + class Driver + { + readonly CompilerContext ctx; + + public Driver (CompilerContext ctx) + { + this.ctx = ctx; + } + + Report Report { + get { + return ctx.Report; + } + } + + void tokenize_file (CompilationSourceFile file) + { + Stream input; + + try { + input = File.OpenRead (file.Name); + } catch { + Report.Error (2001, "Source file `" + file.Name + "' could not be found"); + return; + } + + using (input){ + SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding); + Tokenizer lexer = new Tokenizer (reader, file, ctx); + int token, tokens = 0, errors = 0; + + while ((token = lexer.token ()) != Token.EOF){ + tokens++; + if (token == Token.ERROR) + errors++; + } + Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors"); + } + + return; + } + + void Parse (ModuleContainer module) + { + Location.Initialize (module.Compiler.SourceFiles); + + bool tokenize_only = module.Compiler.Settings.TokenizeOnly; + var sources = module.Compiler.SourceFiles; + for (int i = 0; i < sources.Count; ++i) { + if (tokenize_only) { + tokenize_file (sources[i]); + } else { + Parse (sources[i], module); + } + } + } + + public void Parse (CompilationSourceFile file, ModuleContainer module) + { + Stream input; + + try { + input = File.OpenRead (file.Name); + } catch { + Report.Error (2001, "Source file `{0}' could not be found", file.Name); + return; + } + + // Check 'MZ' header + if (input.ReadByte () == 77 && input.ReadByte () == 90) { + Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name); + input.Close (); + return; + } + + input.Position = 0; + SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding); + + Parse (reader, file, module); + reader.Dispose (); + input.Close (); + } + + public void Parse (SeekableStreamReader reader, CompilationSourceFile file, ModuleContainer module) + { + file.NamespaceContainer = new NamespaceContainer (null, module, null, file); + + CSharpParser parser = new CSharpParser (reader, file); + parser.parse (); + } + + public static int Main (string[] args) + { + Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t"; + + var r = new Report (new ConsoleReportPrinter ()); + CommandLineParser cmd = new CommandLineParser (r); + var settings = cmd.ParseArguments (args); + if (settings == null || r.Errors > 0) + return 1; + + if (cmd.HasBeenStopped) + return 0; + + Driver d = new Driver (new CompilerContext (settings, r)); + + if (d.Compile () && d.Report.Errors == 0) { + if (d.Report.Warnings > 0) { + Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings); + } + Environment.Exit (0); + return 0; + } + + + Console.WriteLine("Compilation failed: {0} error(s), {1} warnings", + d.Report.Errors, d.Report.Warnings); + Environment.Exit (1); + return 1; + } + + public static string GetPackageFlags (string packages, Report report) + { + ProcessStartInfo pi = new ProcessStartInfo (); + pi.FileName = "pkg-config"; + pi.RedirectStandardOutput = true; + pi.UseShellExecute = false; + pi.Arguments = "--libs " + packages; + Process p = null; + try { + p = Process.Start (pi); + } catch (Exception e) { + if (report == null) + throw; + + report.Error (-27, "Couldn't run pkg-config: " + e.Message); + return null; + } + + if (p.StandardOutput == null) { + if (report == null) + throw new ApplicationException ("Specified package did not return any information"); + + report.Warning (-27, 1, "Specified package did not return any information"); + p.Close (); + return null; + } + + string pkgout = p.StandardOutput.ReadToEnd (); + p.WaitForExit (); + if (p.ExitCode != 0) { + if (report == null) + throw new ApplicationException (pkgout); + + report.Error (-27, "Error running pkg-config. Check the above output."); + p.Close (); + return null; + } + + p.Close (); + return pkgout; + } + + // + // Main compilation method + // + public bool Compile () + { + var settings = ctx.Settings; + + // + // If we are an exe, require a source file for the entry point or + // if there is nothing to put in the assembly, and we are not a library + // + if (settings.FirstSourceFile == null && + ((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) || + settings.Resources == null)) { + Report.Error (2008, "No files to compile were specified"); + return false; + } + + TimeReporter tr = new TimeReporter (settings.Timestamps); + ctx.TimeReporter = tr; + tr.StartTotal (); + + var module = new ModuleContainer (ctx); + RootContext.ToplevelTypes = module; + + tr.Start (TimeReporter.TimerType.ParseTotal); + Parse (module); + tr.Stop (TimeReporter.TimerType.ParseTotal); + + if (Report.Errors > 0) + return false; + + if (settings.TokenizeOnly || settings.ParseOnly) { + tr.StopTotal (); + tr.ShowStats (); + return true; + } + + var output_file = settings.OutputFile; + string output_file_name; + if (output_file == null) { + var source_file = settings.FirstSourceFile; + + if (source_file == null) { + Report.Error (1562, "If no source files are specified you must specify the output file with -out:"); + return false; + } + + output_file_name = source_file.Name; + int pos = output_file_name.LastIndexOf ('.'); + + if (pos > 0) + output_file_name = output_file_name.Substring (0, pos); + + output_file_name += settings.TargetExt; + output_file = output_file_name; + } else { + output_file_name = Path.GetFileName (output_file); + } + +#if STATIC + var importer = new StaticImporter (module); + var references_loader = new StaticLoader (importer, ctx); + + tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup); + var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file); + assembly.Create (references_loader.Domain); + tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup); + + // Create compiler types first even before any referenced + // assembly is loaded to allow forward referenced types from + // loaded assembly into compiled builder to be resolved + // correctly + tr.Start (TimeReporter.TimerType.CreateTypeTotal); + module.CreateType (); + importer.AddCompiledAssembly (assembly); + tr.Stop (TimeReporter.TimerType.CreateTypeTotal); + + references_loader.LoadReferences (module); + + tr.Start (TimeReporter.TimerType.PredefinedTypesInit); + if (!ctx.BuiltinTypes.CheckDefinitions (module)) + return false; + + tr.Stop (TimeReporter.TimerType.PredefinedTypesInit); + + references_loader.LoadModules (assembly, module.GlobalRootNamespace); +#else + var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file); + module.SetDeclaringAssembly (assembly); + + var importer = new ReflectionImporter (module, ctx.BuiltinTypes); + assembly.Importer = importer; + + var loader = new DynamicLoader (importer, ctx); + loader.LoadReferences (module); + + if (!ctx.BuiltinTypes.CheckDefinitions (module)) + return false; + + if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save)) + return false; + + module.CreateType (); + + loader.LoadModules (assembly, module.GlobalRootNamespace); +#endif + module.InitializePredefinedTypes (); + + tr.Start (TimeReporter.TimerType.UsingResolve); + foreach (var source_file in ctx.SourceFiles) { + source_file.NamespaceContainer.Resolve (); + } + tr.Stop (TimeReporter.TimerType.UsingResolve); + + tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal); + module.Define (); + tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal); + + if (Report.Errors > 0) + return false; + + if (settings.DocumentationFile != null) { + var doc = new DocumentationBuilder (module); + doc.OutputDocComment (output_file, settings.DocumentationFile); + } + + assembly.Resolve (); + + if (Report.Errors > 0) + return false; + + + tr.Start (TimeReporter.TimerType.EmitTotal); + assembly.Emit (); + tr.Stop (TimeReporter.TimerType.EmitTotal); + + if (Report.Errors > 0){ + return false; + } + + tr.Start (TimeReporter.TimerType.CloseTypes); + module.CloseType (); + tr.Stop (TimeReporter.TimerType.CloseTypes); + + tr.Start (TimeReporter.TimerType.Resouces); + assembly.EmbedResources (); + tr.Stop (TimeReporter.TimerType.Resouces); + + if (Report.Errors > 0) + return false; + + assembly.Save (); + +#if STATIC + references_loader.Dispose (); +#endif + tr.StopTotal (); + tr.ShowStats (); + + return Report.Errors == 0; + } + } + + public class CompilerCompilationUnit { + public ModuleContainer ModuleCompiled { get; set; } + public LocationsBag LocationsBag { get; set; } + public UsingsBag UsingsBag { get; set; } + public SpecialsBag SpecialsBag { get; set; } + public object LastYYValue { get; set; } + } + + // + // This is the only public entry point + // + public class CompilerCallableEntryPoint : MarshalByRefObject { + + public static bool InvokeCompiler (string [] args, TextWriter error) + { + try { + var r = new Report (new StreamReportPrinter (error)); + CommandLineParser cmd = new CommandLineParser (r, error); + var setting = cmd.ParseArguments (args); + if (setting == null || r.Errors > 0) + return false; + + var d = new Driver (new CompilerContext (setting, r)); + return d.Compile (); + } finally { + Reset (); + } + } + + public static int[] AllWarningNumbers { + get { + return Report.AllWarnings; + } + } + + public static void Reset () + { + Reset (true); + } + + public static void PartialReset () + { + Reset (false); + } + + public static void Reset (bool full_flag) + { + CSharpParser.yacc_verbose_flag = 0; + Location.Reset (); + + if (!full_flag) + return; + + AnonymousTypeClass.Reset (); + AnonymousMethodBody.Reset (); + AnonymousMethodStorey.Reset (); + SymbolWriter.Reset (); + Switch.Reset (); + Linq.QueryBlock.TransparentParameter.Reset (); + TypeInfo.Reset (); + } + + public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, TextWriter reportStream) + { + return ParseFile (args, input, inputFile, new StreamReportPrinter (reportStream)); + } + + internal static object parseLock = new object (); + + public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, ReportPrinter reportPrinter) + { + lock (parseLock) { + try { + // Driver d = Driver.Create (args, false, null, reportPrinter); + // if (d == null) + // return null; + + var r = new Report (reportPrinter); + CommandLineParser cmd = new CommandLineParser (r, Console.Out); + var setting = cmd.ParseArguments (args); + if (setting == null || r.Errors > 0) + return null; + + CompilerContext ctx = new CompilerContext (setting, r); + + var files = new List (); + var unit = new CompilationSourceFile (inputFile, inputFile, 0); + var module = new ModuleContainer (ctx); + unit.NamespaceContainer = new NamespaceContainer (null, module, null, unit); + files.Add (unit); + Location.Initialize (files); + + // TODO: encoding from driver + SeekableStreamReader reader = new SeekableStreamReader (input, Encoding.Default); + + RootContext.ToplevelTypes = module; + + CSharpParser parser = new CSharpParser (reader, unit); + parser.Lexer.TabSize = 1; + parser.Lexer.sbag = new SpecialsBag (); + parser.LocationsBag = new LocationsBag (); + parser.UsingsBag = new UsingsBag (); + parser.parse (); + + return new CompilerCompilationUnit () { + ModuleCompiled = RootContext.ToplevelTypes, + LocationsBag = parser.LocationsBag, + UsingsBag = parser.UsingsBag, + SpecialsBag = parser.Lexer.sbag, + LastYYValue = parser.LastYYVal + }; + } finally { + Reset (); + } + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs new file mode 100644 index 0000000000..c7df9f7c85 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs @@ -0,0 +1,965 @@ +// +// dynamic.cs: support for dynamic expressions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009 Novell, Inc +// + +using System; +using System.Linq; +using SLE = System.Linq.Expressions; + +#if NET_4_0 +using System.Dynamic; +#endif + +namespace Mono.CSharp +{ + // + // A copy of Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpBinderFlags.cs + // has to be kept in sync + // + [Flags] + public enum CSharpBinderFlags + { + None = 0, + CheckedContext = 1, + InvokeSimpleName = 1 << 1, + InvokeSpecialName = 1 << 2, + BinaryOperationLogical = 1 << 3, + ConvertExplicit = 1 << 4, + ConvertArrayIndex = 1 << 5, + ResultIndexed = 1 << 6, + ValueFromCompoundAssignment = 1 << 7, + ResultDiscarded = 1 << 8 + } + + // + // Type expression with internal dynamic type symbol + // + class DynamicTypeExpr : TypeExpr + { + public DynamicTypeExpr (Location loc) + { + this.loc = loc; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + eclass = ExprClass.Type; + type = ec.Module.Compiler.BuiltinTypes.Dynamic; + return type; + } + } + + #region Dynamic runtime binder expressions + + // + // Expression created from runtime dynamic object value by dynamic binder + // + public class RuntimeValueExpression : Expression, IDynamicAssign, IMemoryLocation + { +#if !NET_4_0 + public class DynamicMetaObject + { + public TypeSpec RuntimeType; + public TypeSpec LimitType; + public SLE.Expression Expression; + } +#endif + + readonly DynamicMetaObject obj; + + public RuntimeValueExpression (DynamicMetaObject obj, TypeSpec type) + { + this.obj = obj; + this.type = type; + this.eclass = ExprClass.Variable; + } + + #region Properties + + public bool IsSuggestionOnly { get; set; } + + public DynamicMetaObject MetaObject { + get { return obj; } + } + + #endregion + + public void AddressOf (EmitContext ec, AddressOp mode) + { + throw new NotImplementedException (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + throw new NotImplementedException (); + } + + #endregion + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { + return obj.Expression; + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + + #if NET_4_0 + if (type.IsStruct && !obj.Expression.Type.IsValueType) + return SLE.Expression.Unbox (obj.Expression, type.GetMetaInfo ()); + + if (obj.Expression.NodeType == SLE.ExpressionType.Parameter) { + if (((SLE.ParameterExpression) obj.Expression).IsByRef) + return obj.Expression; + } + #endif + + return SLE.Expression.Convert (obj.Expression, type.GetMetaInfo ()); +#endif + } + } + + // + // Wraps runtime dynamic expression into expected type. Needed + // to satify expected type check by dynamic binder and no conversion + // is required (ResultDiscarded). + // + public class DynamicResultCast : ShimExpression + { + public DynamicResultCast (TypeSpec type, Expression expr) + : base (expr) + { + this.type = type; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + eclass = ExprClass.Value; + return this; + } + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Block (expr.MakeExpression (ctx), SLE.Expression.Default (type.GetMetaInfo ())); +#endif + } +#endif + } + + #endregion + + // + // Creates dynamic binder expression + // + interface IDynamicBinder + { + Expression CreateCallSiteBinder (ResolveContext ec, Arguments args); + } + + // + // Extends standard assignment interface for expressions + // supported by dynamic resolver + // + interface IDynamicAssign : IAssignMethod + { + SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); + } + + // + // Base dynamic expression statement creator + // + class DynamicExpressionStatement : ExpressionStatement + { + // + // Binder flag dynamic constant, the value is combination of + // flags known at resolve stage and flags known only at emit + // stage + // + protected class BinderFlags : EnumConstant + { + DynamicExpressionStatement statement; + CSharpBinderFlags flags; + + public BinderFlags (CSharpBinderFlags flags, DynamicExpressionStatement statement) + : base (statement.loc) + { + this.flags = flags; + this.statement = statement; + eclass = 0; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Child = new IntConstant (ec.BuiltinTypes, (int) (flags | statement.flags), statement.loc); + + type = ec.Module.PredefinedTypes.BinderFlags.Resolve (); + eclass = Child.eclass; + return this; + } + } + + readonly Arguments arguments; + protected IDynamicBinder binder; + protected Expression binder_expr; + + // Used by BinderFlags + protected CSharpBinderFlags flags; + + TypeSpec binder_type; + TypeParameter[] context_mvars; + + public DynamicExpressionStatement (IDynamicBinder binder, Arguments args, Location loc) + { + this.binder = binder; + this.arguments = args; + this.loc = loc; + } + + public Arguments Arguments { + get { + return arguments; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1963, loc, "An expression tree cannot contain a dynamic operation"); + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + if (DoResolveCore (rc)) + binder_expr = binder.CreateCallSiteBinder (rc, arguments); + + return this; + } + + protected bool DoResolveCore (ResolveContext rc) + { + if (rc.CurrentTypeParameters != null && rc.CurrentTypeParameters[0].IsMethodTypeParameter) + context_mvars = rc.CurrentTypeParameters; + + int errors = rc.Report.Errors; + var pt = rc.Module.PredefinedTypes; + + binder_type = pt.Binder.Resolve (); + pt.CallSite.Resolve (); + pt.CallSiteGeneric.Resolve (); + + eclass = ExprClass.Value; + + if (type == null) + type = rc.BuiltinTypes.Dynamic; + + if (rc.Report.Errors == errors) + return true; + + rc.Report.Error (1969, loc, + "Dynamic operation cannot be compiled without `Microsoft.CSharp.dll' assembly reference"); + return false; + } + + public override void Emit (EmitContext ec) + { + EmitCall (ec, binder_expr, arguments, false); + } + + public override void EmitStatement (EmitContext ec) + { + EmitCall (ec, binder_expr, arguments, true); + } + + protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments, bool isStatement) + { + // + // This method generates all internal infrastructure for a dynamic call. The + // reason why it's quite complicated is the mixture of dynamic and anonymous + // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous + // methods can generate temporary storey as well (AnonStorey). Handling MVAR + // type parameters rewrite is non-trivial in such case as there are various + // combinations possible therefore the mutator is not straightforward. Secondly + // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit + // correct Site field type and its access from EmitContext. + // + + int dyn_args_count = arguments == null ? 0 : arguments.Count; + int default_args = isStatement ? 1 : 2; + var module = ec.Module; + + bool has_ref_out_argument = false; + var targs = new TypeExpression[dyn_args_count + default_args]; + targs[0] = new TypeExpression (module.PredefinedTypes.CallSite.TypeSpec, loc); + + TypeExpression[] targs_for_instance = null; + TypeParameterMutator mutator; + + var site_container = ec.CreateDynamicSite (); + + if (context_mvars != null) { + TypeParameter[] tparam; + TypeContainer sc = site_container; + do { + tparam = sc.CurrentTypeParameters; + sc = sc.Parent; + } while (tparam == null); + + mutator = new TypeParameterMutator (context_mvars, tparam); + + if (!ec.IsAnonymousStoreyMutateRequired) { + targs_for_instance = new TypeExpression[targs.Length]; + targs_for_instance[0] = targs[0]; + } + } else { + mutator = null; + } + + for (int i = 0; i < dyn_args_count; ++i) { + Argument a = arguments[i]; + if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) + has_ref_out_argument = true; + + var t = a.Type; + + // Convert any internal type like dynamic or null to object + if (t.Kind == MemberKind.InternalCompilerType) + t = ec.BuiltinTypes.Object; + + if (targs_for_instance != null) + targs_for_instance[i + 1] = new TypeExpression (t, loc); + + if (mutator != null) + t = t.Mutate (mutator); + + targs[i + 1] = new TypeExpression (t, loc); + } + + TypeExpr del_type = null; + TypeExpr del_type_instance_access = null; + if (!has_ref_out_argument) { + string d_name = isStatement ? "Action" : "Func"; + + TypeExpr te = null; + Namespace type_ns = module.GlobalRootNamespace.GetNamespace ("System", true); + if (type_ns != null) { + te = type_ns.LookupType (module, d_name, dyn_args_count + default_args, LookupMode.Normal, loc); + } + + if (te != null) { + if (!isStatement) { + var t = type; + if (t.Kind == MemberKind.InternalCompilerType) + t = ec.BuiltinTypes.Object; + + if (targs_for_instance != null) + targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression (t, loc); + + if (mutator != null) + t = t.Mutate (mutator); + + targs[targs.Length - 1] = new TypeExpression (t, loc); + } + + del_type = new GenericTypeExpr (te.Type, new TypeArguments (targs), loc); + if (targs_for_instance != null) + del_type_instance_access = new GenericTypeExpr (te.Type, new TypeArguments (targs_for_instance), loc); + else + del_type_instance_access = del_type; + } + } + + // + // Create custom delegate when no appropriate predefined delegate has been found + // + Delegate d; + if (del_type == null) { + TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type; + Parameter[] p = new Parameter[dyn_args_count + 1]; + p[0] = new Parameter (targs[0], "p0", Parameter.Modifier.NONE, null, loc); + + var site = ec.CreateDynamicSite (); + int index = site.Types == null ? 0 : site.Types.Count; + + if (mutator != null) + rt = mutator.Mutate (rt); + + for (int i = 1; i < dyn_args_count + 1; ++i) { + p[i] = new Parameter (targs[i], "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); + } + + d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc), + Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, + new MemberName ("Container" + index.ToString ("X")), + new ParametersCompiled (p), null); + + d.CreateType (); + d.DefineType (); + d.Define (); + d.Emit (); + + site.AddDelegate (d); + del_type = new TypeExpression (d.CurrentType, loc); + if (targs_for_instance != null) { + del_type_instance_access = null; + } else { + del_type_instance_access = del_type; + } + } else { + d = null; + } + + var site_type_decl = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc); + var field = site_container.CreateCallSiteField (site_type_decl, loc); + if (field == null) + return; + + if (del_type_instance_access == null) { + var dt = d.CurrentType.DeclaringType.MakeGenericType (module, context_mvars.Select (l => l.Type).ToArray ()); + del_type_instance_access = new TypeExpression (MemberCache.GetMember (dt, d.CurrentType), loc); + } + + var instanceAccessExprType = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, + new TypeArguments (del_type_instance_access), loc); + + if (instanceAccessExprType.ResolveAsType (ec.MemberContext) == null) + return; + + bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired; + + TypeSpec gt; + if (inflate_using_mvar || context_mvars == null) { + gt = site_container.CurrentType; + } else { + gt = site_container.CurrentType.MakeGenericType (module, context_mvars.Select (l => l.Type).ToArray ()); + } + + // When site container already exists the inflated version has to be + // updated manually to contain newly created field + if (gt is InflatedTypeSpec && site_container.Fields.Count > 1) { + var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes; + var inflator = new TypeParameterInflator (module, gt, tparams, gt.TypeArguments); + gt.MemberCache.AddMember (field.InflateMember (inflator)); + } + + FieldExpr site_field_expr = new FieldExpr (MemberCache.GetMember (gt, field), loc); + + BlockContext bc = new BlockContext (ec.MemberContext, null, ec.BuiltinTypes.Void); + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + Arguments args = new Arguments (1); + args.Add (new Argument (binder)); + StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args))); + + if (s.Resolve (bc)) { + Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc), loc), s, loc); + init.Emit (ec); + } + + args = new Arguments (1 + dyn_args_count); + args.Add (new Argument (site_field_expr)); + if (arguments != null) { + int arg_pos = 1; + foreach (Argument a in arguments) { + if (a is NamedArgument) { + // Name is not valid in this context + args.Add (new Argument (a.Expr, a.ArgType)); + } else { + args.Add (a); + } + + if (inflate_using_mvar && a.Type != targs[arg_pos].Type) + a.Expr.Type = targs[arg_pos].Type; + + ++arg_pos; + } + } + + Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); + if (target != null) + target.Emit (ec); + + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + public static MemberAccess GetBinderNamespace (Location loc) + { + return new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "Microsoft", loc), "CSharp", loc), "RuntimeBinder", loc); + } + + protected MemberAccess GetBinder (string name, Location loc) + { + return new MemberAccess (new TypeExpression (binder_type, loc), name, loc); + } + } + + // + // Dynamic member access compound assignment for events + // + class DynamicEventCompoundAssign : ExpressionStatement + { + class IsEvent : DynamicExpressionStatement, IDynamicBinder + { + string name; + + public IsEvent (string name, Arguments args, Location loc) + : base (null, args, loc) + { + this.name = name; + binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + type = ec.BuiltinTypes.Bool; + + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (0, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + + return new Invocation (GetBinder ("IsEvent", loc), binder_args); + } + } + + Expression condition; + ExpressionStatement invoke, assign; + + public DynamicEventCompoundAssign (string name, Arguments args, ExpressionStatement assignment, ExpressionStatement invoke, Location loc) + { + condition = new IsEvent (name, args, loc); + this.invoke = invoke; + this.assign = assignment; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return condition.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext rc) + { + type = rc.BuiltinTypes.Dynamic; + eclass = ExprClass.Value; + condition = condition.Resolve (rc); + return this; + } + + public override void Emit (EmitContext ec) + { + var rc = new ResolveContext (ec.MemberContext); + var expr = new Conditional (new BooleanExpression (condition), invoke, assign, loc).Resolve (rc); + expr.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + var stmt = new If (condition, new StatementExpression (invoke), new StatementExpression (assign), loc); + stmt.Emit (ec); + } + } + + class DynamicConversion : DynamicExpressionStatement, IDynamicBinder + { + public DynamicConversion (TypeSpec targetType, CSharpBinderFlags flags, Arguments args, Location loc) + : base (null, args, loc) + { + type = targetType; + base.flags = flags; + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (3); + + flags |= ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new TypeOf (type, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + return new Invocation (GetBinder ("Convert", loc), binder_args); + } + } + + class DynamicConstructorBinder : DynamicExpressionStatement, IDynamicBinder + { + public DynamicConstructorBinder (TypeSpec type, Arguments args, Location loc) + : base (null, args, loc) + { + this.type = type; + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (0, this))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (GetBinder ("InvokeConstructor", loc), binder_args); + } + } + + class DynamicIndexBinder : DynamicMemberAssignable + { + bool can_be_mutator; + + public DynamicIndexBinder (Arguments args, Location loc) + : base (args, loc) + { + } + + public DynamicIndexBinder (CSharpBinderFlags flags, Arguments args, Location loc) + : this (args, loc) + { + base.flags = flags; + } + + protected override Expression DoResolve (ResolveContext ec) + { + can_be_mutator = true; + return base.DoResolve (ec); + } + + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) + { + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; + return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args); + } + + protected override Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + // + // Indexer has arguments which complicates things as the setter and getter + // are called in two steps when unary mutator is used. We have to make a + // copy of all variable arguments to not duplicate any side effect. + // + // ++d[++arg, Foo ()] + // + + if (!can_be_mutator) + return base.CreateSetterArguments (rc, rhs); + + var setter_args = new Arguments (Arguments.Count + 1); + for (int i = 0; i < Arguments.Count; ++i) { + var expr = Arguments[i].Expr; + + if (expr is Constant || expr is VariableReference || expr is This) { + setter_args.Add (Arguments [i]); + continue; + } + + LocalVariable temp = LocalVariable.CreateCompilerGenerated (expr.Type, rc.CurrentBlock, loc); + expr = new SimpleAssign (temp.CreateReferenceExpression (rc, expr.Location), expr).Resolve (rc); + Arguments[i].Expr = temp.CreateReferenceExpression (rc, expr.Location).Resolve (rc); + setter_args.Add (Arguments [i].Clone (expr)); + } + + setter_args.Add (new Argument (rhs)); + return setter_args; + } + } + + class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder + { + ATypeNameExpression member; + + public DynamicInvocation (ATypeNameExpression member, Arguments args, Location loc) + : base (null, args, loc) + { + base.binder = this; + this.member = member; + } + + // + // When a return type is known not to be dynamic + // + public DynamicInvocation (ATypeNameExpression member, Arguments args, TypeSpec type, Location loc) + : this (member, args, loc) + { + this.type = type; + } + + public static DynamicInvocation CreateSpecialNameInvoke (ATypeNameExpression member, Arguments args, Location loc) + { + return new DynamicInvocation (member, args, loc) { + flags = CSharpBinderFlags.InvokeSpecialName + }; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (member != null ? 5 : 3); + bool is_member_access = member is MemberAccess; + + CSharpBinderFlags call_flags; + if (!is_member_access && member is SimpleName) { + call_flags = CSharpBinderFlags.InvokeSimpleName; + is_member_access = true; + } else { + call_flags = 0; + } + + binder_args.Add (new Argument (new BinderFlags (call_flags, this))); + + if (is_member_access) + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, member.Name, member.Location))); + + if (member != null && member.HasTypeArguments) { + TypeArguments ta = member.TypeArguments; + if (ta.Resolve (ec)) { + var targs = new ArrayInitializer (ta.Count, loc); + foreach (TypeSpec t in ta.Arguments) + targs.Add (new TypeOf (t, loc)); + + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (targs, loc))); + } + } else if (is_member_access) { + binder_args.Add (new Argument (new NullLiteral (loc))); + } + + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + + Expression real_args; + if (args == null) { + // Cannot be null because .NET trips over + real_args = new ArrayCreation ( + new MemberAccess (GetBinderNamespace (loc), "CSharpArgumentInfo", loc), + new ArrayInitializer (0, loc), loc); + } else { + real_args = new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc); + } + + binder_args.Add (new Argument (real_args)); + + return new Invocation (GetBinder (is_member_access ? "InvokeMember" : "Invoke", loc), binder_args); + } + + public override void EmitStatement (EmitContext ec) + { + flags |= CSharpBinderFlags.ResultDiscarded; + base.EmitStatement (ec); + } + } + + class DynamicMemberBinder : DynamicMemberAssignable + { + readonly string name; + + public DynamicMemberBinder (string name, Arguments args, Location loc) + : base (args, loc) + { + this.name = name; + } + + public DynamicMemberBinder (string name, CSharpBinderFlags flags, Arguments args, Location loc) + : this (name, args, loc) + { + base.flags = flags; + } + + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) + { + Arguments binder_args = new Arguments (4); + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; + return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args); + } + } + + // + // Any member binder which can be source and target of assignment + // + abstract class DynamicMemberAssignable : DynamicExpressionStatement, IDynamicBinder, IAssignMethod + { + Expression setter; + Arguments setter_args; + + protected DynamicMemberAssignable (Arguments args, Location loc) + : base (null, args, loc) + { + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + // + // DoResolve always uses getter + // + return CreateCallSiteBinder (ec, args, false); + } + + protected abstract Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet); + + protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + var setter_args = new Arguments (Arguments.Count + 1); + setter_args.AddRange (Arguments); + setter_args.Add (new Argument (rhs)); + return setter_args; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (right_side == EmptyExpression.OutAccess) { + right_side.DoResolveLValue (rc, this); + return null; + } + + if (DoResolveCore (rc)) { + setter_args = CreateSetterArguments (rc, right_side); + setter = CreateCallSiteBinder (rc, setter_args, true); + } + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + // It's null for ResolveLValue used without assignment + if (binder_expr == null) + EmitCall (ec, setter, Arguments, false); + else + base.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + // It's null for ResolveLValue used without assignment + if (binder_expr == null) + EmitCall (ec, setter, Arguments, true); + else + base.EmitStatement (ec); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + EmitCall (ec, setter, setter_args, !leave_copy); + } + + #endregion + } + + class DynamicUnaryConversion : DynamicExpressionStatement, IDynamicBinder + { + readonly string name; + + public DynamicUnaryConversion (string name, Arguments args, Location loc) + : base (null, args, loc) + { + this.name = name; + base.binder = this; + } + + public static DynamicUnaryConversion CreateIsTrue (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsTrue", args, loc) { type = rc.BuiltinTypes.Bool }; + } + + public static DynamicUnaryConversion CreateIsFalse (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsFalse", args, loc) { type = rc.BuiltinTypes.Bool }; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (4); + + MemberAccess sle = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); + + var flags = ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (GetBinder ("UnaryOperation", loc), binder_args); + } + } + + sealed class DynamicSiteClass : HoistedStoreyClass + { + public DynamicSiteClass (TypeContainer parent, MemberBase host, TypeParameter[] tparams) + : base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC) + { + parent.DynamicSitesCounter++; + } + + public FieldSpec CreateCallSiteField (FullNamedExpression type, Location loc) + { + int index = fields == null ? 0 : fields.Count; + Field f = new HoistedField (this, type, Modifiers.PUBLIC | Modifiers.STATIC, "Site" + index.ToString ("X"), null, loc); + f.Define (); + + AddField (f); + return f.Spec; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs new file mode 100644 index 0000000000..3be2ce0cda --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs @@ -0,0 +1,5920 @@ +// +// ecore.cs: Core of the Expression representation for the intermediate tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.Text; +using SLE = System.Linq.Expressions; +using System.Linq; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// The ExprClass class contains the is used to pass the + /// classification of an expression (value, variable, namespace, + /// type, method group, property access, event access, indexer access, + /// nothing). + /// + public enum ExprClass : byte { + Unresolved = 0, + + Value, + Variable, + Namespace, + Type, + TypeParameter, + MethodGroup, + PropertyAccess, + EventAccess, + IndexerAccess, + Nothing, + } + + /// + /// This is used to tell Resolve in which types of expressions we're + /// interested. + /// + [Flags] + public enum ResolveFlags { + // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess. + VariableOrValue = 1, + + // Returns a type expression. + Type = 1 << 1, + + // Returns a method group. + MethodGroup = 1 << 2, + + TypeParameter = 1 << 3, + + // Mask of all the expression class flags. + MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter, + } + + // + // This is just as a hint to AddressOf of what will be done with the + // address. + [Flags] + public enum AddressOp { + Store = 1, + Load = 2, + LoadStore = 3 + }; + + /// + /// This interface is implemented by variables + /// + public interface IMemoryLocation { + /// + /// The AddressOf method should generate code that loads + /// the address of the object and leaves it on the stack. + /// + /// The `mode' argument is used to notify the expression + /// of whether this will be used to read from the address or + /// write to the address. + /// + /// This is just a hint that can be used to provide good error + /// reporting, and should have no other side effects. + /// + void AddressOf (EmitContext ec, AddressOp mode); + } + + // + // An expressions resolved as a direct variable reference + // + public interface IVariableReference : IFixedExpression + { + bool IsHoisted { get; } + string Name { get; } + VariableInfo VariableInfo { get; } + + void SetHasAddressTaken (); + } + + // + // Implemented by an expression which could be or is always + // fixed + // + public interface IFixedExpression + { + bool IsFixed { get; } + } + + /// + /// Base class for expressions + /// + public abstract class Expression { + public ExprClass eclass; + protected TypeSpec type; + protected Location loc; + + public TypeSpec Type { + get { return type; } + set { type = value; } + } + + public Location Location { + get { return loc; } + } + + public virtual string GetSignatureForError () + { + if (type == null) + return ""; + TypeSpec typeSpec = type.GetDefinition (); + return typeSpec != null ? typeSpec.GetSignatureForError () : ""; + } + + public virtual bool IsNull { + get { + return false; + } + } + + /// + /// Performs semantic analysis on the Expression + /// + /// + /// + /// The Resolve method is invoked to perform the semantic analysis + /// on the node. + /// + /// The return value is an expression (it can be the + /// same expression in some cases) or a new + /// expression that better represents this node. + /// + /// For example, optimizations of Unary (LiteralInt) + /// would return a new LiteralInt with a negated + /// value. + /// + /// If there is an error during semantic analysis, + /// then an error should be reported (using Report) + /// and a null value should be returned. + /// + /// There are two side effects expected from calling + /// Resolve(): the the field variable "eclass" should + /// be set to any value of the enumeration + /// `ExprClass' and the type variable should be set + /// to a valid type (this is the type of the + /// expression). + /// + protected abstract Expression DoResolve (ResolveContext rc); + + public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + return null; + } + + // + // This is used if the expression should be resolved as a type or namespace name. + // the default implementation fails. + // + public virtual TypeSpec ResolveAsType (IMemberContext mc) + { + ResolveContext ec = new ResolveContext (mc); + Expression e = Resolve (ec); + if (e != null) + e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc); + + return null; + } + + public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc) + { + rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member); + } + + public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name) + { + rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); + } + + public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name) + { + rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null", + name, TypeManager.CSharpName (type)); + } + + public static void Error_InvalidExpressionStatement (Report Report, Location loc) + { + Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " + + "expressions can be used as a statement"); + } + + public void Error_InvalidExpressionStatement (BlockContext ec) + { + Error_InvalidExpressionStatement (ec.Report, loc); + } + + public static void Error_VoidInvalidInTheContext (Location loc, Report Report) + { + Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); + } + + public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + Error_ValueCannotBeConvertedCore (ec, loc, target, expl); + } + + protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + // The error was already reported as CS1660 + if (type == InternalType.AnonymousMethod) + return; + + string from_type = type.GetSignatureForError (); + string to_type = target.GetSignatureForError (); + if (from_type == to_type) { + from_type = type.GetSignatureForErrorIncludingAssemblyName (); + to_type = target.GetSignatureForErrorIncludingAssemblyName (); + } + + if (expl) { + ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", + from_type, to_type); + return; + } + + ec.Report.DisableReporting (); + bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null; + ec.Report.EnableReporting (); + + if (expl_exists) { + ec.Report.Error (266, loc, + "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)", + from_type, to_type); + } else { + ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", + from_type, to_type); + } + } + + public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc) + { + // Better message for possible generic expressions + if (member != null && (member.Kind & MemberKind.GenericMask) != 0) { + var report = context.Module.Compiler.Report; + report.SymbolRelatedToPreviousError (member); + if (member is TypeSpec) + member = ((TypeSpec) member).GetDefinition (); + else + member = ((MethodSpec) member).GetGenericMethodDefinition (); + + string name = member.Kind == MemberKind.Method ? "method" : "type"; + if (member.IsGeneric) { + report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)", + name, member.GetSignatureForError (), member.Arity.ToString ()); + } else { + report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments", + name, member.GetSignatureForError ()); + } + } else { + Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc); + } + } + + public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc) + { + context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments", + exprType, name); + } + + protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + Error_TypeDoesNotContainDefinition (ec, loc, type, name); + } + + public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name) + { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", + TypeManager.CSharpName (type), name); + } + + protected static void Error_ValueAssignment (ResolveContext ec, Location loc) + { + ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer"); + } + + protected void Error_VoidPointerOperation (ResolveContext rc) + { + rc.Report.Error (242, loc, "The operation in question is undefined on void pointers"); + } + + public ResolveFlags ExprClassToResolveFlags { + get { + switch (eclass) { + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; + + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; + + case ExprClass.TypeParameter: + return ResolveFlags.TypeParameter; + + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + return ResolveFlags.VariableOrValue; + + default: + throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve"); + } + } + } + + /// + /// Resolves an expression and performs semantic analysis on it. + /// + /// + /// + /// Currently Resolve wraps DoResolve to perform sanity + /// checking and assertion checking on what we expect from Resolve. + /// + public Expression Resolve (ResolveContext ec, ResolveFlags flags) + { + if (eclass != ExprClass.Unresolved) + return this; + + Expression e; + try { + e = DoResolve (ec); + + if (e == null) + return null; + + if ((flags & e.ExprClassToResolveFlags) == 0) { + e.Error_UnexpectedKind (ec, flags, loc); + return null; + } + + if (e.type == null) + throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ()); + + return e; + } catch (Exception ex) { + if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled) + throw; + + ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message); + return EmptyExpression.Null; // TODO: Add location + } + } + + /// + /// Resolves an expression and performs semantic analysis on it. + /// + public Expression Resolve (ResolveContext rc) + { + return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + } + + /// + /// Resolves an expression for LValue assignment + /// + /// + /// + /// Currently ResolveLValue wraps DoResolveLValue to perform sanity + /// checking and assertion checking on what we expect from Resolve + /// + public Expression ResolveLValue (ResolveContext ec, Expression right_side) + { + int errors = ec.Report.Errors; + bool out_access = right_side == EmptyExpression.OutAccess; + + Expression e = DoResolveLValue (ec, right_side); + + if (e != null && out_access && !(e is IMemoryLocation)) { + // FIXME: There's no problem with correctness, the 'Expr = null' handles that. + // Enabling this 'throw' will "only" result in deleting useless code elsewhere, + + //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " + + // e.GetType () + " " + e.GetSignatureForError ()); + e = null; + } + + if (e == null) { + if (errors == ec.Report.Errors) { + if (out_access) + ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); + else + Error_ValueAssignment (ec, loc); + } + return null; + } + + if (e.eclass == ExprClass.Unresolved) + throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); + + if ((e.type == null) && !(e is GenericTypeExpr)) + throw new Exception ("Expression " + e + " did not set its type after Resolve"); + + return e; + } + + public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + rc.Module.Compiler.Report.Error (182, loc, + "An attribute argument must be a constant expression, typeof expression or array creation expression"); + } + + /// + /// Emits the code for the expression + /// + /// + /// + /// The Emit method is invoked to generate the code + /// for the expression. + /// + public abstract void Emit (EmitContext ec); + + + // Emit code to branch to @target if this expression is equivalent to @on_true. + // The default implementation is to emit the value, and then emit a brtrue or brfalse. + // Subclasses can provide more efficient implementations, but those MUST be equivalent, + // including the use of conditional branches. Note also that a branch MUST be emitted + public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + Emit (ec); + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + // Emit this expression for its side effects, not for its value. + // The default implementation is to emit the value, and then throw it away. + // Subclasses can provide more efficient implementations, but those MUST be equivalent + public virtual void EmitSideEffect (EmitContext ec) + { + Emit (ec); + ec.Emit (OpCodes.Pop); + } + + /// + /// Protected constructor. Only derivate types should + /// be able to be created + /// + + protected Expression () + { + } + + /// + /// Returns a fully formed expression after a MemberLookup + /// + /// + static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc) + { + if (spec is EventSpec) + return new EventExpr ((EventSpec) spec, loc); + if (spec is ConstSpec) + return new ConstantExpr ((ConstSpec) spec, loc); + if (spec is FieldSpec) + return new FieldExpr ((FieldSpec) spec, loc); + if (spec is PropertySpec) + return new PropertyExpr ((PropertySpec) spec, loc); + if (spec is TypeSpec) + return new TypeExpression (((TypeSpec) spec), loc); + + return null; + } + + protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc) + { + var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true); + if (ctors == null) { + rc.Report.SymbolRelatedToPreviousError (type); + if (type.IsStruct) { + // Report meaningful error for struct as they always have default ctor in C# context + OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc); + } else { + rc.Report.Error (143, loc, "The class `{0}' has no constructors defined", + type.GetSignatureForError ()); + } + + return null; + } + + var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc); + var ctor = r.ResolveMember (rc, ref args); + if (ctor == null) + return null; + + if ((ctor.Modifiers & Modifiers.PROTECTED) != 0 && !rc.HasSet (ResolveContext.Options.BaseInitializer)) { + MemberExpr.CheckProtectedMemberAccess (rc, ctor, ctor.DeclaringType, loc); + } + + return ctor; + } + + [Flags] + public enum MemberLookupRestrictions + { + None = 0, + InvocableOnly = 1, + ExactArity = 1 << 2, + ReadAccess = 1 << 3 + } + + // + // Lookup type `queried_type' for code in class `container_type' with a qualifier of + // `qualifier_type' or null to lookup members in the current class. + // + public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc) + { + var members = MemberCache.FindMembers (queried_type, name, false); + if (members == null) + return null; + + MemberSpec non_method = null; + MemberSpec ambig_non_method = null; + do { + for (int i = 0; i < members.Count; ++i) { + var member = members[i]; + + // HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there + if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event) + continue; + + if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity) + continue; + + if (!errorMode) { + if (!member.IsAccessible (rc)) + continue; + + // + // With runtime binder we can have a situation where queried type is inaccessible + // because it came via dynamic object, the check about inconsisted accessibility + // had no effect as the type was unknown during compilation + // + // class A { + // private class N { } + // + // public dynamic Foo () + // { + // return new N (); + // } + // } + // + if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) + continue; + } + + if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) { + if (member is MethodSpec) + return new MethodGroupExpr (members, queried_type, loc); + + if (!Invocation.IsMemberInvocable (member)) + continue; + } + + if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) { + non_method = member; + } else if (!errorMode && !member.IsNotCSharpCompatible) { + ambig_non_method = member; + } + } + + if (non_method != null) { + if (ambig_non_method != null && rc != null) { + var report = rc.Module.Compiler.Report; + report.SymbolRelatedToPreviousError (non_method); + report.SymbolRelatedToPreviousError (ambig_non_method); + report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", + non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ()); + } + + if (non_method is MethodSpec) + return new MethodGroupExpr (members, queried_type, loc); + + return ExprClassFromMemberInfo (non_method, loc); + } + + if (members[0].DeclaringType.BaseType == null) + members = null; + else + members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false); + + } while (members != null); + + return null; + } + + protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + throw new NotImplementedException (); + } + + protected void Error_PointerInsideExpressionTree (ResolveContext ec) + { + ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation"); + } + + /// + /// Returns an expression that can be used to invoke operator true + /// on the expression if it exists. + /// + protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc) + { + return GetOperatorTrueOrFalse (ec, e, true, loc); + } + + /// + /// Returns an expression that can be used to invoke operator false + /// on the expression if it exists. + /// + protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc) + { + return GetOperatorTrueOrFalse (ec, e, false, loc); + } + + static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc) + { + var op = is_true ? Operator.OpType.True : Operator.OpType.False; + var methods = MemberCache.GetUserOperator (e.type, op, false); + if (methods == null) + return null; + + Arguments arguments = new Arguments (1); + arguments.Add (new Argument (e)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var oper = res.ResolveOperator (ec, ref arguments); + + if (oper == null) + return null; + + return new UserOperatorCall (oper, arguments, null, loc); + } + + public virtual string ExprClassName + { + get { + switch (eclass){ + case ExprClass.Unresolved: + return "Unresolved"; + case ExprClass.Value: + return "value"; + case ExprClass.Variable: + return "variable"; + case ExprClass.Namespace: + return "namespace"; + case ExprClass.Type: + return "type"; + case ExprClass.MethodGroup: + return "method group"; + case ExprClass.PropertyAccess: + return "property access"; + case ExprClass.EventAccess: + return "event access"; + case ExprClass.IndexerAccess: + return "indexer access"; + case ExprClass.Nothing: + return "null"; + case ExprClass.TypeParameter: + return "type parameter"; + } + throw new Exception ("Should not happen"); + } + } + + /// + /// Reports that we were expecting `expr' to be of class `expected' + /// + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, Location loc) + { + Error_UnexpectedKind (r, mc, expected, ExprClassName, loc); + } + + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, string was, Location loc) + { + string name; + if (mc != null) + name = mc.GetSignatureForError (); + else + name = GetSignatureForError (); + + r.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", + name, was, expected); + } + + public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc) + { + string [] valid = new string [4]; + int count = 0; + + if ((flags & ResolveFlags.VariableOrValue) != 0) { + valid [count++] = "variable"; + valid [count++] = "value"; + } + + if ((flags & ResolveFlags.Type) != 0) + valid [count++] = "type"; + + if ((flags & ResolveFlags.MethodGroup) != 0) + valid [count++] = "method group"; + + if (count == 0) + valid [count++] = "unknown"; + + StringBuilder sb = new StringBuilder (valid [0]); + for (int i = 1; i < count - 1; i++) { + sb.Append ("', `"); + sb.Append (valid [i]); + } + if (count > 1) { + sb.Append ("' or `"); + sb.Append (valid [count - 1]); + } + + ec.Report.Error (119, loc, + "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ()); + } + + public static void UnsafeError (ResolveContext ec, Location loc) + { + UnsafeError (ec.Report, loc); + } + + public static void UnsafeError (Report Report, Location loc) + { + Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context"); + } + + protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec) + { + ec.Report.SymbolRelatedToPreviousError (type); + if (ec.CurrentInitializerVariable != null) { + ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer", + TypeManager.CSharpName (type), GetSignatureForError ()); + } else { + ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable", + GetSignatureForError ()); + } + } + + // + // Converts `source' to an int, uint, long or ulong. + // + protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source) + { + var btypes = ec.BuiltinTypes; + + if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (source)); + return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec); + } + + Expression converted; + + using (ec.Set (ResolveContext.Options.CheckedScope)) { + converted = Convert.ImplicitConversion (ec, source, btypes.Int, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.UInt, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.Long, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc); + + if (converted == null) { + source.Error_ValueCannotBeConverted (ec, source.loc, btypes.Int, false); + return null; + } + } + + // + // Only positive constants are allowed at compile time + // + Constant c = converted as Constant; + if (c != null && c.IsNegative) + Error_NegativeArrayIndex (ec, source.loc); + + // No conversion needed to array index + if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return converted; + + return new ArrayIndexCast (converted, btypes.Int).Resolve (ec); + } + + // + // Derived classes implement this method by cloning the fields that + // could become altered during the Resolve stage + // + // Only expressions that are created for the parser need to implement + // this. + // + protected virtual void CloneTo (CloneContext clonectx, Expression target) + { + throw new NotImplementedException ( + String.Format ( + "CloneTo not implemented for expression {0}", this.GetType ())); + } + + // + // Clones an expression created by the parser. + // + // We only support expressions created by the parser so far, not + // expressions that have been resolved (many more classes would need + // to implement CloneTo). + // + // This infrastructure is here merely for Lambda expressions which + // compile the same code using different type values for the same + // arguments to find the correct overload + // + public virtual Expression Clone (CloneContext clonectx) + { + Expression cloned = (Expression) MemberwiseClone (); + CloneTo (clonectx, cloned); + + return cloned; + } + + // + // Implementation of expression to expression tree conversion + // + public abstract Expression CreateExpressionTree (ResolveContext ec); + + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args) + { + return CreateExpressionFactoryCall (ec, name, null, args, loc); + } + + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args) + { + return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc); + } + + public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc) + { + return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args); + } + + protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc) + { + var t = ec.Module.PredefinedTypes.Expression.Resolve (); + if (t == null) + return null; + + return new TypeExpression (t, loc); + } + + // + // Implemented by all expressions which support conversion from + // compiler expression to invokable runtime expression. Used by + // dynamic C# binder. + // + public virtual SLE.Expression MakeExpression (BuilderContext ctx) + { + throw new NotImplementedException ("MakeExpression for " + GetType ()); + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This is just a base class for expressions that can + /// appear on statements (invocations, object creation, + /// assignments, post/pre increment and decrement). The idea + /// being that they would support an extra Emition interface that + /// does not leave a result on the stack. + /// + public abstract class ExpressionStatement : Expression { + + public ExpressionStatement ResolveStatement (BlockContext ec) + { + Expression e = Resolve (ec); + if (e == null) + return null; + + ExpressionStatement es = e as ExpressionStatement; + if (es == null) + Error_InvalidExpressionStatement (ec); + + return es; + } + + /// + /// Requests the expression to be emitted in a `statement' + /// context. This means that no new value is left on the + /// stack after invoking this method (constrasted with + /// Emit that will always leave a value on the stack). + /// + public abstract void EmitStatement (EmitContext ec); + + public override void EmitSideEffect (EmitContext ec) + { + EmitStatement (ec); + } + } + + /// + /// This kind of cast is used to encapsulate the child + /// whose type is child.Type into an expression that is + /// reported to return "return_type". This is used to encapsulate + /// expressions which have compatible types, but need to be dealt + /// at higher levels with. + /// + /// For example, a "byte" expression could be encapsulated in one + /// of these as an "unsigned int". The type for the expression + /// would be "unsigned int". + /// + /// + public abstract class TypeCast : Expression + { + protected readonly Expression child; + + protected TypeCast (Expression child, TypeSpec return_type) + { + eclass = child.eclass; + loc = child.Location; + type = return_type; + this.child = child; + } + + public Expression Child { + get { + return child; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (child.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOf (type, loc))); + + if (type.IsPointer || child.Type.IsPointer) + Error_PointerInsideExpressionTree (ec); + + return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return ctx.HasSet (BuilderContext.Options.CheckedScope) ? + SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) : + SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ()); +#endif + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing to clone + } + + public override bool IsNull { + get { return child.IsNull; } + } + } + + public class EmptyCast : TypeCast { + EmptyCast (Expression child, TypeSpec target_type) + : base (child, target_type) + { + } + + public static Expression Create (Expression child, TypeSpec type) + { + Constant c = child as Constant; + if (c != null) + return new EmptyConstantCast (c, type); + + EmptyCast e = child as EmptyCast; + if (e != null) + return new EmptyCast (e.child, type); + + return new EmptyCast (child, type); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } + } + + // + // Used for predefined type user operator (no obsolete check, etc.) + // + public class OperatorCast : TypeCast + { + readonly MethodSpec conversion_operator; + + public OperatorCast (Expression expr, TypeSpec target_type) + : this (expr, target_type, target_type, false) + { + } + + public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit) + : this (expr, target_type, target_type, find_explicit) + { + } + + public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit) + : base (expr, returnType) + { + var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit; + var mi = MemberCache.GetUserOperator (declaringType, op, true); + + if (mi != null) { + foreach (MethodSpec oper in mi) { + if (oper.ReturnType != returnType) + continue; + + if (oper.Parameters.Types[0] == expr.Type) { + conversion_operator = oper; + return; + } + } + } + + throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'", + returnType.GetSignatureForError (), expr.Type.GetSignatureForError ()); + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + ec.Emit (OpCodes.Call, conversion_operator); + } + } + + // + // Constant specialization of EmptyCast. + // We need to special case this since an empty cast of + // a constant is still a constant. + // + public class EmptyConstantCast : Constant + { + public readonly Constant child; + + public EmptyConstantCast (Constant child, TypeSpec type) + : base (child.Location) + { + if (child == null) + throw new ArgumentNullException ("child"); + + this.child = child; + this.eclass = child.eclass; + this.type = type; + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + if (child.Type == target_type) + return child; + + // FIXME: check that 'type' can be converted to 'target_type' first + return child.ConvertExplicitly (in_checked_context, target_type); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + child.CreateExpressionTree (ec), + new TypeOf (type, loc)); + + if (type.IsPointer) + Error_PointerInsideExpressionTree (ec); + + return CreateExpressionFactoryCall (ec, "Convert", args); + } + + public override bool IsDefaultValue { + get { return child.IsDefaultValue; } + } + + public override bool IsNegative { + get { return child.IsNegative; } + } + + public override bool IsNull { + get { return child.IsNull; } + } + + public override bool IsOneInteger { + get { return child.IsOneInteger; } + } + + public override bool IsZeroInteger { + get { return child.IsZeroInteger; } + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + + // Only to make verifier happy + if (TypeManager.IsGenericParameter (type) && child.IsNull) + ec.Emit (OpCodes.Unbox_Any, type); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } + + public override object GetValue () + { + return child.GetValue (); + } + + public override string GetValueAsLiteral () + { + return child.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return child.GetValueAsLong (); + } + + public override Constant ConvertImplicitly (TypeSpec target_type) + { + if (type == target_type) + return this; + + // FIXME: Do we need to check user conversions? + if (!Convert.ImplicitStandardConversionExists (this, target_type)) + return null; + + return child.ConvertImplicitly (target_type); + } + } + + /// + /// This class is used to wrap literals which belong inside Enums + /// + public class EnumConstant : Constant + { + public Constant Child; + + public EnumConstant (Constant child, TypeSpec enum_type) + : base (child.Location) + { + this.Child = child; + + this.eclass = ExprClass.Value; + this.type = enum_type; + } + + protected EnumConstant (Location loc) + : base (loc) + { + } + + public override void Emit (EmitContext ec) + { + Child.Emit (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + Child.EncodeAttributeValue (rc, enc, Child.Type); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + Child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + Child.EmitSideEffect (ec); + } + + public override string GetSignatureForError() + { + return TypeManager.CSharpName (Type); + } + + public override object GetValue () + { + return Child.GetValue (); + } + +#if !STATIC + public override object GetTypedValue () + { + // + // The method can be used in dynamic context only (on closed types) + // + // System.Enum.ToObject cannot be called on dynamic types + // EnumBuilder has to be used, but we cannot use EnumBuilder + // because it does not properly support generics + // + return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ()); + } +#endif + + public override string GetValueAsLiteral () + { + return Child.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return Child.GetValueAsLong (); + } + + public EnumConstant Increment() + { + return new EnumConstant (((IntegralConstant) Child).Increment (), type); + } + + public override bool IsDefaultValue { + get { + return Child.IsDefaultValue; + } + } + + public override bool IsZeroInteger { + get { return Child.IsZeroInteger; } + } + + public override bool IsNegative { + get { + return Child.IsNegative; + } + } + + public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type) + { + if (Child.Type == target_type) + return Child; + + return Child.ConvertExplicitly (in_checked_context, target_type); + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) { + return this; + } + + if (!Convert.ImplicitStandardConversionExists (this, type)){ + return null; + } + + return Child.ConvertImplicitly (type); + } + } + + /// + /// This kind of cast is used to encapsulate Value Types in objects. + /// + /// The effect of it is to box the value type emitted by the previous + /// operation. + /// + public class BoxedCast : TypeCast { + + public BoxedCast (Expression expr, TypeSpec target_type) + : base (expr, target_type) + { + eclass = ExprClass.Value; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Only boxing to object type is supported + if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + enc.Encode (child.Type); + child.EncodeAttributeValue (rc, enc, child.Type); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.Emit (OpCodes.Box, child.Type); + } + + public override void EmitSideEffect (EmitContext ec) + { + // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType + // so, we need to emit the box+pop instructions in most cases + if (child.Type.IsStruct && + (type.BuiltinType == BuiltinTypeSpec.Type.Object || type.BuiltinType == BuiltinTypeSpec.Type.ValueType)) + child.EmitSideEffect (ec); + else + base.EmitSideEffect (ec); + } + } + + public class UnboxCast : TypeCast { + public UnboxCast (Expression expr, TypeSpec return_type) + : base (expr, return_type) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.Emit (OpCodes.Unbox_Any, type); + } + } + + /// + /// This is used to perform explicit numeric conversions. + /// + /// Explicit numeric conversions might trigger exceptions in a checked + /// context, so they should generate the conv.ovf opcodes instead of + /// conv opcodes. + /// + public class ConvCast : TypeCast { + public enum Mode : byte { + I1_U1, I1_U2, I1_U4, I1_U8, I1_CH, + U1_I1, U1_CH, + I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH, + U2_I1, U2_U1, U2_I2, U2_CH, + I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH, + U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH, + I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I, + U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I, + CH_I1, CH_U1, CH_I2, + R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH, + R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4, + I_I8, + } + + Mode mode; + + public ConvCast (Expression child, TypeSpec return_type, Mode m) + : base (child, return_type) + { + mode = m; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override string ToString () + { + return String.Format ("ConvCast ({0}, {1})", mode, child); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + switch (mode){ + case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U1_CH: /* nothing */ break; + + case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U2_CH: /* nothing */ break; + + case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break; + case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; + } + } else { + switch (mode){ + case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U2_CH: /* nothing */ break; + + case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.I4_U4: /* nothing */ break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U4_I4: /* nothing */ break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I8_U8: /* nothing */ break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.U8_I8: /* nothing */ break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_I2); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_U8); break; + } + } + } + } + + class OpcodeCast : TypeCast + { + readonly OpCode op; + + public OpcodeCast (Expression child, TypeSpec return_type, OpCode op) + : base (child, return_type) + { + this.op = op; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + ec.Emit (op); + } + + public TypeSpec UnderlyingType { + get { return child.Type; } + } + } + + // + // Opcode casts expression with 2 opcodes but only + // single expression tree node + // + class OpcodeCastDuplex : OpcodeCast + { + readonly OpCode second; + + public OpcodeCastDuplex (Expression child, TypeSpec returnType, OpCode first, OpCode second) + : base (child, returnType, first) + { + this.second = second; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + ec.Emit (second); + } + } + + /// + /// This kind of cast is used to encapsulate a child and cast it + /// to the class requested + /// + public sealed class ClassCast : TypeCast { + readonly bool forced; + + public ClassCast (Expression child, TypeSpec return_type) + : base (child, return_type) + { + } + + public ClassCast (Expression child, TypeSpec return_type, bool forced) + : base (child, return_type) + { + this.forced = forced; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + bool gen = TypeManager.IsGenericParameter (child.Type); + if (gen) + ec.Emit (OpCodes.Box, child.Type); + + if (type.IsGenericParameter) { + ec.Emit (OpCodes.Unbox_Any, type); + return; + } + + if (gen && !forced) + return; + + ec.Emit (OpCodes.Castclass, type); + } + } + + // + // Created during resolving pahse when an expression is wrapped or constantified + // and original expression can be used later (e.g. for expression trees) + // + public class ReducedExpression : Expression + { + sealed class ReducedConstantExpression : EmptyConstantCast + { + readonly Expression orig_expr; + + public ReducedConstantExpression (Constant expr, Expression orig_expr) + : base (expr, expr.Type) + { + this.orig_expr = orig_expr; + } + + public override Constant ConvertImplicitly (TypeSpec target_type) + { + Constant c = base.ConvertImplicitly (target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + + return c; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + Constant c = base.ConvertExplicitly (in_checked_context, target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + return c; + } + } + + sealed class ReducedExpressionStatement : ExpressionStatement + { + readonly Expression orig_expr; + readonly ExpressionStatement stm; + + public ReducedExpressionStatement (ExpressionStatement stm, Expression orig) + { + this.orig_expr = orig; + this.stm = stm; + this.eclass = stm.eclass; + this.type = stm.Type; + + this.loc = orig.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + stm.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + stm.EmitStatement (ec); + } + } + + readonly Expression expr, orig_expr; + + private ReducedExpression (Expression expr, Expression orig_expr) + { + this.expr = expr; + this.eclass = expr.eclass; + this.type = expr.Type; + this.orig_expr = orig_expr; + this.loc = orig_expr.Location; + } + + #region Properties + + public Expression OriginalExpression { + get { + return orig_expr; + } + } + + #endregion + + // + // Creates fully resolved expression switcher + // + public static Constant Create (Constant expr, Expression original_expr) + { + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + + return new ReducedConstantExpression (expr, original_expr); + } + + public static ExpressionStatement Create (ExpressionStatement s, Expression orig) + { + return new ReducedExpressionStatement (s, orig); + } + + public static Expression Create (Expression expr, Expression original_expr) + { + return Create (expr, original_expr, true); + } + + // + // Creates unresolved reduce expression. The original expression has to be + // already resolved. Created expression is constant based based on `expr' + // value unless canBeConstant is used + // + public static Expression Create (Expression expr, Expression original_expr, bool canBeConstant) + { + if (canBeConstant) { + Constant c = expr as Constant; + if (c != null) + return Create (c, original_expr); + } + + ExpressionStatement s = expr as ExpressionStatement; + if (s != null) + return Create (s, original_expr); + + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + + return new ReducedExpression (expr, original_expr); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + expr.EmitBranchable (ec, target, on_true); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return orig_expr.MakeExpression (ctx); + } + } + + // + // Standard composite pattern + // + public abstract class CompositeExpression : Expression + { + protected Expression expr; + + protected CompositeExpression (Expression expr) + { + this.expr = expr; + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext rc) + { + return expr.CreateExpressionTree (rc); + } + + public Expression Child { + get { return expr; } + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr != null) { + type = expr.Type; + eclass = expr.eclass; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + + public override bool IsNull { + get { return expr.IsNull; } + } + } + + // + // Base of expressions used only to narrow resolve flow + // + public abstract class ShimExpression : Expression + { + protected Expression expr; + + protected ShimExpression (Expression expr) + { + this.expr = expr; + } + + public Expression Expr { + get { + return expr; + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + if (expr == null) + return; + + ShimExpression target = (ShimExpression) t; + target.expr = expr.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } + + } + + // + // Unresolved type name expressions + // + public abstract class ATypeNameExpression : FullNamedExpression + { + string name; + protected TypeArguments targs; + + protected ATypeNameExpression (string name, Location l) + { + this.name = name; + loc = l; + } + + protected ATypeNameExpression (string name, TypeArguments targs, Location l) + { + this.name = name; + this.targs = targs; + loc = l; + } + + protected ATypeNameExpression (string name, int arity, Location l) + : this (name, new UnboundTypeArguments (arity), l) + { + } + + #region Properties + + protected int Arity { + get { + return targs == null ? 0 : targs.Count; + } + } + + public bool HasTypeArguments { + get { + return targs != null && !targs.IsEmpty; + } + } + + public string Name { + get { + return name; + } + set { + name = value; + } + } + + public TypeArguments TypeArguments { + get { + return targs; + } + } + + #endregion + + public override bool Equals (object obj) + { + ATypeNameExpression atne = obj as ATypeNameExpression; + return atne != null && atne.Name == Name && + (targs == null || targs.Equals (atne.targs)); + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + // TODO: Move it to MemberCore + public static string GetMemberType (MemberCore mc) + { + if (mc is Property) + return "property"; + if (mc is Indexer) + return "indexer"; + if (mc is FieldBase) + return "field"; + if (mc is MethodCore) + return "method"; + if (mc is EnumMember) + return "enum"; + if (mc is Event) + return "event"; + + return "type"; + } + + public override string GetSignatureForError () + { + if (targs != null) { + return Name + "<" + targs.GetSignatureForError () + ">"; + } + + return Name; + } + + public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction); + } + + /// + /// SimpleName expressions are formed of a single word and only happen at the beginning + /// of a dotted-name. + /// + public class SimpleName : ATypeNameExpression + { + public SimpleName (string name, Location l) + : base (name, l) + { + } + + public SimpleName (string name, TypeArguments args, Location l) + : base (name, args, l) + { + } + + public SimpleName (string name, int arity, Location l) + : base (name, arity, l) + { + } + + public SimpleName GetMethodGroup () + { + return new SimpleName (Name, targs, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return SimpleNameResolve (ec, null, false); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return SimpleNameResolve (ec, right_side, false); + } + + protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ctx) + { + if (ctx.CurrentType != null) { + if (ctx.CurrentMemberDefinition != null) { + MemberCore mc = ctx.CurrentMemberDefinition.Parent.GetDefinition (Name); + if (mc != null) { + Error_UnexpectedKind (ctx.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc); + return; + } + } + } + + // MSAF + var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc); + if (retval != null) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type); + ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc); + return; + } + + retval = ctx.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc); + if (retval != null) { + Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, Arity, loc); + return; + } + + NamespaceContainer.Error_NamespaceNotFound (loc, Name, ctx.Module.Compiler.Report); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, LookupMode.Normal, loc); + + if (fne != null) { + if (fne.Type != null && Arity > 0) { + if (HasTypeArguments) { + GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); + if (ct.ResolveAsType (ec) == null) + return null; + + return ct; + } + + return new GenericOpenTypeExpr (fne.Type, loc); + } + + // + // dynamic namespace is ignored when dynamic is allowed (does not apply to types) + // + if (!(fne is Namespace)) + return fne; + } + + if (Arity == 0 && Name == "dynamic" && ec.Module.Compiler.Settings.Version > LanguageVersion.V_3) { + if (!ec.Module.PredefinedAttributes.Dynamic.IsDefined) { + ec.Module.Compiler.Report.Error (1980, Location, + "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?", + ec.Module.PredefinedAttributes.Dynamic.GetSignatureForError ()); + } + + fne = new DynamicTypeExpr (loc); + fne.ResolveAsType (ec); + } + + if (fne != null) + return fne; + + Error_TypeOrNamespaceNotFound (ec); + return null; + } + + public bool IsPossibleTypeOrNamespace (IMemberContext mc) + { + return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + int lookup_arity = Arity; + bool errorMode = false; + Expression e; + Block current_block = rc.CurrentBlock; + INamedBlockVariable variable = null; + bool variable_found = false; + + while (true) { + // + // Stage 1: binding to local variables or parameters + // + // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility + // + if (current_block != null && lookup_arity == 0) { + if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) { + if (!variable.IsDeclared) { + // We found local name in accessible block but it's not + // initialized yet, maybe the user wanted to bind to something else + errorMode = true; + variable_found = true; + } else { + e = variable.CreateReferenceExpression (rc, loc); + if (e != null) { + if (Arity > 0) + Error_TypeArgumentsCannotBeUsed (rc, "variable", Name, loc); + + return e; + } + } + } + } + + // + // Stage 2: Lookup members if we are inside a type up to top level type for nested types + // + TypeSpec member_type = rc.CurrentType; + for (; member_type != null; member_type = member_type.DeclaringType) { + e = MemberLookup (rc, errorMode, member_type, Name, lookup_arity, restrictions, loc); + if (e == null) + continue; + + var me = e as MemberExpr; + if (me == null) { + // The name matches a type, defer to ResolveAsTypeStep + if (e is TypeExpr) + break; + + continue; + } + + if (errorMode) { + if (variable != null) { + if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) { + rc.Report.Error (844, loc, + "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'", + Name, me.GetSignatureForError ()); + } else { + break; + } + } else if (me is MethodGroupExpr) { + // Leave it to overload resolution to report correct error + } else { + // TODO: rc.Report.SymbolRelatedToPreviousError () + ErrorIsInaccesible (rc, me.GetSignatureForError (), loc); + } + } else { + // LAMESPEC: again, ignores InvocableOnly + if (variable != null) { + rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); + rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); + } + + // + // MemberLookup does not check accessors availability, this is actually needed for properties only + // + var pe = me as PropertyExpr; + if (pe != null) { + + // Break as there is no other overload available anyway + if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) { + if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (rc)) + break; + + pe.Getter = pe.PropertyInfo.Get; + } else { + if (!pe.PropertyInfo.HasSet || !pe.PropertyInfo.Set.IsAccessible (rc)) + break; + + pe.Setter = pe.PropertyInfo.Set; + } + } + } + + // TODO: It's used by EventExpr -> FieldExpr transformation only + // TODO: Should go to MemberAccess + me = me.ResolveMemberAccess (rc, null, null); + + if (Arity > 0) { + targs.Resolve (rc); + me.SetTypeArguments (rc, targs); + } + + return me; + } + + // + // Stage 3: Lookup nested types, namespaces and type parameters in the context + // + if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) { + if (IsPossibleTypeOrNamespace (rc)) { + if (variable != null) { + rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); + rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); + } + + return ResolveAsTypeOrNamespace (rc); + } + } + + if (errorMode) { + if (variable_found) { + rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name); + } else { + if (Arity > 0) { + TypeParameter[] tparams = rc.CurrentTypeParameters; + if (tparams != null) { + foreach (var ctp in tparams) { + if (ctp.Name == Name) { + Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc); + return null; + } + } + } + + var ct = rc.CurrentType; + do { + if (ct.MemberDefinition.TypeParametersCount > 0) { + foreach (var ctp in ct.MemberDefinition.TypeParameters) { + if (ctp.Name == Name) { + Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc); + return null; + } + } + } + + ct = ct.DeclaringType; + } while (ct != null); + } + + if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) { + e = rc.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc); + if (e != null) { + rc.Report.SymbolRelatedToPreviousError (e.Type); + ErrorIsInaccesible (rc, e.GetSignatureForError (), loc); + return e; + } + } + + e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc); + if (e != null) { + if (!(e is TypeExpr) || (restrictions & MemberLookupRestrictions.InvocableOnly) == 0 || !e.Type.IsDelegate) { + Error_TypeArgumentsCannotBeUsed (rc, e.Type, Arity, loc); + return e; + } + } + + rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name); + } + + return ErrorExpression.Instance; + } + + if (rc.Module.Evaluator != null) { + var fi = rc.Module.Evaluator.LookupField (Name); + if (fi != null) + return new FieldExpr (fi.Item1, loc); + } + + lookup_arity = 0; + errorMode = true; + } + } + + Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate) + { + Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None); + + if (e == null) + return null; + + if (right_side != null) { + if (e is TypeExpr) { + e.Error_UnexpectedKind (ec, ResolveFlags.VariableOrValue, loc); + return null; + } + + e = e.ResolveLValue (ec, right_side); + } else { + e = e.Resolve (ec); + } + + //if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location)) + return e; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents a namespace or a type. The name of the class was inspired by + /// section 10.8.1 (Fully Qualified Names). + /// + public abstract class FullNamedExpression : Expression + { + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // Do nothing, most unresolved type expressions cannot be + // resolved to different type + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public abstract FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc); + + // + // This is used to resolve the expression as a type, a null + // value will be returned if the expression is not a type + // reference + // + public override TypeSpec ResolveAsType (IMemberContext mc) + { + FullNamedExpression fne = ResolveAsTypeOrNamespace (mc); + + if (fne == null) + return null; + + TypeExpr te = fne as TypeExpr; + if (te == null) { + fne.Error_UnexpectedKind (mc.Module.Compiler.Report, null, "type", loc); + return null; + } + + te.loc = loc; + + type = te.Type; + + var dep = type.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc); + } + + // + // Obsolete checks cannot be done when resolving base context as they + // require type dependencies to be set but we are in process of resolving them + // + if (!(mc is TypeContainer.BaseContext)) { + ObsoleteAttribute obsolete_attr = type.GetAttributeObsolete (); + if (obsolete_attr != null && !mc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, mc.Module.Compiler.Report); + } + } + + return type; + } + + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree", + GetSignatureForError ()); + } + } + + /// + /// Expression that evaluates to a type + /// + public abstract class TypeExpr : FullNamedExpression + { + public sealed override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc) + { + ResolveAsType (mc); + return this; + } + + protected sealed override Expression DoResolve (ResolveContext ec) + { + ResolveAsType (ec); + return this; + } + + public override bool Equals (object obj) + { + TypeExpr tobj = obj as TypeExpr; + if (tobj == null) + return false; + + return Type == tobj.Type; + } + + public override int GetHashCode () + { + return Type.GetHashCode (); + } + } + + /// + /// Fully resolved Expression that already evaluated to a type + /// + public class TypeExpression : TypeExpr + { + public TypeExpression (TypeSpec t, Location l) + { + Type = t; + eclass = ExprClass.Type; + loc = l; + } + + public sealed override TypeSpec ResolveAsType (IMemberContext ec) + { + return type; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This class denotes an expression which evaluates to a member + /// of a struct or a class. + /// + public abstract class MemberExpr : Expression + { + // + // An instance expression associated with this member, if it's a + // non-static member + // + public Expression InstanceExpression; + + /// + /// The name of this member. + /// + public abstract string Name { + get; + } + + // + // When base.member is used + // + public bool IsBase { + get { return InstanceExpression is BaseThis; } + } + + /// + /// Whether this is an instance member. + /// + public abstract bool IsInstance { + get; + } + + /// + /// Whether this is a static member. + /// + public abstract bool IsStatic { + get; + } + + protected abstract TypeSpec DeclaringType { + get; + } + + // + // Converts best base candidate for virtual method starting from QueriedBaseType + // + protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec method) + { + // + // Only when base.member is used and method is virtual + // + if (!IsBase) + return method; + + // + // Overload resulution works on virtual or non-virtual members only (no overrides). That + // means for base.member access we have to find the closest match after we found best candidate + // + if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) { + // + // The method could already be what we are looking for + // + TypeSpec[] targs = null; + if (method.DeclaringType != InstanceExpression.Type) { + var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec; + if (base_override != null && base_override.DeclaringType != method.DeclaringType) { + if (base_override.IsGeneric) + targs = method.TypeArguments; + + method = base_override; + } + } + + // TODO: For now we do it for any hoisted call even if it's needed for + // hoisted stories only but that requires a new expression wrapper + if (rc.CurrentAnonymousMethod != null) { + if (targs == null && method.IsGeneric) { + targs = method.TypeArguments; + method = method.GetGenericMethodDefinition (); + } + + if (method.Parameters.HasArglist) + throw new NotImplementedException ("__arglist base call proxy"); + + method = rc.CurrentMemberDefinition.Parent.PartialContainer.CreateHoistedBaseCallProxy (rc, method); + + // Ideally this should apply to any proxy rewrite but in the case of unary mutators on + // get/set member expressions second call would fail to proxy because left expression + // would be of 'this' and not 'base' + if (rc.CurrentType.IsStruct) + InstanceExpression = new This (loc).Resolve (rc); + } + + if (targs != null) + method = method.MakeGenericMethod (rc, targs); + } + + // + // Only base will allow this invocation to happen. + // + if (method.IsAbstract) { + Error_CannotCallAbstractBase (rc, method.GetSignatureForError ()); + } + + return method; + } + + protected void CheckProtectedMemberAccess (ResolveContext rc, T member) where T : MemberSpec + { + if (InstanceExpression == null) + return; + + if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) { + CheckProtectedMemberAccess (rc, member, InstanceExpression.Type, loc); + } + } + + public static void CheckProtectedMemberAccess (ResolveContext rc, T member, TypeSpec qualifier, Location loc) where T : MemberSpec + { + var ct = rc.CurrentType; + if (ct == qualifier) + return; + + if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly)) + return; + + qualifier = qualifier.GetDefinition (); + if (ct != qualifier && !IsSameOrBaseQualifier (ct, qualifier)) { + rc.Report.SymbolRelatedToPreviousError (member); + rc.Report.Error (1540, loc, + "Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it", + member.GetSignatureForError (), qualifier.GetSignatureForError (), ct.GetSignatureForError ()); + } + } + + static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype) + { + do { + type = type.GetDefinition (); + + if (type == qtype || TypeManager.IsFamilyAccessible (qtype, type)) + return true; + + type = type.DeclaringType; + } while (type != null); + + return false; + } + + protected void DoBestMemberChecks (ResolveContext rc, T member) where T : MemberSpec, IInterfaceMemberSpec + { + if (InstanceExpression != null) { + InstanceExpression = InstanceExpression.Resolve (rc); + CheckProtectedMemberAccess (rc, member); + } + + if (member.MemberType.IsPointer && !rc.IsUnsafe) { + UnsafeError (rc, loc); + } + + var dep = member.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } + + if (!rc.IsObsolete) { + ObsoleteAttribute oa = member.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, member.GetSignatureForError (), loc, rc.Report); + } + + if (!(member is FieldSpec)) + member.MemberDefinition.SetIsUsed (); + } + + protected virtual void Error_CannotCallAbstractBase (ResolveContext rc, string name) + { + rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); + } + + // + // Implements identicial simple name and type-name + // + public Expression ProbeIdenticalTypeName (ResolveContext rc, Expression left, SimpleName name) + { + var t = left.Type; + if (t.Kind == MemberKind.InternalCompilerType || t is ElementTypeSpec || t.Arity > 0) + return left; + + // In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple-name is + // a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name + + if (left is MemberExpr || left is VariableReference) { + var identical_type = rc.LookupNamespaceOrType (name.Name, 0, LookupMode.Probing, loc) as TypeExpr; + if (identical_type != null && identical_type.Type == left.Type) + return identical_type; + } + + return left; + } + + public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs) + { + if (IsStatic) { + if (InstanceExpression != null) { + if (InstanceExpression is TypeExpr) { + var t = InstanceExpression.Type; + do { + ObsoleteAttribute oa = t.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (oa, t.GetSignatureForError (), loc, rc.Report); + } + + t = t.DeclaringType; + } while (t != null); + } else { + var runtime_expr = InstanceExpression as RuntimeValueExpression; + if (runtime_expr == null || !runtime_expr.IsSuggestionOnly) { + rc.Report.Error (176, loc, + "Static member `{0}' cannot be accessed with an instance reference, qualify it with a type name instead", + GetSignatureForError ()); + } + } + + InstanceExpression = null; + } + + return false; + } + + if (InstanceExpression == null || InstanceExpression is TypeExpr) { + if (InstanceExpression != null || !This.IsThisAvailable (rc, true)) { + if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) + rc.Report.Error (236, loc, + "A field initializer cannot reference the nonstatic field, method, or property `{0}'", + GetSignatureForError ()); + else + rc.Report.Error (120, loc, + "An object reference is required to access non-static member `{0}'", + GetSignatureForError ()); + + return false; + } + + if (!TypeManager.IsFamilyAccessible (rc.CurrentType, DeclaringType)) { + rc.Report.Error (38, loc, + "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", + DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ()); + } + + InstanceExpression = new This (loc); + if (this is FieldExpr && rc.CurrentType.IsStruct) { + using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { + InstanceExpression = InstanceExpression.Resolve (rc); + } + } else { + InstanceExpression = InstanceExpression.Resolve (rc); + } + + return false; + } + + var me = InstanceExpression as MemberExpr; + if (me != null) { + me.ResolveInstanceExpression (rc, rhs); + + var fe = me as FieldExpr; + if (fe != null && fe.IsMarshalByRefAccess (rc)) { + rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); + rc.Report.Warning (1690, 1, loc, + "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", + me.GetSignatureForError ()); + } + + return true; + } + + // + // Run member-access postponed check once we know that + // the expression is not field expression which is the only + // expression which can use uninitialized this + // + if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentType.IsStruct) { + ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc); + } + + // + // Additional checks for l-value member access + // + if (rhs != null) { + // + // TODO: It should be recursive but that would break csc compatibility + // + if (InstanceExpression is UnboxCast) { + rc.Report.Error (445, InstanceExpression.Location, "Cannot modify the result of an unboxing conversion"); + } + } + + return true; + } + + public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + if (left != null && left.IsNull && TypeSpec.IsReferenceType (left.Type)) { + ec.Report.Warning (1720, 1, left.Location, + "Expression will always cause a `{0}'", "System.NullReferenceException"); + } + + InstanceExpression = left; + return this; + } + + protected void EmitInstance (EmitContext ec, bool prepare_for_load) + { + TypeSpec instance_type = InstanceExpression.Type; + if (TypeSpec.IsValueType (instance_type)) { + if (InstanceExpression is IMemoryLocation) { + ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load); + } else { + LocalTemporary t = new LocalTemporary (instance_type); + InstanceExpression.Emit (ec); + t.Store (ec); + t.AddressOf (ec, AddressOp.Store); + } + } else { + InstanceExpression.Emit (ec); + + // Only to make verifier happy + if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeSpec.IsReferenceType (instance_type)) + ec.Emit (OpCodes.Box, instance_type); + } + + if (prepare_for_load) + ec.Emit (OpCodes.Dup); + } + + public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta); + } + + // + // Represents a group of extension method candidates for whole namespace + // + class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler + { + NamespaceContainer namespace_entry; + public readonly Expression ExtensionExpression; + + public ExtensionMethodGroupExpr (IList list, NamespaceContainer n, Expression extensionExpr, Location l) + : base (list.Cast().ToList (), extensionExpr.Type, l) + { + this.namespace_entry = n; + this.ExtensionExpression = extensionExpr; + } + + public override bool IsStatic { + get { return true; } + } + + public override IList GetBaseMembers (TypeSpec baseType) + { + if (namespace_entry == null) + return null; + + // + // For extension methodgroup we are not looking for base members but parent + // namespace extension methods + // + int arity = type_arguments == null ? 0 : type_arguments.Count; + var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry); + if (found == null) + return null; + + return found.Cast ().ToList (); + } + + public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + // We are already here + return null; + } + + public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, OverloadResolver.Restrictions restr) + { + if (arguments == null) + arguments = new Arguments (1); + + arguments.Insert (0, new Argument (ExtensionExpression, Argument.AType.ExtensionType)); + var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr); + + // Store resolved argument and restore original arguments + if (res == null) { + // Clean-up modified arguments for error reporting + arguments.RemoveAt (0); + return null; + } + + var me = ExtensionExpression as MemberExpr; + if (me != null) + me.ResolveInstanceExpression (ec, null); + + InstanceExpression = null; + return this; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous) + { + return false; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + rc.Report.SymbolRelatedToPreviousError (best); + rc.Report.Error (1928, loc, + "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments", + queried_type.GetSignatureForError (), Name, best.GetSignatureForError ()); + + if (index == 0) { + rc.Report.Error (1929, loc, + "Extension method instance type `{0}' cannot be converted to `{1}'", + arg.Type.GetSignatureForError (), ((MethodSpec)best).Parameters.ExtensionMethodType.GetSignatureForError ()); + } + + return true; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + /// + /// MethodGroupExpr represents a group of method candidates which + /// can be resolved to the best method overload + /// + public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider + { + protected IList Methods; + MethodSpec best_candidate; + TypeSpec best_candidate_return; + protected TypeArguments type_arguments; + + SimpleName simple_name; + protected TypeSpec queried_type; + + public MethodGroupExpr (IList mi, TypeSpec type, Location loc) + { + Methods = mi; + this.loc = loc; + this.type = InternalType.MethodGroup; + + eclass = ExprClass.MethodGroup; + queried_type = type; + } + + public MethodGroupExpr (MethodSpec m, TypeSpec type, Location loc) + : this (new MemberSpec[] { m }, type, loc) + { + } + + #region Properties + + public MethodSpec BestCandidate { + get { + return best_candidate; + } + } + + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return; + } + } + + public IList Candidates { + get { + return Methods; + } + } + + protected override TypeSpec DeclaringType { + get { + return queried_type; + } + } + + public override bool IsInstance { + get { + if (best_candidate != null) + return !best_candidate.IsStatic; + + return false; + } + } + + public override bool IsStatic { + get { + if (best_candidate != null) + return best_candidate.IsStatic; + + return false; + } + } + + public override string Name { + get { + if (best_candidate != null) + return best_candidate.Name; + + // TODO: throw ? + return Methods.First ().Name; + } + } + + #endregion + + // + // When best candidate is already know this factory can be used + // to avoid expensive overload resolution to be called + // + // NOTE: InstanceExpression has to be set manually + // + public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc) + { + return new MethodGroupExpr (best, queriedType, loc) { + best_candidate = best, + best_candidate_return = best.ReturnType + }; + } + + public override string GetSignatureForError () + { + if (best_candidate != null) + return best_candidate.GetSignatureForError (); + + return Methods.First ().GetSignatureForError (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (best_candidate == null) { + ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group"); + return null; + } + + if (best_candidate.IsConditionallyExcluded (ec.Module.Compiler, loc)) + ec.Report.Error (765, loc, + "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree"); + + return new TypeOfMethod (best_candidate, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + this.eclass = ExprClass.MethodGroup; + + if (InstanceExpression != null) { + InstanceExpression = InstanceExpression.Resolve (ec); + if (InstanceExpression == null) + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + } + + public void EmitCall (EmitContext ec, Arguments arguments) + { + Invocation.EmitCall (ec, InstanceExpression, best_candidate, arguments, loc); + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", + Name, TypeManager.CSharpName (target)); + } + + public static bool IsExtensionMethodArgument (Expression expr) + { + // + // LAMESPEC: No details about which expressions are not allowed + // + return !(expr is TypeExpr) && !(expr is BaseThis); + } + + /// + /// Find the Applicable Function Members (7.4.2.1) + /// + /// me: Method Group expression with the members to select. + /// it might contain constructors or methods (or anything + /// that maps to a method). + /// + /// Arguments: ArrayList containing resolved Argument objects. + /// + /// loc: The location if we want an error to be reported, or a Null + /// location for "probing" purposes. + /// + /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo) + /// that is the best match of me on Arguments. + /// + /// + public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments args, OverloadResolver.IErrorHandler cerrors, OverloadResolver.Restrictions restr) + { + // TODO: causes issues with probing mode, remove explicit Kind check + if (best_candidate != null && best_candidate.Kind == MemberKind.Destructor) + return this; + + var r = new OverloadResolver (Methods, type_arguments, restr, loc); + if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) { + r.BaseMembersProvider = this; + } + + if (cerrors != null) + r.CustomErrors = cerrors; + + // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting + best_candidate = r.ResolveMember (ec, ref args); + if (best_candidate == null) + return r.BestCandidateIsDynamic ? this : null; + + // Overload resolver had to create a new method group, all checks bellow have already been executed + if (r.BestCandidateNewMethodGroup != null) + return r.BestCandidateNewMethodGroup; + + if (best_candidate.Kind == MemberKind.Method && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0) { + if (InstanceExpression != null) { + if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) { + InstanceExpression = null; + } else { + if (best_candidate.IsStatic && simple_name != null) { + InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name); + } + + InstanceExpression.Resolve (ec); + } + } + + ResolveInstanceExpression (ec, null); + if (InstanceExpression != null) + CheckProtectedMemberAccess (ec, best_candidate); + } + + var base_override = CandidateToBaseOverride (ec, best_candidate); + if (base_override == best_candidate) { + best_candidate_return = r.BestCandidateReturnType; + } else { + best_candidate = base_override; + best_candidate_return = best_candidate.ReturnType; + } + + return this; + } + + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + simple_name = original; + return base.ResolveMemberAccess (ec, left, original); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + type_arguments = ta; + } + + #region IBaseMembersProvider Members + + public virtual IList GetBaseMembers (TypeSpec baseType) + { + return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false); + } + + public IParametersMember GetOverrideMemberParameters (MemberSpec member) + { + if (queried_type == member.DeclaringType) + return null; + + return MemberCache.FindMember (queried_type, new MemberFilter ((MethodSpec) member), + BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember; + } + + // + // Extension methods lookup after ordinary methods candidates failed to apply + // + public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + if (InstanceExpression == null) + return null; + + InstanceExpression = InstanceExpression.Resolve (rc); + if (!IsExtensionMethodArgument (InstanceExpression)) + return null; + + int arity = type_arguments == null ? 0 : type_arguments.Count; + NamespaceContainer methods_scope = null; + var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope); + if (methods == null) + return null; + + var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc); + emg.SetTypeArguments (rc, type_arguments); + return emg; + } + + #endregion + } + + public struct OverloadResolver + { + [Flags] + public enum Restrictions + { + None = 0, + DelegateInvoke = 1, + ProbingOnly = 1 << 1, + CovariantDelegate = 1 << 2, + NoBaseMembers = 1 << 3, + BaseMembersIncluded = 1 << 4 + } + + public interface IBaseMembersProvider + { + IList GetBaseMembers (TypeSpec baseType); + IParametersMember GetOverrideMemberParameters (MemberSpec member); + MethodGroupExpr LookupExtensionMethod (ResolveContext rc); + } + + public interface IErrorHandler + { + bool AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous); + bool ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument a, int index); + bool NoArgumentMatch (ResolveContext rc, MemberSpec best); + bool TypeInferenceFailed (ResolveContext rc, MemberSpec best); + } + + sealed class NoBaseMembers : IBaseMembersProvider + { + public static readonly IBaseMembersProvider Instance = new NoBaseMembers (); + + public IList GetBaseMembers (TypeSpec baseType) + { + return null; + } + + public IParametersMember GetOverrideMemberParameters (MemberSpec member) + { + return null; + } + + public MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + return null; + } + } + + struct AmbiguousCandidate + { + public readonly MemberSpec Member; + public readonly bool Expanded; + public readonly AParametersCollection Parameters; + + public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded) + { + Member = member; + Parameters = parameters; + Expanded = expanded; + } + } + + Location loc; + IList members; + TypeArguments type_arguments; + IBaseMembersProvider base_provider; + IErrorHandler custom_errors; + Restrictions restrictions; + MethodGroupExpr best_candidate_extension_group; + TypeSpec best_candidate_return_type; + + SessionReportPrinter lambda_conv_msgs; + ReportPrinter prev_recorder; + + public OverloadResolver (IList members, Restrictions restrictions, Location loc) + : this (members, null, restrictions, loc) + { + } + + public OverloadResolver (IList members, TypeArguments targs, Restrictions restrictions, Location loc) + : this () + { + if (members == null || members.Count == 0) + throw new ArgumentException ("empty members set"); + + this.members = members; + this.loc = loc; + type_arguments = targs; + this.restrictions = restrictions; + if (IsDelegateInvoke) + this.restrictions |= Restrictions.NoBaseMembers; + + base_provider = NoBaseMembers.Instance; + } + + #region Properties + + public IBaseMembersProvider BaseMembersProvider { + get { + return base_provider; + } + set { + base_provider = value; + } + } + + public bool BestCandidateIsDynamic { get; set; } + + // + // Best candidate was found in newly created MethodGroupExpr, used by extension methods + // + public MethodGroupExpr BestCandidateNewMethodGroup { + get { + return best_candidate_extension_group; + } + } + + // + // Return type can be different between best candidate and closest override + // + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return_type; + } + } + + public IErrorHandler CustomErrors { + get { + return custom_errors; + } + set { + custom_errors = value; + } + } + + TypeSpec DelegateType { + get { + if ((restrictions & Restrictions.DelegateInvoke) == 0) + throw new InternalErrorException ("Not running in delegate mode", loc); + + return members [0].DeclaringType; + } + } + + bool IsProbingOnly { + get { + return (restrictions & Restrictions.ProbingOnly) != 0; + } + } + + bool IsDelegateInvoke { + get { + return (restrictions & Restrictions.DelegateInvoke) != 0; + } + } + + #endregion + + // + // 7.4.3.3 Better conversion from expression + // Returns : 1 if a->p is better, + // 2 if a->q is better, + // 0 if neither is better + // + static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q) + { + TypeSpec argument_type = a.Type; + + // + // If argument is an anonymous function + // + if (argument_type == InternalType.AnonymousMethod && ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2) { + // + // p and q are delegate types or expression tree types + // + if (p.IsExpressionTreeType || q.IsExpressionTreeType) { + if (q.MemberDefinition != p.MemberDefinition) { + return 0; + } + + // + // Uwrap delegate from Expression + // + q = TypeManager.GetTypeArguments (q)[0]; + p = TypeManager.GetTypeArguments (p)[0]; + } + + var p_m = Delegate.GetInvokeMethod (p); + var q_m = Delegate.GetInvokeMethod (q); + + // + // With identical parameter lists + // + if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types)) + return 0; + + p = p_m.ReturnType; + q = q_m.ReturnType; + + // + // if p is void returning, and q has a return type Y, then C2 is the better conversion. + // + if (p.Kind == MemberKind.Void) { + return q.Kind != MemberKind.Void ? 2 : 0; + } + + // + // if p has a return type Y, and q is void returning, then C1 is the better conversion. + // + if (q.Kind == MemberKind.Void) { + return p.Kind != MemberKind.Void ? 1: 0; + } + + // + // When anonymous method is an asynchronous, and P has a return type Task, and Q has a return type Task + // better conversion is performed between underlying types Y1 and Y2 + // + if (p.IsGenericTask || q.IsGenericTask) { + if (p.IsGenericTask != q.IsGenericTask) { + return 0; + } + + var async_am = a.Expr as AnonymousMethodExpression; + if (async_am == null || !async_am.IsAsync) + return 0; + + q = q.TypeArguments[0]; + p = p.TypeArguments[0]; + } + + // + // The parameters are identicial and return type is not void, use better type conversion + // on return type to determine better one + // + } else { + if (argument_type == p) + return 1; + + if (argument_type == q) + return 2; + } + + return BetterTypeConversion (ec, p, q); + } + + // + // 7.4.3.4 Better conversion from type + // + public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q) + { + if (p == null || q == null) + throw new InternalErrorException ("BetterTypeConversion got a null conversion"); + + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (q.BuiltinType == BuiltinTypeSpec.Type.UInt || q.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 1; + break; + case BuiltinTypeSpec.Type.Long: + if (q.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 1; + break; + case BuiltinTypeSpec.Type.SByte: + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 1; + } + break; + case BuiltinTypeSpec.Type.Short: + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 1; + } + break; + case BuiltinTypeSpec.Type.Dynamic: + // Dynamic is never better + return 2; + } + + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (p.BuiltinType == BuiltinTypeSpec.Type.UInt || p.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 2; + break; + case BuiltinTypeSpec.Type.Long: + if (p.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 2; + break; + case BuiltinTypeSpec.Type.SByte: + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 2; + } + break; + case BuiltinTypeSpec.Type.Short: + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 2; + } + break; + case BuiltinTypeSpec.Type.Dynamic: + // Dynamic is never better + return 1; + } + + // FIXME: handle lifted operators + + // TODO: this is expensive + Expression p_tmp = new EmptyExpression (p); + Expression q_tmp = new EmptyExpression (q); + + bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q); + bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p); + + if (p_to_q && !q_to_p) + return 1; + + if (q_to_p && !p_to_q) + return 2; + + return 0; + } + + /// + /// Determines "Better function" between candidate + /// and the current best match + /// + /// + /// Returns a boolean indicating : + /// false if candidate ain't better + /// true if candidate is better than the current best match + /// + static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params, + MemberSpec best, AParametersCollection bparam, bool best_params) + { + AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters; + AParametersCollection best_pd = ((IParametersMember) best).Parameters; + + bool better_at_least_one = false; + bool same = true; + int args_count = args == null ? 0 : args.Count; + int j = 0; + Argument a = null; + TypeSpec ct, bt; + for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) { + a = args[j]; + + // Default arguments are ignored for better decision + if (a.IsDefaultArgument) + break; + + // + // When comparing named argument the parameter type index has to be looked up + // in original parameter set (override version for virtual members) + // + NamedArgument na = a as NamedArgument; + if (na != null) { + int idx = cparam.GetParameterIndexByName (na.Name); + ct = candidate_pd.Types[idx]; + if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + ct = TypeManager.GetElementType (ct); + + idx = bparam.GetParameterIndexByName (na.Name); + bt = best_pd.Types[idx]; + if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + bt = TypeManager.GetElementType (bt); + } else { + ct = candidate_pd.Types[c_idx]; + bt = best_pd.Types[b_idx]; + + if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { + ct = TypeManager.GetElementType (ct); + --c_idx; + } + + if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { + bt = TypeManager.GetElementType (bt); + --b_idx; + } + } + + if (TypeSpecComparer.IsEqual (ct, bt)) + continue; + + same = false; + int result = BetterExpressionConversion (ec, a, ct, bt); + + // for each argument, the conversion to 'ct' should be no worse than + // the conversion to 'bt'. + if (result == 2) + return false; + + // for at least one argument, the conversion to 'ct' should be better than + // the conversion to 'bt'. + if (result != 0) + better_at_least_one = true; + } + + if (better_at_least_one) + return true; + + // + // This handles the case + // + // Add (float f1, float f2, float f3); + // Add (params decimal [] foo); + // + // The call Add (3, 4, 5) should be ambiguous. Without this check, the + // first candidate would've chosen as better. + // + if (!same && !a.IsDefaultArgument) + return false; + + // + // The two methods have equal non-optional parameter types, apply tie-breaking rules + // + + // + // This handles the following cases: + // + // Foo (int i) is better than Foo (int i, long l = 0) + // Foo (params int[] args) is better than Foo (int i = 0, params int[] args) + // + // Prefer non-optional version + // + // LAMESPEC: Specification claims this should be done at last but the opposite is true + // + if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) { + if (candidate_pd.Count >= best_pd.Count) + return false; + + if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue) + return false; + + return true; + } + + // + // One is a non-generic method and second is a generic method, then non-generic is better + // + if (best.IsGeneric != candidate.IsGeneric) + return best.IsGeneric; + + // + // This handles the following cases: + // + // Trim () is better than Trim (params char[] chars) + // Concat (string s1, string s2, string s3) is better than + // Concat (string s1, params string [] srest) + // Foo (int, params int [] rest) is better than Foo (params int [] rest) + // + // Prefer non-expanded version + // + if (candidate_params != best_params) + return best_params; + + int candidate_param_count = candidate_pd.Count; + int best_param_count = best_pd.Count; + + if (candidate_param_count != best_param_count) + // can only happen if (candidate_params && best_params) + return candidate_param_count > best_param_count && best_pd.HasParams; + + // + // Both methods have the same number of parameters, and the parameters have equal types + // Pick the "more specific" signature using rules over original (non-inflated) types + // + var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters; + var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters; + + bool specific_at_least_once = false; + for (j = 0; j < args_count; ++j) { + NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument; + if (na != null) { + ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)]; + bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)]; + } else { + ct = candidate_def_pd.Types[j]; + bt = best_def_pd.Types[j]; + } + + if (ct == bt) + continue; + TypeSpec specific = MoreSpecific (ct, bt); + if (specific == bt) + return false; + if (specific == ct) + specific_at_least_once = true; + } + + if (specific_at_least_once) + return true; + + return false; + } + + public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, int argCount, Location loc) + { + rc.Report.Error (1729, loc, + "The type `{0}' does not contain a constructor that takes `{1}' arguments", + type.GetSignatureForError (), argCount.ToString ()); + } + + // + // Determines if the candidate method is applicable to the given set of arguments + // There could be two different set of parameters for same candidate where one + // is the closest override for default values and named arguments checks and second + // one being the virtual base for the parameter types and modifiers. + // + // A return value rates candidate method compatibility, + // 0 = the best, int.MaxValue = the worst + // + int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType) + { + // Parameters of most-derived type used mainly for named and optional parameters + var pd = pm.Parameters; + + // Used for params modifier only, that's legacy of C# 1.0 which uses base type for + // params modifier instead of most-derived type + var cpd = ((IParametersMember) candidate).Parameters; + int param_count = pd.Count; + int optional_count = 0; + int score; + Arguments orig_args = arguments; + + if (arg_count != param_count) { + for (int i = 0; i < pd.Count; ++i) { + if (pd.FixedParameters[i].HasDefaultValue) { + optional_count = pd.Count - i; + break; + } + } + + if (optional_count != 0) { + // Readjust expected number when params used + if (cpd.HasParams) { + optional_count--; + if (arg_count < param_count) + param_count--; + } else if (arg_count > param_count) { + int args_gap = System.Math.Abs (arg_count - param_count); + return int.MaxValue - 10000 + args_gap; + } + } else if (arg_count != param_count) { + int args_gap = System.Math.Abs (arg_count - param_count); + if (!cpd.HasParams) + return int.MaxValue - 10000 + args_gap; + if (arg_count < param_count - 1) + return int.MaxValue - 10000 + args_gap; + } + + // Resize to fit optional arguments + if (optional_count != 0) { + if (arguments == null) { + arguments = new Arguments (optional_count); + } else { + // Have to create a new container, so the next run can do same + var resized = new Arguments (param_count); + resized.AddRange (arguments); + arguments = resized; + } + + for (int i = arg_count; i < param_count; ++i) + arguments.Add (null); + } + } + + if (arg_count > 0) { + // + // Shuffle named arguments to the right positions if there are any + // + if (arguments[arg_count - 1] is NamedArgument) { + arg_count = arguments.Count; + + for (int i = 0; i < arg_count; ++i) { + bool arg_moved = false; + while (true) { + NamedArgument na = arguments[i] as NamedArgument; + if (na == null) + break; + + int index = pd.GetParameterIndexByName (na.Name); + + // Named parameter not found + if (index < 0) + return (i + 1) * 3; + + // already reordered + if (index == i) + break; + + Argument temp; + if (index >= param_count) { + // When using parameters which should not be available to the user + if ((cpd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0) + break; + + arguments.Add (null); + ++arg_count; + temp = null; + } else { + temp = arguments[index]; + + // The slot has been taken by positional argument + if (temp != null && !(temp is NamedArgument)) + break; + } + + if (!arg_moved) { + arguments = arguments.MarkOrderedArgument (na); + arg_moved = true; + } + + arguments[index] = arguments[i]; + arguments[i] = temp; + + if (temp == null) + break; + } + } + } else { + arg_count = arguments.Count; + } + } else if (arguments != null) { + arg_count = arguments.Count; + } + + // + // 1. Handle generic method using type arguments when specified or type inference + // + TypeSpec[] ptypes; + var ms = candidate as MethodSpec; + if (ms != null && ms.IsGeneric) { + // Setup constraint checker for probing only + ConstraintChecker cc = new ConstraintChecker (null); + + if (type_arguments != null) { + var g_args_count = ms.Arity; + if (g_args_count != type_arguments.Count) + return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); + + ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); + } else { + // TODO: It should not be here (we don't know yet whether any argument is lambda) but + // for now it simplifies things. I should probably add a callback to ResolveContext + if (lambda_conv_msgs == null) { + lambda_conv_msgs = new SessionReportPrinter (); + prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); + } + + var ti = new TypeInference (arguments); + TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); + lambda_conv_msgs.EndSession (); + + if (i_args == null) + return ti.InferenceScore - 20000; + + if (i_args.Length != 0) { + ms = ms.MakeGenericMethod (ec, i_args); + } + + cc.IgnoreInferredDynamic = true; + } + + // + // Type arguments constraints have to match for the method to be applicable + // + if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc)) { + candidate = ms; + return int.MaxValue - 25000; + } + + // + // We have a generic return type and at same time the method is override which + // means we have to also inflate override return type in case the candidate is + // best candidate and override return type is different to base return type. + // + // virtual Foo with override Foo + // + if (candidate != pm) { + MethodSpec override_ms = (MethodSpec) pm; + var inflator = new TypeParameterInflator (ec, ms.DeclaringType, override_ms.GenericDefinition.TypeParameters, ms.TypeArguments); + returnType = inflator.Inflate (returnType); + } else { + returnType = ms.ReturnType; + } + + candidate = ms; + ptypes = ms.Parameters.Types; + } else { + if (type_arguments != null) + return int.MaxValue - 15000; + + ptypes = cpd.Types; + } + + // + // 2. Each argument has to be implicitly convertible to method parameter + // + Parameter.Modifier p_mod = 0; + TypeSpec pt = null; + + for (int i = 0; i < arg_count; i++) { + Argument a = arguments[i]; + if (a == null) { + if (!pd.FixedParameters[i].HasDefaultValue) { + arguments = orig_args; + return arg_count * 2 + 2; + } + + // + // Get the default value expression, we can use the same expression + // if the type matches + // + Expression e = pd.FixedParameters[i].DefaultValue; + if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) { + // + // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null + // + if (e == EmptyExpression.MissingValue && ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Object || ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + e = new MemberAccess (new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc); + } else { + e = new DefaultValueExpression (new TypeExpression (ptypes [i], loc), loc); + } + + e = e.Resolve (ec); + } + + arguments[i] = new Argument (e, Argument.AType.Default); + continue; + } + + if (p_mod != Parameter.Modifier.PARAMS) { + p_mod = (pd.FixedParameters[i].ModFlags & ~Parameter.Modifier.PARAMS) | (cpd.FixedParameters[i].ModFlags & Parameter.Modifier.PARAMS); + pt = ptypes [i]; + } else if (!params_expanded_form) { + params_expanded_form = true; + pt = ((ElementTypeSpec) pt).Element; + i -= 2; + continue; + } + + score = 1; + if (!params_expanded_form) { + if (a.ArgType == Argument.AType.ExtensionType) { + // + // Indentity, implicit reference or boxing conversion must exist for the extension parameter + // + var at = a.Type; + if (at == pt || TypeSpecComparer.IsEqual (at, pt) || + Convert.ImplicitReferenceConversionExists (at, pt) || + Convert.ImplicitBoxingConversion (null, at, pt) != null) { + score = 0; + continue; + } + } else { + score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt); + + if (score < 0) + dynamicArgument = true; + } + } + + // + // It can be applicable in expanded form (when not doing exact match like for delegates) + // + if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) { + if (!params_expanded_form) + pt = ((ElementTypeSpec) pt).Element; + + if (score > 0) + score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt); + + if (score == 0) { + params_expanded_form = true; + } else if (score < 0) { + params_expanded_form = true; + dynamicArgument = true; + } + } + + if (score > 0) { + if (params_expanded_form) + ++score; + return (arg_count - i) * 2 + score; + } + } + + // + // When params parameter has no argument it will be provided later if the method is the best candidate + // + if (arg_count + 1 == pd.Count && (cpd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0) + params_expanded_form = true; + + // + // Restore original arguments for dynamic binder to keep the intention of original source code + // + if (dynamicArgument) + arguments = orig_args; + + return 0; + } + + // + // Tests argument compatibility with the parameter + // The possible return values are + // 0 - success + // 1 - modifier mismatch + // 2 - type mismatch + // -1 - dynamic binding required + // + int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter) + { + // + // Types have to be identical when ref or out modifer + // is used and argument is not of dynamic type + // + if ((argument.Modifier | param_mod) != 0) { + if (argument.Type != parameter) { + // + // Do full equality check after quick path + // + if (!TypeSpecComparer.IsEqual (argument.Type, parameter)) { + // + // Using dynamic for ref/out parameter can still succeed at runtime + // + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + return 2; + } + } + + if (argument.Modifier != param_mod) { + // + // Using dynamic for ref/out parameter can still succeed at runtime + // + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + return 1; + } + + } else { + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + // + // Deploy custom error reporting for lambda methods. When probing lambda methods + // keep all errors reported in separate set and once we are done and no best + // candidate was found, this set is used to report more details about what was wrong + // with lambda body + // + if (argument.Expr.Type == InternalType.AnonymousMethod) { + if (lambda_conv_msgs == null) { + lambda_conv_msgs = new SessionReportPrinter (); + prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); + } + } + + // + // Use implicit conversion in all modes to return same candidates when the expression + // is used as argument or delegate conversion + // + if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { + if (lambda_conv_msgs != null) { + lambda_conv_msgs.EndSession (); + } + + return 2; + } + } + + return 0; + } + + static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q) + { + if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q)) + return q; + if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q)) + return p; + + var ac_p = p as ArrayContainer; + if (ac_p != null) { + var ac_q = ((ArrayContainer) q); + TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element); + if (specific == ac_p.Element) + return p; + if (specific == ac_q.Element) + return q; + } else if (TypeManager.IsGenericType (p)) { + var pargs = TypeManager.GetTypeArguments (p); + var qargs = TypeManager.GetTypeArguments (q); + + bool p_specific_at_least_once = false; + bool q_specific_at_least_once = false; + + for (int i = 0; i < pargs.Length; i++) { + TypeSpec specific = MoreSpecific (pargs[i], qargs[i]); + if (specific == pargs[i]) + p_specific_at_least_once = true; + if (specific == qargs[i]) + q_specific_at_least_once = true; + } + + if (p_specific_at_least_once && !q_specific_at_least_once) + return p; + if (!p_specific_at_least_once && q_specific_at_least_once) + return q; + } + + return null; + } + + // + // Find the best method from candidate list + // + public T ResolveMember (ResolveContext rc, ref Arguments args) where T : MemberSpec, IParametersMember + { + List ambiguous_candidates = null; + + MemberSpec best_candidate; + Arguments best_candidate_args = null; + bool best_candidate_params = false; + bool best_candidate_dynamic = false; + int best_candidate_rate; + IParametersMember best_parameter_member = null; + + int args_count = args != null ? args.Count : 0; + + Arguments candidate_args = args; + bool error_mode = false; + MemberSpec invocable_member = null; + + // Be careful, cannot return until error reporter is restored + while (true) { + best_candidate = null; + best_candidate_rate = int.MaxValue; + + var type_members = members; + try { + + do { + for (int i = 0; i < type_members.Count; ++i) { + var member = type_members[i]; + + // + // Methods in a base class are not candidates if any method in a derived + // class is applicable + // + if ((member.Modifiers & Modifiers.OVERRIDE) != 0) + continue; + + if (!error_mode) { + if (!member.IsAccessible (rc)) + continue; + + if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) + continue; + } + + IParametersMember pm = member as IParametersMember; + if (pm == null) { + // + // Will use it later to report ambiguity between best method and invocable member + // + if (Invocation.IsMemberInvocable (member)) + invocable_member = member; + + continue; + } + + // + // Overload resolution is looking for base member but using parameter names + // and default values from the closest member. That means to do expensive lookup + // for the closest override for virtual or abstract members + // + if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { + var override_params = base_provider.GetOverrideMemberParameters (member); + if (override_params != null) + pm = override_params; + } + + // + // Check if the member candidate is applicable + // + bool params_expanded_form = false; + bool dynamic_argument = false; + TypeSpec rt = pm.MemberType; + int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt); + + // + // How does it score compare to others + // + if (candidate_rate < best_candidate_rate) { + best_candidate_rate = candidate_rate; + best_candidate = member; + best_candidate_args = candidate_args; + best_candidate_params = params_expanded_form; + best_candidate_dynamic = dynamic_argument; + best_parameter_member = pm; + best_candidate_return_type = rt; + } else if (candidate_rate == 0) { + // + // The member look is done per type for most operations but sometimes + // it's not possible like for binary operators overload because they + // are unioned between 2 sides + // + if ((restrictions & Restrictions.BaseMembersIncluded) != 0) { + if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true)) + continue; + } + + bool is_better; + if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + // + // We pack all interface members into top level type which makes the overload resolution + // more complicated for interfaces. We compensate it by removing methods with same + // signature when building the cache hence this path should not really be hit often + // + // Example: + // interface IA { void Foo (int arg); } + // interface IB : IA { void Foo (params int[] args); } + // + // IB::Foo is the best overload when calling IB.Foo (1) + // + is_better = true; + if (ambiguous_candidates != null) { + foreach (var amb_cand in ambiguous_candidates) { + if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + continue; + } + + is_better = false; + break; + } + + if (is_better) + ambiguous_candidates = null; + } + } else { + // Is the new candidate better + is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params); + } + + if (is_better) { + best_candidate = member; + best_candidate_args = candidate_args; + best_candidate_params = params_expanded_form; + best_candidate_dynamic = dynamic_argument; + best_parameter_member = pm; + best_candidate_return_type = rt; + } else { + // It's not better but any other found later could be but we are not sure yet + if (ambiguous_candidates == null) + ambiguous_candidates = new List (); + + ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); + } + } + + // Restore expanded arguments + if (candidate_args != args) + candidate_args = args; + } + } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null); + } finally { + if (prev_recorder != null) + rc.Report.SetPrinter (prev_recorder); + } + + // + // We've found exact match + // + if (best_candidate_rate == 0) + break; + + // + // Try extension methods lookup when no ordinary method match was found and provider enables it + // + if (!error_mode) { + var emg = base_provider.LookupExtensionMethod (rc); + if (emg != null) { + emg = emg.OverloadResolve (rc, ref args, null, restrictions); + if (emg != null) { + best_candidate_extension_group = emg; + return (T) (MemberSpec) emg.BestCandidate; + } + } + } + + // Don't run expensive error reporting mode for probing + if (IsProbingOnly) + return null; + + if (error_mode) + break; + + lambda_conv_msgs = null; + error_mode = true; + } + + // + // No best member match found, report an error + // + if (best_candidate_rate != 0 || error_mode) { + ReportOverloadError (rc, best_candidate, best_parameter_member, best_candidate_args, best_candidate_params); + return null; + } + + if (best_candidate_dynamic) { + if (args[0].ArgType == Argument.AType.ExtensionType) { + rc.Report.Error (1973, loc, + "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' cannot be dynamically dispatched. Consider calling the method without the extension method syntax", + args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError ()); + } + + BestCandidateIsDynamic = true; + return null; + } + + // + // These flags indicates we are running delegate probing conversion. No need to + // do more expensive checks + // + if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly)) + return (T) best_candidate; + + if (ambiguous_candidates != null) { + // + // Now check that there are no ambiguities i.e the selected method + // should be better than all the others + // + for (int ix = 0; ix < ambiguous_candidates.Count; ix++) { + var candidate = ambiguous_candidates [ix]; + + if (!BetterFunction (rc, best_candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) { + var ambiguous = candidate.Member; + if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.SymbolRelatedToPreviousError (ambiguous); + rc.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", + best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ()); + } + + return (T) best_candidate; + } + } + } + + if (invocable_member != null) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.SymbolRelatedToPreviousError (invocable_member); + rc.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and invocable non-method `{1}'. Using method group", + best_candidate.GetSignatureForError (), invocable_member.GetSignatureForError ()); + } + + // + // And now check if the arguments are all + // compatible, perform conversions if + // necessary etc. and return if everything is + // all right + // + if (!VerifyArguments (rc, ref best_candidate_args, best_candidate, best_parameter_member, best_candidate_params)) + return null; + + if (best_candidate == null) + return null; + + // + // Check ObsoleteAttribute on the best method + // + ObsoleteAttribute oa = best_candidate.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) + AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report); + + var dep = best_candidate.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } + + best_candidate.MemberDefinition.SetIsUsed (); + + args = best_candidate_args; + return (T) best_candidate; + } + + public MethodSpec ResolveOperator (ResolveContext rc, ref Arguments args) + { + return ResolveMember (rc, ref args); + } + + void ReportArgumentMismatch (ResolveContext ec, int idx, MemberSpec method, + Argument a, AParametersCollection expected_par, TypeSpec paramType) + { + if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx)) + return; + + if (a is CollectionElementInitializer.ElementInitializerArgument) { + ec.Report.SymbolRelatedToPreviousError (method); + if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", + TypeManager.CSharpSignature (method)); + return; + } + ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments", + TypeManager.CSharpSignature (method)); + } else if (IsDelegateInvoke) { + ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", + DelegateType.GetSignatureForError ()); + } else { + ec.Report.SymbolRelatedToPreviousError (method); + ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", + method.GetSignatureForError ()); + } + + Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags; + + string index = (idx + 1).ToString (); + if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^ + (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) { + if ((mod & Parameter.Modifier.ISBYREF) == 0) + ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier", + index, Parameter.GetModifierSignature (a.Modifier)); + else + ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier", + index, Parameter.GetModifierSignature (mod)); + } else if (a.Expr != ErrorExpression.Instance) { + string p1 = a.GetSignatureForError (); + string p2 = TypeManager.CSharpName (paramType); + + if (p1 == p2) { + p1 = a.Type.GetSignatureForErrorIncludingAssemblyName (); + p2 = paramType.GetSignatureForErrorIncludingAssemblyName (); + } + + ec.Report.Error (1503, loc, + "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2); + } + } + + // + // We have failed to find exact match so we return error info about the closest match + // + void ReportOverloadError (ResolveContext rc, MemberSpec best_candidate, IParametersMember pm, Arguments args, bool params_expanded) + { + int ta_count = type_arguments == null ? 0 : type_arguments.Count; + int arg_count = args == null ? 0 : args.Count; + + if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) { + var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc); + mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, ta_count, loc); + return; + } + + if (lambda_conv_msgs != null) { + if (lambda_conv_msgs.Merge (rc.Report.Printer)) + return; + } + + // + // For candidates which match on parameters count report more details about incorrect arguments + // + if (pm != null) { + int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count; + if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) { + // Reject any inaccessible member + if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc); + return; + } + + var ms = best_candidate as MethodSpec; + if (ms != null && ms.IsGeneric) { + bool constr_ok = true; + if (ms.TypeArguments != null) + constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc); + + if (ta_count == 0) { + if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate)) + return; + + if (constr_ok) { + rc.Report.Error (411, loc, + "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly", + ms.GetGenericMethodDefinition ().GetSignatureForError ()); + } + + return; + } + } + + VerifyArguments (rc, ref args, best_candidate, pm, params_expanded); + return; + } + } + + // + // We failed to find any method with correct argument count, report best candidate + // + if (custom_errors != null && custom_errors.NoArgumentMatch (rc, best_candidate)) + return; + + if (best_candidate.Kind == MemberKind.Constructor) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + Error_ConstructorMismatch (rc, best_candidate.DeclaringType, arg_count, loc); + } else if (IsDelegateInvoke) { + rc.Report.SymbolRelatedToPreviousError (DelegateType); + rc.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + DelegateType.GetSignatureForError (), arg_count.ToString ()); + } else { + string name = best_candidate.Kind == MemberKind.Indexer ? "this" : best_candidate.Name; + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", + name, arg_count.ToString ()); + } + } + + bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, IParametersMember pm, bool chose_params_expanded) + { + var pd = pm.Parameters; + TypeSpec[] ptypes = ((IParametersMember) member).Parameters.Types; + + Parameter.Modifier p_mod = 0; + TypeSpec pt = null; + int a_idx = 0, a_pos = 0; + Argument a = null; + ArrayInitializer params_initializers = null; + bool has_unsafe_arg = pm.MemberType.IsPointer; + int arg_count = args == null ? 0 : args.Count; + + for (; a_idx < arg_count; a_idx++, ++a_pos) { + a = args[a_idx]; + if (p_mod != Parameter.Modifier.PARAMS) { + p_mod = pd.FixedParameters[a_idx].ModFlags; + pt = ptypes[a_idx]; + has_unsafe_arg |= pt.IsPointer; + + if (p_mod == Parameter.Modifier.PARAMS) { + if (chose_params_expanded) { + params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location); + pt = TypeManager.GetElementType (pt); + } + } + } + + // + // Types have to be identical when ref or out modifer is used + // + if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) { + if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier) + break; + + if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) + continue; + + break; + } + + NamedArgument na = a as NamedArgument; + if (na != null) { + int name_index = pd.GetParameterIndexByName (na.Name); + if (name_index < 0 || name_index >= pd.Count) { + if (IsDelegateInvoke) { + ec.Report.SymbolRelatedToPreviousError (DelegateType); + ec.Report.Error (1746, na.Location, + "The delegate `{0}' does not contain a parameter named `{1}'", + DelegateType.GetSignatureForError (), na.Name); + } else { + ec.Report.SymbolRelatedToPreviousError (member); + ec.Report.Error (1739, na.Location, + "The best overloaded method match for `{0}' does not contain a parameter named `{1}'", + TypeManager.CSharpSignature (member), na.Name); + } + } else if (args[name_index] != a) { + if (IsDelegateInvoke) + ec.Report.SymbolRelatedToPreviousError (DelegateType); + else + ec.Report.SymbolRelatedToPreviousError (member); + + ec.Report.Error (1744, na.Location, + "Named argument `{0}' cannot be used for a parameter which has positional argument specified", + na.Name); + } + } + + if (a.Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr.Type, pt)) { + custom_errors.NoArgumentMatch (ec, member); + return false; + } + + Expression conv = null; + if (a.ArgType == Argument.AType.ExtensionType) { + if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) { + conv = a.Expr; + } else { + conv = Convert.ImplicitReferenceConversion (a.Expr, pt, false); + if (conv == null) + conv = Convert.ImplicitBoxingConversion (a.Expr, a.Expr.Type, pt); + } + } else { + conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc); + } + + if (conv == null) + break; + + // + // Convert params arguments to an array initializer + // + if (params_initializers != null) { + // we choose to use 'a.Expr' rather than 'conv' so that + // we don't hide the kind of expression we have (esp. CompoundAssign.Helper) + params_initializers.Add (a.Expr); + args.RemoveAt (a_idx--); + --arg_count; + continue; + } + + // Update the argument with the implicit conversion + a.Expr = conv; + } + + if (a_idx != arg_count) { + ReportArgumentMismatch (ec, a_pos, member, a, pd, pt); + return false; + } + + // + // Fill not provided arguments required by params modifier + // + if (params_initializers == null && pd.HasParams && arg_count + 1 == pd.Count) { + if (args == null) + args = new Arguments (1); + + pt = ptypes[pd.Count - 1]; + pt = TypeManager.GetElementType (pt); + has_unsafe_arg |= pt.IsPointer; + params_initializers = new ArrayInitializer (0, loc); + } + + // + // Append an array argument with all params arguments + // + if (params_initializers != null) { + args.Add (new Argument ( + new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec))); + arg_count++; + } + + if (has_unsafe_arg && !ec.IsUnsafe) { + Expression.UnsafeError (ec, loc); + } + + // + // We could infer inaccesible type arguments + // + if (type_arguments == null && member.IsGeneric) { + var ms = (MethodSpec) member; + foreach (var ta in ms.TypeArguments) { + if (!ta.IsAccessible (ec)) { + ec.Report.SymbolRelatedToPreviousError (ta); + Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + break; + } + } + } + + return true; + } + } + + public class ConstantExpr : MemberExpr + { + readonly ConstSpec constant; + + public ConstantExpr (ConstSpec constant, Location loc) + { + this.constant = constant; + this.loc = loc; + } + + public override string Name { + get { throw new NotImplementedException (); } + } + + public override bool IsInstance { + get { return !IsStatic; } + } + + public override bool IsStatic { + get { return true; } + } + + protected override TypeSpec DeclaringType { + get { return constant.DeclaringType; } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + ResolveInstanceExpression (rc, null); + DoBestMemberChecks (rc, constant); + + var c = constant.GetConstant (rc); + + // Creates reference expression to the constant value + return Constant.CreateConstant (constant.MemberType, c.GetValue (), loc); + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + } + + public override string GetSignatureForError () + { + return constant.GetSignatureForError (); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc); + } + } + + /// + /// Fully resolved expression that evaluates to a Field + /// + public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference { + protected FieldSpec spec; + VariableInfo variable_info; + + LocalTemporary temp; + bool prepared; + + protected FieldExpr (Location l) + { + loc = l; + } + + public FieldExpr (FieldSpec spec, Location loc) + { + this.spec = spec; + this.loc = loc; + + type = spec.MemberType; + } + + public FieldExpr (FieldBase fi, Location l) + : this (fi.Spec, l) + { + } + + #region Properties + + public override string Name { + get { + return spec.Name; + } + } + + public bool IsHoisted { + get { + IVariableReference hv = InstanceExpression as IVariableReference; + return hv != null && hv.IsHoisted; + } + } + + public override bool IsInstance { + get { + return !spec.IsStatic; + } + } + + public override bool IsStatic { + get { + return spec.IsStatic; + } + } + + public FieldSpec Spec { + get { + return spec; + } + } + + protected override TypeSpec DeclaringType { + get { + return spec.DeclaringType; + } + } + + public VariableInfo VariableInfo { + get { + return variable_info; + } + } + +#endregion + + public override string GetSignatureForError () + { + return TypeManager.GetFullNameSignature (spec); + } + + public bool IsMarshalByRefAccess (ResolveContext rc) + { + // Checks possible ldflda of field access expression + return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) && + rc.Module.PredefinedTypes.MarshalByRefObject.Define () && + TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false); + } + + public void SetHasAddressTaken () + { + IVariableReference vr = InstanceExpression as IVariableReference; + if (vr != null) + vr.SetHasAddressTaken (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Expression instance; + if (InstanceExpression == null) { + instance = new NullLiteral (loc); + } else { + instance = InstanceExpression.CreateExpressionTree (ec); + } + + Arguments args = Arguments.CreateForExpressionTree (ec, null, + instance, + CreateTypeOfExpression ()); + + return CreateExpressionFactoryCall (ec, "Field", args); + } + + public Expression CreateTypeOfExpression () + { + return new TypeOfField (spec, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return DoResolve (ec, null); + } + + Expression DoResolve (ResolveContext ec, Expression rhs) + { + bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct; + + if (rhs != this) { + if (ResolveInstanceExpression (ec, rhs)) { + // Resolve the field's instance expression while flow analysis is turned + // off: when accessing a field "a.b", we must check whether the field + // "a.b" is initialized, not whether the whole struct "a" is initialized. + + if (lvalue_instance) { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess; + + Expression right_side = + out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; + + InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); + } + } else { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue); + } + } + + if (InstanceExpression == null) + return null; + } + + DoBestMemberChecks (ec, spec); + } + + var fb = spec as FixedFieldSpec; + IVariableReference var = InstanceExpression as IVariableReference; + + if (lvalue_instance && var != null && var.VariableInfo != null) { + var.VariableInfo.SetFieldAssigned (ec, Name); + } + + if (fb != null) { + IFixedExpression fe = InstanceExpression as IFixedExpression; + if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { + ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + } + + if (InstanceExpression.eclass != ExprClass.Variable) { + ec.Report.SymbolRelatedToPreviousError (spec); + ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", + TypeManager.GetFullNameSignature (spec)); + } else if (var != null && var.IsHoisted) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); + } + + return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); + } + + eclass = ExprClass.Variable; + + // If the instance expression is a local variable or parameter. + if (var == null || var.VariableInfo == null) + return this; + + VariableInfo vi = var.VariableInfo; + if (!vi.IsFieldAssigned (ec, Name, loc)) + return null; + + variable_info = vi.GetSubStruct (Name); + return this; + } + + static readonly int [] codes = { + 191, // instance, write access + 192, // instance, out access + 198, // static, write access + 199, // static, out access + 1648, // member of value instance, write access + 1649, // member of value instance, out access + 1650, // member of value static, write access + 1651 // member of value static, out access + }; + + static readonly string [] msgs = { + /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)", + /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)", + /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)", + /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)" + }; + + // The return value is always null. Returning a value simplifies calling code. + Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side) + { + int i = 0; + if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess) + i += 1; + if (IsStatic) + i += 2; + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) + i += 4; + ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ()); + + return null; + } + + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + Expression e = DoResolve (ec, right_side); + + if (e == null) + return null; + + spec.MemberDefinition.SetIsAssigned (); + + if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) && + (spec.Modifiers & Modifiers.VOLATILE) != 0) { + ec.Report.Warning (420, 1, loc, + "`{0}': A volatile field references will not be treated as volatile", + spec.GetSignatureForError ()); + } + + if (spec.IsReadOnly) { + // InitOnly fields can only be assigned in constructors or initializers + if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope)) + return Report_AssignToReadonly (ec, right_side); + + if (ec.HasSet (ResolveContext.Options.ConstructorScope)) { + + // InitOnly fields cannot be assigned-to in a different constructor from their declaring type + if (ec.CurrentMemberDefinition.Parent.Definition != spec.DeclaringType.GetDefinition ()) + return Report_AssignToReadonly (ec, right_side); + // static InitOnly fields cannot be assigned-to in an instance constructor + if (IsStatic && !ec.IsStatic) + return Report_AssignToReadonly (ec, right_side); + // instance constructors can't modify InitOnly fields of other instances of the same type + if (!IsStatic && !(InstanceExpression is This)) + return Report_AssignToReadonly (ec, right_side); + } + } + + if (right_side == EmptyExpression.OutAccess && IsMarshalByRefAccess (ec)) { + ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType); + ec.Report.Warning (197, 1, loc, + "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class", + GetSignatureForError ()); + } + + eclass = ExprClass.Variable; + return this; + } + + public override int GetHashCode () + { + return spec.GetHashCode (); + } + + public bool IsFixed { + get { + // + // A variable of the form V.I is fixed when V is a fixed variable of a struct type + // + IVariableReference variable = InstanceExpression as IVariableReference; + if (variable != null) + return InstanceExpression.Type.IsStruct && variable.IsFixed; + + IFixedExpression fe = InstanceExpression as IFixedExpression; + return fe != null && fe.IsFixed; + } + } + + public override bool Equals (object obj) + { + FieldExpr fe = obj as FieldExpr; + if (fe == null) + return false; + + if (spec != fe.spec) + return false; + + if (InstanceExpression == null || fe.InstanceExpression == null) + return true; + + return InstanceExpression.Equals (fe.InstanceExpression); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + bool is_volatile = false; + + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + is_volatile = true; + + spec.MemberDefinition.SetIsUsed (); + + if (IsStatic){ + if (is_volatile) + ec.Emit (OpCodes.Volatile); + + ec.Emit (OpCodes.Ldsfld, spec); + } else { + if (!prepared) + EmitInstance (ec, false); + + // Optimization for build-in types + if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) { + ec.EmitLoadFromPtr (type); + } else { + var ff = spec as FixedFieldSpec; + if (ff != null) { + ec.Emit (OpCodes.Ldflda, spec); + ec.Emit (OpCodes.Ldflda, ff.Element); + } else { + if (is_volatile) + ec.Emit (OpCodes.Volatile); + + ec.Emit (OpCodes.Ldfld, spec); + } + } + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + var await_expr = source as Await; + if (await_expr != null) { + // + // Await is not ordinary expression (it contains jump), hence the usual flow cannot be used + // to emit instance load before expression + // + await_expr.EmitAssign (ec, this); + } else { + prepared = prepare_for_load && !(source is DynamicExpressionStatement); + if (IsInstance) + EmitInstance (ec, prepared); + + source.Emit (ec); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + ec.Emit (OpCodes.Volatile); + + spec.MemberDefinition.SetIsAssigned (); + + if (IsStatic) + ec.Emit (OpCodes.Stsfld, spec); + else + ec.Emit (OpCodes.Stfld, spec); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + temp = null; + } + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitSideEffect (EmitContext ec) + { + bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0; + + if (is_volatile) // || is_marshal_by_ref ()) + base.EmitSideEffect (ec); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + if ((mode & AddressOp.Store) != 0) + spec.MemberDefinition.SetIsAssigned (); + if ((mode & AddressOp.Load) != 0) + spec.MemberDefinition.SetIsUsed (); + + // + // Handle initonly fields specially: make a copy and then + // get the address of the copy. + // + bool need_copy; + if (spec.IsReadOnly){ + need_copy = true; + if (ec.HasSet (EmitContext.Options.ConstructorScope) && spec.DeclaringType == ec.CurrentType) { + if (IsStatic){ + if (ec.IsStatic) + need_copy = false; + } else + need_copy = false; + } + } else + need_copy = false; + + if (need_copy){ + LocalBuilder local; + Emit (ec); + local = ec.DeclareLocal (type, false); + ec.Emit (OpCodes.Stloc, local); + ec.Emit (OpCodes.Ldloca, local); + return; + } + + + if (IsStatic){ + ec.Emit (OpCodes.Ldsflda, spec); + } else { + if (!prepared) + EmitInstance (ec, false); + ec.Emit (OpCodes.Ldflda, spec); + } + } + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { + return MakeExpression (ctx); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Field ( + IsStatic ? null : InstanceExpression.MakeExpression (ctx), + spec.GetMetaInfo ()); +#endif + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc); + } + } + + + /// + /// Expression that evaluates to a Property. The Assign class + /// might set the `Value' expression if we are in an assignment. + /// + /// This is not an LValue because we need to re-write the expression, we + /// can not take data from the stack and store it. + /// + class PropertyExpr : PropertyOrIndexerExpr + { + public PropertyExpr (PropertySpec spec, Location l) + : base (l) + { + best_candidate = spec; + type = spec.MemberType; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return best_candidate.DeclaringType; + } + } + + public override string Name { + get { + return best_candidate.Name; + } + } + + public override bool IsInstance { + get { + return !IsStatic; + } + } + + public override bool IsStatic { + get { + return best_candidate.IsStatic; + } + } + + public PropertySpec PropertyInfo { + get { + return best_candidate; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + if (IsSingleDimensionalArrayLength ()) { + args = new Arguments (1); + args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "ArrayLength", args); + } + + args = new Arguments (2); + if (InstanceExpression == null) + args.Add (new Argument (new NullLiteral (loc))); + else + args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOfMethod (Getter, loc))); + return CreateExpressionFactoryCall (ec, "Property", args); + } + + public Expression CreateSetterTypeOfExpression () + { + return new TypeOfMethod (Setter, loc); + } + + public override string GetSignatureForError () + { + return best_candidate.GetSignatureForError (); + } + + public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ()); +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ()); +#endif + } + + void Error_PropertyNotValid (ResolveContext ec) + { + ec.Report.SymbolRelatedToPreviousError (best_candidate); + ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language", + GetSignatureForError ()); + } + + bool IsSingleDimensionalArrayLength () + { + if (best_candidate.DeclaringType.BuiltinType != BuiltinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length") + return false; + + ArrayContainer ac = InstanceExpression.Type as ArrayContainer; + return ac != null && ac.Rank == 1; + } + + public override void Emit (EmitContext ec, bool leave_copy) + { + // + // Special case: length of single dimension array property is turned into ldlen + // + if (IsSingleDimensionalArrayLength ()) { + if (!prepared) + EmitInstance (ec, false); + ec.Emit (OpCodes.Ldlen); + ec.Emit (OpCodes.Conv_I4); + return; + } + + Invocation.EmitCall (ec, InstanceExpression, Getter, null, loc, prepared, false); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } + + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + Arguments args; + + if (prepare_for_load && !(source is DynamicExpressionStatement)) { + args = new Arguments (0); + prepared = true; + source.Emit (ec); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } else { + args = new Arguments (1); + + if (leave_copy) { + source.Emit (ec); + temp = new LocalTemporary (this.Type); + temp.Store (ec); + args.Add (new Argument (temp)); + } else { + args.Add (new Argument (source)); + } + } + + Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + protected override Expression OverloadResolve (ResolveContext rc, Expression right_side) + { + eclass = ExprClass.PropertyAccess; + + if (best_candidate.IsNotCSharpCompatible) { + Error_PropertyNotValid (rc); + } + + ResolveInstanceExpression (rc, right_side); + + if ((best_candidate.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0 && best_candidate.DeclaringType != InstanceExpression.Type) { + var filter = new MemberFilter (best_candidate.Name, 0, MemberKind.Property, null, null); + var p = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as PropertySpec; + if (p != null) { + type = p.MemberType; + } + } + + DoBestMemberChecks (rc, best_candidate); + return this; + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc); + } + } + + abstract class PropertyOrIndexerExpr : MemberExpr, IDynamicAssign where T : PropertySpec + { + // getter and setter can be different for base calls + MethodSpec getter, setter; + protected T best_candidate; + + protected LocalTemporary temp; + protected bool prepared; + + protected PropertyOrIndexerExpr (Location l) + { + loc = l; + } + + #region Properties + + public MethodSpec Getter { + get { + return getter; + } + set { + getter = value; + } + } + + public MethodSpec Setter { + get { + return setter; + } + set { + setter = value; + } + } + + #endregion + + protected override Expression DoResolve (ResolveContext ec) + { + if (eclass == ExprClass.Unresolved) { + var expr = OverloadResolve (ec, null); + if (expr == null) + return null; + + if (expr != this) + return expr.Resolve (ec); + } + + if (!ResolveGetter (ec)) + return null; + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (right_side == EmptyExpression.OutAccess) { + // TODO: best_candidate can be null at this point + INamedBlockVariable variable = null; + if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) { + ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", + best_candidate.Name); + } else { + right_side.DoResolveLValue (ec, this); + } + return null; + } + + // if the property/indexer returns a value type, and we try to set a field in it + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) { + Error_CannotModifyIntermediateExpressionValue (ec); + } + + if (eclass == ExprClass.Unresolved) { + var expr = OverloadResolve (ec, right_side); + if (expr == null) + return null; + + if (expr != this) + return expr.ResolveLValue (ec, right_side); + } + + if (!ResolveSetter (ec)) + return null; + + return this; + } + + // + // Implements the IAssignMethod interface for assignments + // + public abstract void Emit (EmitContext ec, bool leave_copy); + public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); + + protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side); + + bool ResolveGetter (ResolveContext rc) + { + if (!best_candidate.HasGet) { + if (InstanceExpression != EmptyExpression.Null) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor", + best_candidate.GetSignatureForError ()); + return false; + } + } else if (!best_candidate.Get.IsAccessible (rc)) { + if (best_candidate.HasDifferentAccessibility) { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Get); + rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible", + TypeManager.CSharpSignature (best_candidate)); + } else { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Get); + ErrorIsInaccesible (rc, best_candidate.Get.GetSignatureForError (), loc); + } + } + + if (best_candidate.HasDifferentAccessibility) { + CheckProtectedMemberAccess (rc, best_candidate.Get); + } + + getter = CandidateToBaseOverride (rc, best_candidate.Get); + return true; + } + + bool ResolveSetter (ResolveContext rc) + { + if (!best_candidate.HasSet) { + rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)", + GetSignatureForError ()); + return false; + } + + if (!best_candidate.Set.IsAccessible (rc)) { + if (best_candidate.HasDifferentAccessibility) { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Set); + rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible", + GetSignatureForError ()); + } else { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Set); + ErrorIsInaccesible (rc, best_candidate.Set.GetSignatureForError (), loc); + } + } + + if (best_candidate.HasDifferentAccessibility) + CheckProtectedMemberAccess (rc, best_candidate.Set); + + setter = CandidateToBaseOverride (rc, best_candidate.Set); + return true; + } + } + + /// + /// Fully resolved expression that evaluates to an Event + /// + public class EventExpr : MemberExpr, IAssignMethod + { + readonly EventSpec spec; + MethodSpec op; + + public EventExpr (EventSpec spec, Location loc) + { + this.spec = spec; + this.loc = loc; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return spec.DeclaringType; + } + } + + public override string Name { + get { + return spec.Name; + } + } + + public override bool IsInstance { + get { + return !spec.IsStatic; + } + } + + public override bool IsStatic { + get { + return spec.IsStatic; + } + } + + public MethodSpec Operator { + get { + return op; + } + } + + #endregion + + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + // + // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr + // + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { + if (spec.BackingField != null && + (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition))) { + + spec.MemberDefinition.SetIsUsed (); + + if (!ec.IsObsolete) { + ObsoleteAttribute oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report); + } + + if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) + Error_AssignmentEventOnly (ec); + + FieldExpr ml = new FieldExpr (spec.BackingField, loc); + + InstanceExpression = null; + + return ml.ResolveMemberAccess (ec, left, original); + } + } + + return base.ResolveMemberAccess (ec, left, original); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (right_side == EmptyExpression.EventAddition) { + op = spec.AccessorAdd; + } else if (right_side == EmptyExpression.EventSubtraction) { + op = spec.AccessorRemove; + } + + if (op == null) { + Error_AssignmentEventOnly (ec); + return null; + } + + op = CandidateToBaseOverride (ec, op); + return this; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.EventAccess; + type = spec.MemberType; + + ResolveInstanceExpression (ec, null); + + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { + Error_AssignmentEventOnly (ec); + } + + DoBestMemberChecks (ec, spec); + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + //Error_CannotAssign (); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + if (leave_copy || !prepare_for_load) + throw new NotImplementedException ("EventExpr::EmitAssign"); + + Arguments args = new Arguments (1); + args.Add (new Argument (source)); + Invocation.EmitCall (ec, InstanceExpression, op, args, loc); + } + + #endregion + + void Error_AssignmentEventOnly (ResolveContext ec) + { + if (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition)) { + ec.Report.Error (79, loc, + "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", + GetSignatureForError ()); + } else { + ec.Report.Error (70, loc, + "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", + GetSignatureForError (), spec.DeclaringType.GetSignatureForError ()); + } + } + + protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name) + { + name = name.Substring (0, name.LastIndexOf ('.')); + base.Error_CannotCallAbstractBase (rc, name); + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (spec); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc); + } + } + + public class TemporaryVariableReference : VariableReference + { + public class Declarator : Statement + { + TemporaryVariableReference variable; + + public Declarator (TemporaryVariableReference variable) + { + this.variable = variable; + loc = variable.loc; + } + + protected override void DoEmit (EmitContext ec) + { + variable.li.CreateBuilder (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing + } + } + + LocalVariable li; + + public TemporaryVariableReference (LocalVariable li, Location loc) + { + this.li = li; + this.type = li.Type; + this.loc = loc; + } + + public override bool IsLockedByStatement { + get { + return false; + } + set { + } + } + + public LocalVariable LocalInfo { + get { + return li; + } + } + + public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc) + { + var li = LocalVariable.CreateCompilerGenerated (type, block, loc); + return new TemporaryVariableReference (li, loc); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + + // + // Don't capture temporary variables except when using + // iterator redirection + // + if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) { + AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureLocalVariable (ec, li); + } + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return Resolve (ec); + } + + public override void Emit (EmitContext ec) + { + li.CreateBuilder (ec); + + Emit (ec, false); + } + + public void EmitAssign (EmitContext ec, Expression source) + { + li.CreateBuilder (ec); + + EmitAssign (ec, source, false, false); + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return li.HoistedVariant; + } + + public override bool IsFixed { + get { return true; } + } + + public override bool IsRef { + get { return false; } + } + + public override string Name { + get { throw new NotImplementedException (); } + } + + public override void SetHasAddressTaken () + { + throw new NotImplementedException (); + } + + protected override ILocalVariable Variable { + get { return li; } + } + + public override VariableInfo VariableInfo { + get { throw new NotImplementedException (); } + } + } + + /// + /// Handles `var' contextual keyword; var becomes a keyword only + /// if no type called var exists in a variable scope + /// + class VarExpr : SimpleName + { + public VarExpr (Location loc) + : base ("var", loc) + { + } + + public bool InferType (ResolveContext ec, Expression right_side) + { + if (type != null) + throw new InternalErrorException ("An implicitly typed local variable could not be redefined"); + + type = right_side.Type; + if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) { + ec.Report.Error (815, loc, + "An implicitly typed local variable declaration cannot be initialized with `{0}'", + type.GetSignatureForError ()); + return false; + } + + eclass = ExprClass.Variable; + return true; + } + + protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec) + { + if (ec.Module.Compiler.Settings.Version < LanguageVersion.V_3) + base.Error_TypeOrNamespaceNotFound (ec); + else + ec.Module.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration"); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs new file mode 100644 index 0000000000..ec23b5267a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs @@ -0,0 +1,322 @@ +// +// enum.cs: Enum handling. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2003 Novell, Inc (http://www.novell.com) +// + +using System; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; +using System.Reflection; +#endif + +namespace Mono.CSharp { + + public class EnumMember : Const + { + class EnumTypeExpr : TypeExpr + { + public override TypeSpec ResolveAsType (IMemberContext ec) + { + type = ec.CurrentType; + eclass = ExprClass.Type; + return type; + } + } + + public EnumMember (Enum parent, MemberName name, Attributes attrs) + : base (parent, new EnumTypeExpr (), Modifiers.PUBLIC, name, attrs) + { + } + + static bool IsValidEnumType (TypeSpec t) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + return true; + default: + return t.IsEnum; + } + } + + public override Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + if (expr is EnumConstant) + expr = ((EnumConstant) expr).Child; + + var underlying = ((Enum) Parent).UnderlyingType; + if (expr != null) { + expr = expr.ImplicitConversionRequired (rc, underlying, Location); + if (expr != null && !IsValidEnumType (expr.Type)) { + Enum.Error_1008 (Location, Report); + expr = null; + } + } + + if (expr == null) + expr = New.Constantify (underlying, Location); + + return new EnumConstant (expr, MemberType); + } + + public override bool Define () + { + if (!ResolveMemberType ()) + return false; + + const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; + FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr); + spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer); + + Parent.MemberCache.AddMember (spec); + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + } + + /// + /// Enumeration container + /// + public class Enum : TypeContainer + { + // + // Implicit enum member initializer, used when no constant value is provided + // + sealed class ImplicitInitializer : Expression + { + readonly EnumMember prev; + readonly EnumMember current; + + public ImplicitInitializer (EnumMember current, EnumMember prev) + { + this.current = current; + this.prev = prev; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + // We are the first member + if (prev == null) { + return New.Constantify (current.Parent.Definition, Location); + } + + var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant; + try { + return c.Increment (); + } catch (OverflowException) { + rc.Report.Error (543, current.Location, + "The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'", + current.GetSignatureForError (), ((Enum) current.Parent).UnderlyingType.GetSignatureForError ()); + + return New.Constantify (current.Parent.Definition, current.Location); + } + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); + } + } + + public static readonly string UnderlyingValueField = "value__"; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + readonly TypeExpr underlying_type_expr; + + public Enum (NamespaceContainer ns, DeclSpace parent, TypeExpression type, + Modifiers mod_flags, MemberName name, Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Enum) + { + underlying_type_expr = type; + var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE; + ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report); + spec = new EnumSpec (null, this, null, null, ModFlags); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Enum; + } + } + + public TypeExpr BaseTypeExpression { + get { + return underlying_type_expr; + } + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | + TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr; + } + } + + public TypeSpec UnderlyingType { + get { + return ((EnumSpec) spec).UnderlyingType; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public void AddEnumMember (EnumMember em) + { + if (em.Name == UnderlyingValueField) { + Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'", + UnderlyingValueField); + return; + } + + AddConstant (em); + } + + public static void Error_1008 (Location loc, Report Report) + { + Report.Error (1008, loc, + "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); + } + + protected override bool DefineNestedTypes () + { + ((EnumSpec) spec).UnderlyingType = underlying_type_expr == null ? Compiler.BuiltinTypes.Int : underlying_type_expr.Type; + + TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (), + FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); + + return true; + } + + protected override bool DoDefineMembers () + { + if (constants != null) { + for (int i = 0; i < constants.Count; ++i) { + EnumMember em = (EnumMember) constants [i]; + if (em.Initializer == null) { + em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) constants[i - 1]); + } + + em.Define (); + } + } + + return true; + } + + public override bool IsUnmanagedType () + { + return true; + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_type = Compiler.BuiltinTypes.Enum; + base_class = null; + return null; + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + switch (UnderlyingType.BuiltinType) { + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.UShort: + Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", + GetSignatureForError (), TypeManager.CSharpName (UnderlyingType)); + break; + } + + return true; + } + } + + class EnumSpec : TypeSpec + { + TypeSpec underlying; + + public EnumSpec (TypeSpec declaringType, ITypeDefinition definition, TypeSpec underlyingType, MetaType info, Modifiers modifiers) + : base (MemberKind.Enum, declaringType, definition, info, modifiers | Modifiers.SEALED) + { + this.underlying = underlyingType; + } + + public TypeSpec UnderlyingType { + get { + return underlying; + } + set { + if (underlying != null) + throw new InternalErrorException ("UnderlyingType reset"); + + underlying = value; + } + } + + public static TypeSpec GetUnderlyingType (TypeSpec t) + { + return ((EnumSpec) t.GetDefinition ()).UnderlyingType; + } + + public static bool IsValidUnderlyingType (TypeSpec type) + { + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.ULong: + return true; + } + + return false; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs new file mode 100644 index 0000000000..03097dfd84 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs @@ -0,0 +1,1128 @@ +// +// eval.cs: Evaluation and Hosting API for the C# compiler +// +// Authors: +// Miguel de Icaza (miguel@gnome.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2011 Novell, Inc +// + +using System; +using System.Threading; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using System.IO; +using System.Text; +using System.Linq; + +namespace Mono.CSharp +{ + + /// + /// Evaluator: provides an API to evaluate C# statements and + /// expressions dynamically. + /// + /// + /// This class exposes static methods to evaluate expressions in the + /// current program. + /// + /// To initialize the evaluator with a number of compiler + /// options call the Init(string[]args) method with a set of + /// command line options that the compiler recognizes. + /// + /// To interrupt execution of a statement, you can invoke the + /// Evaluator.Interrupt method. + /// + public class Evaluator { + + enum ParseMode { + // Parse silently, do not output any error messages + Silent, + + // Report errors during parse + ReportErrors, + + // Auto-complete, means that the tokenizer will start producing + // GETCOMPLETIONS tokens when it reaches a certain point. + GetCompletions + } + + static object evaluator_lock = new object (); + static volatile bool invoking; + + static int count; + static Thread invoke_thread; + + readonly Dictionary> fields; + + Type base_class; + bool inited; + int startup_files; + + readonly CompilerContext ctx; + readonly ModuleContainer module; + readonly ReflectionImporter importer; + readonly CompilationSourceFile source_file; + + public Evaluator (CompilerSettings settings, Report report) + { + ctx = new CompilerContext (settings, report); + + module = new ModuleContainer (ctx); + module.Evaluator = this; + + source_file = new CompilationSourceFile ("{interactive}", "", 1); + source_file.NamespaceContainer = new NamespaceContainer (null, module, null, source_file); + + startup_files = ctx.SourceFiles.Count; + ctx.SourceFiles.Add (source_file); + + // FIXME: Importer needs this assembly for internalsvisibleto + module.SetDeclaringAssembly (new AssemblyDefinitionDynamic (module, "evaluator")); + importer = new ReflectionImporter (module, ctx.BuiltinTypes); + + InteractiveBaseClass = typeof (InteractiveBase); + fields = new Dictionary> (); + } + + void Init () + { + var loader = new DynamicLoader (importer, ctx); + + CompilerCallableEntryPoint.Reset (); + RootContext.ToplevelTypes = module; + + //var startup_files = new List (); + //foreach (CompilationUnit file in Location.SourceFiles) + // startup_files.Add (file.Path); + + loader.LoadReferences (module); + ctx.BuiltinTypes.CheckDefinitions (module); + module.InitializePredefinedTypes (); + + inited = true; + } + + void ParseStartupFiles () + { + Driver d = new Driver (ctx); + + Location.Initialize (ctx.SourceFiles); + + for (int i = 0; i < startup_files; ++i) { + var sf = ctx.Settings.SourceFiles [i]; + d.Parse (sf, module); + } + } + + void Reset () + { + CompilerCallableEntryPoint.PartialReset (); + + Location.Reset (); + Location.Initialize (ctx.SourceFiles); + } + + /// + /// If true, turns type expressions into valid expressions + /// and calls the describe method on it + /// + public bool DescribeTypeExpressions; + + /// + /// The base class for the classes that host the user generated code + /// + /// + /// + /// This is the base class that will host the code + /// executed by the Evaluator. By default + /// this is the Mono.CSharp.InteractiveBase class + /// which is useful for interactive use. + /// + /// By changing this property you can control the + /// base class and the static members that are + /// available to your evaluated code. + /// + public Type InteractiveBaseClass { + get { + return base_class; + } + set { + base_class = value; + + if (value != null && typeof (InteractiveBase).IsAssignableFrom (value)) + InteractiveBase.Evaluator = this; + } + } + + /// + /// Interrupts the evaluation of an expression executing in Evaluate. + /// + /// + /// Use this method to interrupt long-running invocations. + /// + public void Interrupt () + { + if (!inited || !invoking) + return; + + if (invoke_thread != null) + invoke_thread.Abort (); + } + + /// + /// Compiles the input string and returns a delegate that represents the compiled code. + /// + /// + /// + /// Compiles the input string as a C# expression or + /// statement, unlike the Evaluate method, the + /// resulting delegate can be invoked multiple times + /// without incurring in the compilation overhead. + /// + /// If the return value of this function is null, + /// this indicates that the parsing was complete. + /// If the return value is a string it indicates + /// that the input string was partial and that the + /// invoking code should provide more code before + /// the code can be successfully compiled. + /// + /// If you know that you will always get full expressions or + /// statements and do not care about partial input, you can use + /// the other Compile overload. + /// + /// On success, in addition to returning null, the + /// compiled parameter will be set to the delegate + /// that can be invoked to execute the code. + /// + /// + public string Compile (string input, out CompiledMethod compiled) + { + if (input == null || input.Length == 0){ + compiled = null; + return null; + } + + lock (evaluator_lock){ + if (!inited) { + Init (); + ParseStartupFiles (); + } else { + ctx.Report.Printer.Reset (); + } + + bool partial_input; + CSharpParser parser = ParseString (ParseMode.Silent, input, out partial_input); + if (parser == null){ + compiled = null; + if (partial_input) + return input; + + ParseString (ParseMode.ReportErrors, input, out partial_input); + return null; + } + + Class parser_result = parser.InteractiveResult; + compiled = CompileBlock (parser_result, parser.undo, ctx.Report); + return null; + } + } + + /// + /// Compiles the input string and returns a delegate that represents the compiled code. + /// + /// + /// + /// Compiles the input string as a C# expression or + /// statement, unlike the Evaluate method, the + /// resulting delegate can be invoked multiple times + /// without incurring in the compilation overhead. + /// + /// This method can only deal with fully formed input + /// strings and does not provide a completion mechanism. + /// If you must deal with partial input (for example for + /// interactive use) use the other overload. + /// + /// On success, a delegate is returned that can be used + /// to invoke the method. + /// + /// + public CompiledMethod Compile (string input) + { + CompiledMethod compiled; + + // Ignore partial inputs + if (Compile (input, out compiled) != null){ + // Error, the input was partial. + return null; + } + + // Either null (on error) or the compiled method. + return compiled; + } + + /// + /// Evaluates and expression or statement and returns any result values. + /// + /// + /// Evaluates the input string as a C# expression or + /// statement. If the input string is an expression + /// the result will be stored in the result variable + /// and the result_set variable will be set to true. + /// + /// It is necessary to use the result/result_set + /// pair to identify when a result was set (for + /// example, execution of user-provided input can be + /// an expression, a statement or others, and + /// result_set would only be set if the input was an + /// expression. + /// + /// If the return value of this function is null, + /// this indicates that the parsing was complete. + /// If the return value is a string, it indicates + /// that the input is partial and that the user + /// should provide an updated string. + /// + public string Evaluate (string input, out object result, out bool result_set) + { + CompiledMethod compiled; + + result_set = false; + result = null; + + input = Compile (input, out compiled); + if (input != null) + return input; + + if (compiled == null) + return null; + + // + // The code execution does not need to keep the compiler lock + // + object retval = typeof (QuitValue); + + try { + invoke_thread = System.Threading.Thread.CurrentThread; + invoking = true; + compiled (ref retval); + } catch (ThreadAbortException e){ + Thread.ResetAbort (); + Console.WriteLine ("Interrupted!\n{0}", e); + } finally { + invoking = false; + } + + // + // We use a reference to a compiler type, in this case + // Driver as a flag to indicate that this was a statement + // + if (!ReferenceEquals (retval, typeof (QuitValue))) { + result_set = true; + result = retval; + } + + return null; + } + + public string [] GetCompletions (string input, out string prefix) + { + prefix = ""; + if (input == null || input.Length == 0) + return null; + + lock (evaluator_lock){ + if (!inited) + Init (); + + bool partial_input; + CSharpParser parser = ParseString (ParseMode.GetCompletions, input, out partial_input); + if (parser == null){ + if (CSharpParser.yacc_verbose_flag != 0) + Console.WriteLine ("DEBUG: No completions available"); + return null; + } + + Class parser_result = parser.InteractiveResult; + +#if NET_4_0 + var access = AssemblyBuilderAccess.RunAndCollect; +#else + var access = AssemblyBuilderAccess.Run; +#endif + var a = new AssemblyDefinitionDynamic (module, "completions"); + a.Create (AppDomain.CurrentDomain, access); + module.SetDeclaringAssembly (a); + + // Need to setup MemberCache + parser_result.CreateType (); + + var method = parser_result.Methods[0] as Method; + BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void); + + try { + method.Block.Resolve (null, bc, method); + } catch (CompletionResult cr) { + prefix = cr.BaseText; + return cr.Result; + } + } + return null; + } + + /// + /// Executes the given expression or statement. + /// + /// + /// Executes the provided statement, returns true + /// on success, false on parsing errors. Exceptions + /// might be thrown by the called code. + /// + public bool Run (string statement) + { + object result; + bool result_set; + + return Evaluate (statement, out result, out result_set) == null; + } + + /// + /// Evaluates and expression or statement and returns the result. + /// + /// + /// Evaluates the input string as a C# expression or + /// statement and returns the value. + /// + /// This method will throw an exception if there is a syntax error, + /// of if the provided input is not an expression but a statement. + /// + public object Evaluate (string input) + { + object result; + bool result_set; + + string r = Evaluate (input, out result, out result_set); + + if (r != null) + throw new ArgumentException ("Syntax error on input: partial input"); + + if (result_set == false) + throw new ArgumentException ("The expression did not set a result"); + + return result; + } + + enum InputKind { + EOF, + StatementOrExpression, + CompilationUnit, + Error + } + + // + // Deambiguates the input string to determine if we + // want to process a statement or if we want to + // process a compilation unit. + // + // This is done using a top-down predictive parser, + // since the yacc/jay parser can not deambiguage this + // without more than one lookahead token. There are very + // few ambiguities. + // + InputKind ToplevelOrStatement (SeekableStreamReader seekable) + { + Tokenizer tokenizer = new Tokenizer (seekable, source_file, ctx); + + int t = tokenizer.token (); + switch (t){ + case Token.EOF: + return InputKind.EOF; + + // These are toplevels + case Token.EXTERN: + case Token.OPEN_BRACKET: + case Token.ABSTRACT: + case Token.CLASS: + case Token.ENUM: + case Token.INTERFACE: + case Token.INTERNAL: + case Token.NAMESPACE: + case Token.PRIVATE: + case Token.PROTECTED: + case Token.PUBLIC: + case Token.SEALED: + case Token.STATIC: + case Token.STRUCT: + return InputKind.CompilationUnit; + + // Definitely expression + case Token.FIXED: + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.NEW: + case Token.OBJECT: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + return InputKind.StatementOrExpression; + + // These need deambiguation help + case Token.USING: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + + if (t == Token.IDENTIFIER) + return InputKind.CompilationUnit; + return InputKind.StatementOrExpression; + + + // Distinguish between: + // delegate opt_anonymous_method_signature block + // delegate type + case Token.DELEGATE: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + if (t == Token.OPEN_PARENS || t == Token.OPEN_BRACE) + return InputKind.StatementOrExpression; + return InputKind.CompilationUnit; + + // Distinguih between: + // unsafe block + // unsafe as modifier of a type declaration + case Token.UNSAFE: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + if (t == Token.OPEN_PARENS) + return InputKind.StatementOrExpression; + return InputKind.CompilationUnit; + + // These are errors: we list explicitly what we had + // from the grammar, ERROR and then everything else + + case Token.READONLY: + case Token.OVERRIDE: + case Token.ERROR: + return InputKind.Error; + + // This catches everything else allowed by + // expressions. We could add one-by-one use cases + // if needed. + default: + return InputKind.StatementOrExpression; + } + } + + // + // Parses the string @input and returns a CSharpParser if succeeful. + // + // if @silent is set to true then no errors are + // reported to the user. This is used to do various calls to the + // parser and check if the expression is parsable. + // + // @partial_input: if @silent is true, then it returns whether the + // parsed expression was partial, and more data is needed + // + CSharpParser ParseString (ParseMode mode, string input, out bool partial_input) + { + partial_input = false; + Reset (); + Tokenizer.LocatedToken.Initialize (); + + var enc = ctx.Settings.Encoding; + var s = new MemoryStream (enc.GetBytes (input)); + SeekableStreamReader seekable = new SeekableStreamReader (s, enc); + + InputKind kind = ToplevelOrStatement (seekable); + if (kind == InputKind.Error){ + if (mode == ParseMode.ReportErrors) + ctx.Report.Error (-25, "Detection Parsing Error"); + partial_input = false; + return null; + } + + if (kind == InputKind.EOF){ + if (mode == ParseMode.ReportErrors) + Console.Error.WriteLine ("Internal error: EOF condition should have been detected in a previous call with silent=true"); + partial_input = true; + return null; + + } + seekable.Position = 0; + + source_file.NamespaceContainer.DeclarationFound = false; + CSharpParser parser = new CSharpParser (seekable, source_file); + + if (kind == InputKind.StatementOrExpression){ + parser.Lexer.putback_char = Tokenizer.EvalStatementParserCharacter; + ctx.Settings.StatementMode = true; + } else { + parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; + ctx.Settings.StatementMode = false; + } + + if (mode == ParseMode.GetCompletions) + parser.Lexer.CompleteOnEOF = true; + + ReportPrinter old_printer = null; + if ((mode == ParseMode.Silent || mode == ParseMode.GetCompletions) && CSharpParser.yacc_verbose_flag == 0) + old_printer = ctx.Report.SetPrinter (new StreamReportPrinter (TextWriter.Null)); + + try { + parser.parse (); + } finally { + if (ctx.Report.Errors != 0){ + if (mode != ParseMode.ReportErrors && parser.UnexpectedEOF) + partial_input = true; + + if (parser.undo != null) + parser.undo.ExecuteUndo (); + + parser = null; + } + + if (old_printer != null) + ctx.Report.SetPrinter (old_printer); + } + return parser; + } + + CompiledMethod CompileBlock (Class host, Undo undo, Report Report) + { + string current_debug_name = "eval-" + count + ".dll"; + ++count; +#if STATIC + throw new NotSupportedException (); +#else + AssemblyDefinitionDynamic assembly; + AssemblyBuilderAccess access; + + if (Environment.GetEnvironmentVariable ("SAVE") != null) { + access = AssemblyBuilderAccess.RunAndSave; + assembly = new AssemblyDefinitionDynamic (module, current_debug_name, current_debug_name); + assembly.Importer = importer; + } else { +#if NET_4_0 + access = AssemblyBuilderAccess.RunAndCollect; +#else + access = AssemblyBuilderAccess.Run; +#endif + assembly = new AssemblyDefinitionDynamic (module, current_debug_name); + } + + assembly.Create (AppDomain.CurrentDomain, access); + + Method expression_method; + if (host != null) { + var base_class_imported = importer.ImportType (base_class); + var baseclass_list = new List (1) { + new TypeExpression (base_class_imported, host.Location) + }; + + host.AddBasesForPart (host, baseclass_list); + + host.CreateType (); + host.DefineType (); + host.Define (); + + expression_method = (Method) host.Methods[0]; + } else { + expression_method = null; + } + + module.CreateType (); + module.Define (); + + if (Report.Errors != 0){ + if (undo != null) + undo.ExecuteUndo (); + + return null; + } + + if (host != null){ + host.EmitType (); + } + + module.Emit (); + if (Report.Errors != 0){ + if (undo != null) + undo.ExecuteUndo (); + return null; + } + + module.CloseType (); + if (host != null) + host.CloseType (); + + if (access == AssemblyBuilderAccess.RunAndSave) + assembly.Save (); + + if (host == null) + return null; + + // + // Unlike Mono, .NET requires that the MethodInfo is fetched, it cant + // work from MethodBuilders. Retarded, I know. + // + var tt = assembly.Builder.GetType (host.TypeBuilder.Name); + var mi = tt.GetMethod (expression_method.Name); + + if (host.Fields != null) { + // + // We need to then go from FieldBuilder to FieldInfo + // or reflection gets confused (it basically gets confused, and variables override each + // other). + // + foreach (Field field in host.Fields) { + var fi = tt.GetField (field.Name); + + Tuple old; + + // If a previous value was set, nullify it, so that we do + // not leak memory + if (fields.TryGetValue (field.Name, out old)) { + if (old.Item1.MemberType.IsStruct) { + // + // TODO: Clear fields for structs + // + } else { + try { + old.Item2.SetValue (null, null); + } catch { + } + } + } + + fields[field.Name] = Tuple.Create (field.Spec, fi); + } + } + + return (CompiledMethod) System.Delegate.CreateDelegate (typeof (CompiledMethod), mi); +#endif + } + + /// + /// A sentinel value used to indicate that no value was + /// was set by the compiled function. This is used to + /// differentiate between a function not returning a + /// value and null. + /// + internal static class QuitValue { } + + internal Tuple LookupField (string name) + { + Tuple fi; + fields.TryGetValue (name, out fi); + return fi; + } + + static string Quote (string s) + { + if (s.IndexOf ('"') != -1) + s = s.Replace ("\"", "\\\""); + + return "\"" + s + "\""; + } + + public string GetUsing () + { + StringBuilder sb = new StringBuilder (); + // TODO: + //foreach (object x in ns.using_alias_list) + // sb.AppendFormat ("using {0};\n", x); + + foreach (var ue in source_file.NamespaceContainer.Usings) { + sb.AppendFormat ("using {0};", ue.ToString ()); + sb.Append (Environment.NewLine); + } + + return sb.ToString (); + } + + internal ICollection GetUsingList () + { + var res = new List (); + + foreach (var ue in source_file.NamespaceContainer.Usings) + res.Add (ue.Name); + return res; + } + + internal string [] GetVarNames () + { + lock (evaluator_lock){ + return new List (fields.Keys).ToArray (); + } + } + + public string GetVars () + { + lock (evaluator_lock){ + StringBuilder sb = new StringBuilder (); + + foreach (var de in fields){ + var fi = LookupField (de.Key); + object value; + try { + value = fi.Item2.GetValue (null); + if (value is string) + value = Quote ((string)value); + } catch { + value = ""; + } + + sb.AppendFormat ("{0} {1} = {2}", fi.Item1.MemberType.GetSignatureForError (), de.Key, value); + sb.AppendLine (); + } + + return sb.ToString (); + } + } + + /// + /// Loads the given assembly and exposes the API to the user. + /// + public void LoadAssembly (string file) + { + var loader = new DynamicLoader (importer, ctx); + var assembly = loader.LoadAssemblyFile (file); + if (assembly == null) + return; + + lock (evaluator_lock){ + importer.ImportAssembly (assembly, module.GlobalRootNamespace); + } + } + + /// + /// Exposes the API of the given assembly to the Evaluator + /// + public void ReferenceAssembly (Assembly a) + { + lock (evaluator_lock){ + importer.ImportAssembly (a, module.GlobalRootNamespace); + } + } + } + + + /// + /// A delegate that can be used to invoke the + /// compiled expression or statement. + /// + /// + /// Since the Compile methods will compile + /// statements and expressions into the same + /// delegate, you can tell if a value was returned + /// by checking whether the returned value is of type + /// NoValueSet. + /// + + public delegate void CompiledMethod (ref object retvalue); + + /// + /// The default base class for every interaction line + /// + /// + /// The expressions and statements behave as if they were + /// a static method of this class. The InteractiveBase class + /// contains a number of useful methods, but can be overwritten + /// by setting the InteractiveBaseType property in the Evaluator + /// + public class InteractiveBase { + /// + /// Determines where the standard output of methods in this class will go. + /// + public static TextWriter Output = Console.Out; + + /// + /// Determines where the standard error of methods in this class will go. + /// + public static TextWriter Error = Console.Error; + + /// + /// The primary prompt used for interactive use. + /// + public static string Prompt = "csharp> "; + + /// + /// The secondary prompt used for interactive use (used when + /// an expression is incomplete). + /// + public static string ContinuationPrompt = " > "; + + /// + /// Used to signal that the user has invoked the `quit' statement. + /// + public static bool QuitRequested; + + public static Evaluator Evaluator; + + /// + /// Shows all the variables defined so far. + /// + static public void ShowVars () + { + Output.Write (Evaluator.GetVars ()); + Output.Flush (); + } + + /// + /// Displays the using statements in effect at this point. + /// + static public void ShowUsing () + { + Output.Write (Evaluator.GetUsing ()); + Output.Flush (); + } + + /// + /// Times the execution of the given delegate + /// + static public TimeSpan Time (Action a) + { + DateTime start = DateTime.Now; + a (); + return DateTime.Now - start; + } + + /// + /// Loads the assemblies from a package + /// + /// + /// Loads the assemblies from a package. This is equivalent + /// to passing the -pkg: command line flag to the C# compiler + /// on the command line. + /// + static public void LoadPackage (string pkg) + { + if (pkg == null){ + Error.WriteLine ("Invalid package specified"); + return; + } + + string pkgout = Driver.GetPackageFlags (pkg, null); + + string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}). + Split (new Char [] { ' ', '\t'}); + + foreach (string s in xargs){ + if (s.StartsWith ("-r:") || s.StartsWith ("/r:") || s.StartsWith ("/reference:")){ + string lib = s.Substring (s.IndexOf (':')+1); + + Evaluator.LoadAssembly (lib); + continue; + } + } + } + + /// + /// Loads the assembly + /// + /// + /// Loads the specified assembly and makes its types + /// available to the evaluator. This is equivalent + /// to passing the -pkg: command line flag to the C# + /// compiler on the command line. + /// + static public void LoadAssembly (string assembly) + { + Evaluator.LoadAssembly (assembly); + } + + static public void print (object obj) + { + Output.WriteLine (obj); + } + + static public void print (string fmt, params object [] args) + { + Output.WriteLine (fmt, args); + } + + /// + /// Returns a list of available static methods. + /// + static public string help { + get { + return "Static methods:\n" + + " Describe (object); - Describes the object's type\n" + + " LoadPackage (package); - Loads the given Package (like -pkg:FILE)\n" + + " LoadAssembly (assembly); - Loads the given assembly (like -r:ASSEMBLY)\n" + + " ShowVars (); - Shows defined local variables.\n" + + " ShowUsing (); - Show active using declarations.\n" + + " Prompt - The prompt used by the C# shell\n" + + " ContinuationPrompt - The prompt for partial input\n" + + " Time (() => { }); - Times the specified code\n" + + " print (obj); - Shorthand for Console.WriteLine\n" + + " quit; - You'll never believe it - this quits the repl!\n" + + " help; - This help text\n"; + } + } + + /// + /// Indicates to the read-eval-print-loop that the interaction should be finished. + /// + static public object quit { + get { + QuitRequested = true; + + // To avoid print null at the exit + return typeof (Evaluator.QuitValue); + } + } + +#if !NET_2_1 + /// + /// Describes an object or a type. + /// + /// + /// This method will show a textual representation + /// of the object's type. If the object is a + /// System.Type it renders the type directly, + /// otherwise it renders the type returned by + /// invoking GetType on the object. + /// + static public string Describe (object x) + { + if (x == null) + return ""; + + var type = x as Type ?? x.GetType (); + + StringWriter sw = new StringWriter (); + new Outline (type, sw, true, false, false).OutlineType (); + return sw.ToString (); + } +#endif + } + + class HoistedEvaluatorVariable : HoistedVariable + { + public HoistedEvaluatorVariable (Field field) + : base (null, field) + { + } + + public override void EmitSymbolInfo () + { + } + + protected override FieldExpr GetFieldExpression (EmitContext ec) + { + return new FieldExpr (field, field.Location); + } + } + + /// + /// A class used to assign values if the source expression is not void + /// + /// Used by the interactive shell to allow it to call this code to set + /// the return value for an invocation. + /// + class OptionalAssign : SimpleAssign { + public OptionalAssign (Expression t, Expression s, Location loc) + : base (t, s, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression clone = source.Clone (new CloneContext ()); + + clone = clone.Resolve (ec); + if (clone == null) + return null; + + // + // A useful feature for the REPL: if we can resolve the expression + // as a type, Describe the type; + // + if (ec.Module.Evaluator.DescribeTypeExpressions){ + var old_printer = ec.Report.SetPrinter (new SessionReportPrinter ()); + Expression tclone; + try { + // Note: clone context cannot be shared otherwise block mapping would leak + tclone = source.Clone (new CloneContext ()); + tclone = tclone.Resolve (ec, ResolveFlags.Type); + if (ec.Report.Errors > 0) + tclone = null; + } finally { + ec.Report.SetPrinter (old_printer); + } + + if (tclone != null) { + Arguments args = new Arguments (1); + args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location))); + return new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec); + } + } + + // This means its really a statement. + if (clone.Type.Kind == MemberKind.Void || clone is DynamicInvocation || clone is Assign) { + return clone; + } + + source = clone; + return base.DoResolve (ec); + } + } + + public class Undo + { + List undo_actions; + + public Undo () + { + } + + public void AddTypeContainer (TypeContainer current_container, TypeContainer tc) + { + if (current_container == tc){ + Console.Error.WriteLine ("Internal error: inserting container into itself"); + return; + } + + if (undo_actions == null) + undo_actions = new List (); + + var existing = current_container.Types.FirstOrDefault (l => l.MemberName.Basename == tc.MemberName.Basename); + if (existing != null) { + current_container.RemoveTypeContainer (existing); + existing.NamespaceEntry.SlaveDeclSpace.RemoveTypeContainer (existing); + undo_actions.Add (() => current_container.AddTypeContainer (existing)); + } + + undo_actions.Add (() => current_container.RemoveTypeContainer (tc)); + } + + public void ExecuteUndo () + { + if (undo_actions == null) + return; + + foreach (var p in undo_actions){ + p (); + } + + undo_actions = null; + } + } + +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs new file mode 100644 index 0000000000..3349a7c000 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs @@ -0,0 +1,9943 @@ +// +// expression.cs: Expression representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using SLE = System.Linq.Expressions; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // This is an user operator expression, automatically created during + // resolve phase + // + public class UserOperatorCall : Expression { + protected readonly Arguments arguments; + protected readonly MethodSpec oper; + readonly Func expr_tree; + + public UserOperatorCall (MethodSpec oper, Arguments args, Func expr_tree, Location loc) + { + this.oper = oper; + this.arguments = args; + this.expr_tree = expr_tree; + + type = oper.ReturnType; + eclass = ExprClass.Value; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (expr_tree != null) + return expr_tree (ec, new TypeOfMethod (oper, loc)); + + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + new NullLiteral (loc), + new TypeOfMethod (oper, loc)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + protected override void CloneTo (CloneContext context, Expression target) + { + // Nothing to clone + } + + protected override Expression DoResolve (ResolveContext ec) + { + // + // We are born fully resolved + // + return this; + } + + public override void Emit (EmitContext ec) + { + Invocation.EmitCall (ec, null, oper, arguments, loc); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Call ((MethodInfo) oper.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx)); +#endif + } + } + + public class ParenthesizedExpression : ShimExpression + { + public ParenthesizedExpression (Expression expr) + : base (expr) + { + loc = expr.Location; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return expr.Resolve (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return expr.DoResolveLValue (ec, right_side); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Unary implements unary expressions. + // + public class Unary : Expression + { + public enum Operator : byte { + UnaryPlus, UnaryNegation, LogicalNot, OnesComplement, + AddressOf, TOP + } + + public readonly Operator Oper; + public Expression Expr; + Expression enum_conversion; + + public Unary (Operator op, Expression expr, Location loc) + { + Oper = op; + Expr = expr; + this.loc = loc; + } + + // + // This routine will attempt to simplify the unary expression when the + // argument is a constant. + // + Constant TryReduceConstant (ResolveContext ec, Constant e) + { + if (e is EmptyConstantCast) + return TryReduceConstant (ec, ((EmptyConstantCast) e).child); + + if (e is SideEffectConstant) { + Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value); + return r == null ? null : new SideEffectConstant (r, e, r.Location); + } + + TypeSpec expr_type = e.Type; + + switch (Oper){ + case Operator.UnaryPlus: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, ((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, ((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, ((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, ((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, ((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Decimal: + return e; + } + + return null; + + case Operator.UnaryNegation: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, -((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, -((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, -((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, -((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, -((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + int ivalue = ((IntConstant) e).Value; + if (ivalue == int.MinValue) { + if (ec.ConstantCheckState) { + ConstantFold.Error_CompileTimeOverflow (ec, loc); + return null; + } + return e; + } + return new IntConstant (ec.BuiltinTypes, -ivalue, e.Location); + + case BuiltinTypeSpec.Type.Long: + long lvalue = ((LongConstant) e).Value; + if (lvalue == long.MinValue) { + if (ec.ConstantCheckState) { + ConstantFold.Error_CompileTimeOverflow (ec, loc); + return null; + } + return e; + } + return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location); + + case BuiltinTypeSpec.Type.UInt: + UIntLiteral uil = e as UIntLiteral; + if (uil != null) { + if (uil.Value == int.MaxValue + (uint) 1) + return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location); + return new LongLiteral (ec.BuiltinTypes, -uil.Value, e.Location); + } + return new LongConstant (ec.BuiltinTypes, -((UIntConstant) e).Value, e.Location); + + + case BuiltinTypeSpec.Type.ULong: + ULongLiteral ull = e as ULongLiteral; + if (ull != null && ull.Value == 9223372036854775808) + return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location); + return null; + + case BuiltinTypeSpec.Type.Float: + FloatLiteral fl = e as FloatLiteral; + // For better error reporting + if (fl != null) + return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location); + + return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location); + + case BuiltinTypeSpec.Type.Double: + DoubleLiteral dl = e as DoubleLiteral; + // For better error reporting + if (dl != null) + return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location); + + return new DoubleConstant (ec.BuiltinTypes, -((DoubleConstant) e).Value, e.Location); + + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (ec.BuiltinTypes, -((DecimalConstant) e).Value, e.Location); + } + + return null; + + case Operator.LogicalNot: + if (expr_type.BuiltinType != BuiltinTypeSpec.Type.Bool) + return null; + + bool b = (bool)e.GetValue (); + return new BoolConstant (ec.BuiltinTypes, !b, e.Location); + + case Operator.OnesComplement: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, ~((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, ~((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, ~((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, ~((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, ~((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + return new IntConstant (ec.BuiltinTypes, ~((IntConstant)e).Value, e.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ~((UIntConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ~((LongConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ~((ULongConstant) e).Value, e.Location); + } + if (e is EnumConstant) { + e = TryReduceConstant (ec, ((EnumConstant)e).Child); + if (e != null) + e = new EnumConstant (e, expr_type); + return e; + } + return null; + } + throw new Exception ("Can not constant fold: " + Oper.ToString()); + } + + protected virtual Expression ResolveOperator (ResolveContext ec, Expression expr) + { + eclass = ExprClass.Value; + + TypeSpec expr_type = expr.Type; + Expression best_expr; + + TypeSpec[] predefined = ec.BuiltinTypes.OperatorsUnary [(int) Oper]; + + // + // Primitive types first + // + if (BuiltinTypeSpec.IsPrimitiveType (expr_type)) { + best_expr = ResolvePrimitivePredefinedType (ec, expr, predefined); + if (best_expr == null) + return null; + + type = best_expr.Type; + Expr = best_expr; + return this; + } + + // + // E operator ~(E x); + // + if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type)) + return ResolveEnumOperator (ec, expr, predefined); + + return ResolveUserType (ec, expr, predefined); + } + + protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type); + Expression best_expr = ResolvePrimitivePredefinedType (ec, EmptyCast.Create (expr, underlying_type), predefined); + if (best_expr == null) + return null; + + Expr = best_expr; + enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (best_expr.Type), underlying_type); + type = expr.Type; + return EmptyCast.Create (this, type); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return CreateExpressionTree (ec, null); + } + + Expression CreateExpressionTree (ResolveContext ec, Expression user_op) + { + string method_name; + switch (Oper) { + case Operator.AddressOf: + Error_PointerInsideExpressionTree (ec); + return null; + case Operator.UnaryNegation: + if (ec.HasSet (ResolveContext.Options.CheckedScope) && user_op == null && !IsFloat (type)) + method_name = "NegateChecked"; + else + method_name = "Negate"; + break; + case Operator.OnesComplement: + case Operator.LogicalNot: + method_name = "Not"; + break; + case Operator.UnaryPlus: + method_name = "UnaryPlus"; + break; + default: + throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ()); + } + + Arguments args = new Arguments (2); + args.Add (new Argument (Expr.CreateExpressionTree (ec))); + if (user_op != null) + args.Add (new Argument (user_op)); + + return CreateExpressionFactoryCall (ec, method_name, args); + } + + public static TypeSpec[][] CreatePredefinedOperatorsTable (BuiltinTypes types) + { + var predefined_operators = new TypeSpec[(int) Operator.TOP][]; + + // + // 7.6.1 Unary plus operator + // + predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] { + types.Int, types.UInt, + types.Long, types.ULong, + types.Float, types.Double, + types.Decimal + }; + + // + // 7.6.2 Unary minus operator + // + predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] { + types.Int, types.Long, + types.Float, types.Double, + types.Decimal + }; + + // + // 7.6.3 Logical negation operator + // + predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] { + types.Bool + }; + + // + // 7.6.4 Bitwise complement operator + // + predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] { + types.Int, types.UInt, + types.Long, types.ULong + }; + + return predefined_operators; + } + + // + // Unary numeric promotions + // + static Expression DoNumericPromotion (ResolveContext rc, Operator op, Expression expr) + { + TypeSpec expr_type = expr.Type; + if (op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) { + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Int); + } + } + + if (op == Operator.UnaryNegation && expr_type.BuiltinType == BuiltinTypeSpec.Type.UInt) + return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Long); + + return expr; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (Oper == Operator.AddressOf) { + return ResolveAddressOf (ec); + } + + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + if (Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (Expr)); + return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec); + } + + if (Expr.Type.IsNullableType) + return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec); + + // + // Attempt to use a constant folding operation. + // + Constant cexpr = Expr as Constant; + if (cexpr != null) { + cexpr = TryReduceConstant (ec, cexpr); + if (cexpr != null) + return cexpr; + } + + Expression expr = ResolveOperator (ec, Expr); + if (expr == null) + Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), Expr.Type); + + // + // Reduce unary operator on predefined types + // + if (expr == this && Oper == Operator.UnaryPlus) + return Expr; + + return expr; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right) + { + return null; + } + + public override void Emit (EmitContext ec) + { + EmitOperator (ec, type); + } + + protected void EmitOperator (EmitContext ec, TypeSpec type) + { + switch (Oper) { + case Operator.UnaryPlus: + Expr.Emit (ec); + break; + + case Operator.UnaryNegation: + if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) { + ec.Emit (OpCodes.Ldc_I4_0); + if (type.BuiltinType == BuiltinTypeSpec.Type.Long) + ec.Emit (OpCodes.Conv_U8); + Expr.Emit (ec); + ec.Emit (OpCodes.Sub_Ovf); + } else { + Expr.Emit (ec); + ec.Emit (OpCodes.Neg); + } + + break; + + case Operator.LogicalNot: + Expr.Emit (ec); + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + break; + + case Operator.OnesComplement: + Expr.Emit (ec); + ec.Emit (OpCodes.Not); + break; + + case Operator.AddressOf: + ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore); + break; + + default: + throw new Exception ("This should not happen: Operator = " + + Oper.ToString ()); + } + + // + // Same trick as in Binary expression + // + if (enum_conversion != null) + enum_conversion.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + if (Oper == Operator.LogicalNot) + Expr.EmitBranchable (ec, target, !on_true); + else + base.EmitBranchable (ec, target, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + Expr.EmitSideEffect (ec); + } + + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, TypeSpec t) + { + ec.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'", + oper, TypeManager.CSharpName (t)); + } + + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + switch (Oper) { + case Operator.OnesComplement: + return "OnesComplement"; + case Operator.LogicalNot: + return "Not"; + case Operator.UnaryNegation: + return "Negate"; + case Operator.UnaryPlus: + return "UnaryPlus"; + default: + throw new NotImplementedException ("Unknown express type operator " + Oper.ToString ()); + } + } + + static bool IsFloat (TypeSpec t) + { + return t.BuiltinType == BuiltinTypeSpec.Type.Double || t.BuiltinType == BuiltinTypeSpec.Type.Float; + } + + // + // Returns a stringified representation of the Operator + // + public static string OperName (Operator oper) + { + switch (oper) { + case Operator.UnaryPlus: + return "+"; + case Operator.UnaryNegation: + return "-"; + case Operator.LogicalNot: + return "!"; + case Operator.OnesComplement: + return "~"; + case Operator.AddressOf: + return "&"; + } + + throw new NotImplementedException (oper.ToString ()); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var expr = Expr.MakeExpression (ctx); + bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope); + + switch (Oper) { + case Operator.UnaryNegation: + return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr); + case Operator.LogicalNot: + return SLE.Expression.Not (expr); +#if NET_4_0 + case Operator.OnesComplement: + return SLE.Expression.OnesComplement (expr); +#endif + default: + throw new NotImplementedException (Oper.ToString ()); + } + } + + Expression ResolveAddressOf (ResolveContext ec) + { + if (!ec.IsUnsafe) + UnsafeError (ec, loc); + + Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress); + if (Expr == null || Expr.eclass != ExprClass.Variable) { + ec.Report.Error (211, loc, "Cannot take the address of the given expression"); + return null; + } + + if (!TypeManager.VerifyUnmanaged (ec.Module, Expr.Type, loc)) { + return null; + } + + IVariableReference vr = Expr as IVariableReference; + bool is_fixed; + if (vr != null) { + VariableInfo vi = vr.VariableInfo; + if (vi != null) { + if (vi.LocalInfo != null) + vi.LocalInfo.SetIsUsed (); + + // + // A variable is considered definitely assigned if you take its address. + // + vi.SetAssigned (ec); + } + + is_fixed = vr.IsFixed; + vr.SetHasAddressTaken (); + + if (vr.IsHoisted) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc); + } + } else { + IFixedExpression fe = Expr as IFixedExpression; + is_fixed = fe != null && fe.IsFixed; + } + + if (!is_fixed && !ec.HasSet (ResolveContext.Options.FixedInitializerScope)) { + ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer"); + } + + type = PointerContainer.MakeType (ec.Module, Expr.Type); + eclass = ExprClass.Value; + return this; + } + + Expression ResolvePrimitivePredefinedType (ResolveContext rc, Expression expr, TypeSpec[] predefined) + { + expr = DoNumericPromotion (rc, Oper, expr); + TypeSpec expr_type = expr.Type; + foreach (TypeSpec t in predefined) { + if (t == expr_type) + return expr; + } + return null; + } + + // + // Perform user-operator overload resolution + // + protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression expr) + { + CSharp.Operator.OpType op_type; + switch (Oper) { + case Operator.LogicalNot: + op_type = CSharp.Operator.OpType.LogicalNot; break; + case Operator.OnesComplement: + op_type = CSharp.Operator.OpType.OnesComplement; break; + case Operator.UnaryNegation: + op_type = CSharp.Operator.OpType.UnaryNegation; break; + case Operator.UnaryPlus: + op_type = CSharp.Operator.OpType.UnaryPlus; break; + default: + throw new InternalErrorException (Oper.ToString ()); + } + + var methods = MemberCache.GetUserOperator (expr.Type, op_type, false); + if (methods == null) + return null; + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var oper = res.ResolveOperator (ec, ref args); + + if (oper == null) + return null; + + Expr = args [0].Expr; + return new UserOperatorCall (oper, args, CreateExpressionTree, expr.Location); + } + + // + // Unary user type overload resolution + // + Expression ResolveUserType (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + Expression best_expr = ResolveUserOperator (ec, expr); + if (best_expr != null) + return best_expr; + + foreach (TypeSpec t in predefined) { + Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location); + if (oper_expr == null) + continue; + + if (oper_expr == ErrorExpression.Instance) + return oper_expr; + + // + // decimal type is predefined but has user-operators + // + if (oper_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) + oper_expr = ResolveUserType (ec, oper_expr, predefined); + else + oper_expr = ResolvePrimitivePredefinedType (ec, oper_expr, predefined); + + if (oper_expr == null) + continue; + + if (best_expr == null) { + best_expr = oper_expr; + continue; + } + + int result = OverloadResolver.BetterTypeConversion (ec, best_expr.Type, t); + if (result == 0) { + if ((oper_expr is UserOperatorCall || oper_expr is UserCast) && (best_expr is UserOperatorCall || best_expr is UserCast)) { + ec.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'", + OperName (Oper), expr.Type.GetSignatureForError ()); + } else { + Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), expr.Type); + } + + break; + } + + if (result == 2) + best_expr = oper_expr; + } + + if (best_expr == null) + return null; + + // + // HACK: Decimal user-operator is included in standard operators + // + if (best_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) + return best_expr; + + Expr = best_expr; + type = best_expr.Type; + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Unary target = (Unary) t; + + target.Expr = Expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // Unary operators are turned into Indirection expressions + // after semantic analysis (this is so we can take the address + // of an indirection). + // + public class Indirection : Expression, IMemoryLocation, IAssignMethod, IFixedExpression { + Expression expr; + LocalTemporary temporary; + bool prepared; + + public Expression Expr { + get { + return expr; + } + } + + public Indirection (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Indirection target = (Indirection) t; + target.expr = expr.Clone (clonectx); + } + + public override void Emit (EmitContext ec) + { + if (!prepared) + expr.Emit (ec); + + ec.EmitLoadFromPtr (Type); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + Emit (ec); + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temporary = new LocalTemporary (expr.Type); + temporary.Store (ec); + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + prepared = prepare_for_load; + + expr.Emit (ec); + + if (prepare_for_load) + ec.Emit (OpCodes.Dup); + + source.Emit (ec); + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temporary = new LocalTemporary (source.Type); + temporary.Store (ec); + } + + ec.EmitStoreFromPtr (type); + + if (temporary != null) { + temporary.Emit (ec); + temporary.Release (ec); + } + } + + public void AddressOf (EmitContext ec, AddressOp Mode) + { + expr.Emit (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolve (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (!ec.IsUnsafe) + UnsafeError (ec, loc); + + var pc = expr.Type as PointerContainer; + + if (pc == null) { + ec.Report.Error (193, loc, "The * or -> operator must be applied to a pointer"); + return null; + } + + type = pc.Element; + + if (type.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + eclass = ExprClass.Variable; + return this; + } + + public bool IsFixed { + get { return true; } + } + + public override string ToString () + { + return "*(" + expr + ")"; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Unary Mutator expressions (pre and post ++ and --) + /// + /// + /// + /// UnaryMutator implements ++ and -- expressions. It derives from + /// ExpressionStatement becuase the pre/post increment/decrement + /// operators can be used in a statement context. + /// + /// FIXME: Idea, we could split this up in two classes, one simpler + /// for the common case, and one with the extra fields for more complex + /// classes (indexers require temporary access; overloaded require method) + /// + /// + public class UnaryMutator : ExpressionStatement + { + class DynamicPostMutator : Expression, IAssignMethod + { + LocalTemporary temp; + Expression expr; + + public DynamicPostMutator (Expression expr) + { + this.expr = expr; + this.type = expr.Type; + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + eclass = expr.eclass; + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + expr.DoResolveLValue (ec, right_side); + return DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + temp.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + // + // Emits target assignment using unmodified source value + // + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + // + // Allocate temporary variable to keep original value before it's modified + // + temp = new LocalTemporary (type); + expr.Emit (ec); + temp.Store (ec); + + ((IAssignMethod) expr).EmitAssign (ec, source, false, prepare_for_load); + + if (leave_copy) + Emit (ec); + + temp.Release (ec); + temp = null; + } + } + + [Flags] + public enum Mode : byte { + IsIncrement = 0, + IsDecrement = 1, + IsPre = 0, + IsPost = 2, + + PreIncrement = 0, + PreDecrement = IsDecrement, + PostIncrement = IsPost, + PostDecrement = IsPost | IsDecrement + } + + Mode mode; + bool is_expr, recurse; + + Expression expr; + + // Holds the real operation + Expression operation; + + public Mode UnaryMutatorMode { + get { + return mode; + } + } + + public Expression Expr { + get { + return expr; + } + } + + public UnaryMutator (Mode m, Expression e, Location loc) + { + mode = m; + this.loc = loc; + expr = e; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return new SimpleAssign (this, this).CreateExpressionTree (ec); + } + + public static TypeSpec[] CreatePredefinedOperatorsTable (BuiltinTypes types) + { + // + // Predefined ++ and -- operators exist for the following types: + // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal + // + return new TypeSpec[] { + types.Int, + types.Long, + + types.SByte, + types.Byte, + types.Short, + types.UInt, + types.ULong, + types.Char, + types.Float, + types.Double, + types.Decimal + }; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + + if (expr == null) + return null; + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + // + // Handle postfix unary operators using local + // temporary variable + // + if ((mode & Mode.IsPost) != 0) + expr = new DynamicPostMutator (expr); + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new SimpleAssign (expr, new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc)).Resolve (ec); + } + + if (expr.Type.IsNullableType) + return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec); + + eclass = ExprClass.Value; + type = expr.Type; + + if (expr is RuntimeValueExpression) { + operation = expr; + } else { + // Use itself at the top of the stack + operation = new EmptyExpression (type); + } + + // + // The operand of the prefix/postfix increment decrement operators + // should be an expression that is classified as a variable, + // a property access or an indexer access + // + // TODO: Move to parser, expr is ATypeNameExpression + if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) { + expr = expr.ResolveLValue (ec, expr); + } else { + ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); + } + + // + // Step 1: Try to find a user operator, it has priority over predefined ones + // + var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment; + var methods = MemberCache.GetUserOperator (type, user_op, false); + + if (methods != null) { + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveOperator (ec, ref args); + if (method == null) + return null; + + args[0].Expr = operation; + operation = new UserOperatorCall (method, args, null, loc); + operation = Convert.ImplicitConversionRequired (ec, operation, type, loc); + return this; + } + + // + // Step 2: Try predefined types + // + + Expression source = null; + bool primitive_type; + + // + // Predefined without user conversion first for speed-up + // + // Predefined ++ and -- operators exist for the following types: + // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal + // + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Decimal: + source = operation; + primitive_type = true; + break; + default: + primitive_type = false; + + // ++/-- on pointer variables of all types except void* + if (type.IsPointer) { + if (((PointerContainer) type).Element.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + source = operation; + } else { + foreach (var t in ec.BuiltinTypes.OperatorsUnaryMutator) { + source = Convert.ImplicitUserConversion (ec, operation, t, loc); + + // LAMESPEC: It should error on ambiguous operators but that would make us incompatible + if (source != null) { + break; + } + } + } + + // ++/-- on enum types + if (source == null && type.IsEnum) + source = operation; + + if (source == null) { + Unary.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type); + return null; + } + + break; + } + + var one = new IntConstant (ec.BuiltinTypes, 1, loc); + var op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition; + operation = new Binary (op, source, one, loc); + operation = operation.Resolve (ec); + if (operation == null) + throw new NotImplementedException ("should not be reached"); + + if (operation.Type != type) { + if (primitive_type) + operation = Convert.ExplicitNumericConversion (ec, operation, type); + else + operation = Convert.ImplicitConversionRequired (ec, operation, type, loc); + } + + return this; + } + + void EmitCode (EmitContext ec, bool is_expr) + { + recurse = true; + this.is_expr = is_expr; + ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true); + } + + public override void Emit (EmitContext ec) + { + // + // We use recurse to allow ourselfs to be the source + // of an assignment. This little hack prevents us from + // having to allocate another expression + // + if (recurse) { + ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement)); + + operation.Emit (ec); + + recurse = false; + return; + } + + EmitCode (ec, true); + } + + public override void EmitStatement (EmitContext ec) + { + EmitCode (ec, false); + } + + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + return IsDecrement ? "Decrement" : "Increment"; + } + + bool IsDecrement { + get { return (mode & Mode.IsDecrement) != 0; } + } + + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var target = ((RuntimeValueExpression) expr).MetaObject.Expression; + var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type); + return SLE.Expression.Assign (target, source); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + UnaryMutator target = (UnaryMutator) t; + + target.expr = expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + /// + /// Base class for the `Is' and `As' classes. + /// + /// + /// + /// FIXME: Split this in two, and we get to save the `Operator' Oper + /// size. + /// + public abstract class Probe : Expression { + public Expression ProbeType; + protected Expression expr; + protected TypeSpec probe_type_expr; + + public Probe (Expression expr, Expression probe_type, Location l) + { + ProbeType = probe_type; + loc = l; + this.expr = expr; + } + + public Expression Expr { + get { + return expr; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + probe_type_expr = ProbeType.ResolveAsType (ec); + if (probe_type_expr == null) + return null; + + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (probe_type_expr.IsStatic) { + ec.Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type", + OperatorName); + } + + if (expr.Type.IsPointer || probe_type_expr.IsPointer) { + ec.Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type", + OperatorName); + return null; + } + + if (expr.Type == InternalType.AnonymousMethod) { + ec.Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression or anonymous method", + OperatorName); + return null; + } + + return this; + } + + protected abstract string OperatorName { get; } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Probe target = (Probe) t; + + target.expr = expr.Clone (clonectx); + target.ProbeType = ProbeType.Clone (clonectx); + } + + } + + /// + /// Implementation of the `is' operator. + /// + public class Is : Probe { + Nullable.Unwrap expr_unwrap; + + public Is (Expression expr, Expression probe_type, Location l) + : base (expr, probe_type, l) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + + return CreateExpressionFactoryCall (ec, "TypeIs", args); + } + + public override void Emit (EmitContext ec) + { + if (expr_unwrap != null) { + expr_unwrap.EmitCheck (ec); + return; + } + + expr.Emit (ec); + + // Only to make verifier happy + if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type)) + ec.Emit (OpCodes.Box, expr.Type); + + ec.Emit (OpCodes.Isinst, probe_type_expr); + ec.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Cgt_Un); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + if (expr_unwrap != null) { + expr_unwrap.EmitCheck (ec); + } else { + expr.Emit (ec); + ec.Emit (OpCodes.Isinst, probe_type_expr); + } + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + Expression CreateConstantResult (ResolveContext ec, bool result) + { + if (result) + ec.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type", + TypeManager.CSharpName (probe_type_expr)); + else + ec.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type", + TypeManager.CSharpName (probe_type_expr)); + + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, result, loc), this); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (base.DoResolve (ec) == null) + return null; + + TypeSpec d = expr.Type; + bool d_is_nullable = false; + + // + // If E is a method group or the null literal, or if the type of E is a reference + // type or a nullable type and the value of E is null, the result is false + // + if (expr.IsNull || expr.eclass == ExprClass.MethodGroup) + return CreateConstantResult (ec, false); + + if (d.IsNullableType) { + var ut = Nullable.NullableInfo.GetUnderlyingType (d); + if (!ut.IsGenericParameter) { + d = ut; + d_is_nullable = true; + } + } + + type = ec.BuiltinTypes.Bool; + eclass = ExprClass.Value; + TypeSpec t = probe_type_expr; + bool t_is_nullable = false; + if (t.IsNullableType) { + var ut = Nullable.NullableInfo.GetUnderlyingType (t); + if (!ut.IsGenericParameter) { + t = ut; + t_is_nullable = true; + } + } + + if (t.IsStruct) { + if (d == t) { + // + // D and T are the same value types but D can be null + // + if (d_is_nullable && !t_is_nullable) { + expr_unwrap = Nullable.Unwrap.Create (expr, false); + return this; + } + + // + // The result is true if D and T are the same value types + // + return CreateConstantResult (ec, true); + } + + var tp = d as TypeParameterSpec; + if (tp != null) + return ResolveGenericParameter (ec, t, tp); + + // + // An unboxing conversion exists + // + if (Convert.ExplicitReferenceConversionExists (d, t)) + return this; + } else { + if (TypeManager.IsGenericParameter (t)) + return ResolveGenericParameter (ec, d, (TypeParameterSpec) t); + + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Warning (1981, 3, loc, + "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'", + OperatorName, t.GetSignatureForError ()); + } + + if (TypeManager.IsGenericParameter (d)) + return ResolveGenericParameter (ec, t, (TypeParameterSpec) d); + + if (TypeSpec.IsValueType (d)) { + if (Convert.ImplicitBoxingConversion (null, d, t) != null) { + if (d_is_nullable && !t_is_nullable) { + expr_unwrap = Nullable.Unwrap.Create (expr, false); + return this; + } + + return CreateConstantResult (ec, true); + } + } else { + // if (InflatedTypeSpec.ContainsTypeParameter (d)) + // return this; + + if (Convert.ImplicitReferenceConversionExists (d, t) || + Convert.ExplicitReferenceConversionExists (d, t)) { + return this; + } + } + } + + return CreateConstantResult (ec, false); + } + + Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t) + { + if (t.IsReferenceType) { + if (d.IsStruct) + return CreateConstantResult (ec, false); + } + + if (TypeManager.IsGenericParameter (expr.Type)) { + if (expr.Type == d && TypeSpec.IsValueType (t)) + return CreateConstantResult (ec, true); + + expr = new BoxedCast (expr, d); + } + + return this; + } + + protected override string OperatorName { + get { return "is"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implementation of the `as' operator. + /// + public class As : Probe { + Expression resolved_type; + + public As (Expression expr, Expression probe_type, Location l) + : base (expr, probe_type, l) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + + return CreateExpressionFactoryCall (ec, "TypeAs", args); + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + + ec.Emit (OpCodes.Isinst, type); + + if (TypeManager.IsGenericParameter (type) || type.IsNullableType) + ec.Emit (OpCodes.Unbox_Any, type); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (resolved_type == null) { + resolved_type = base.DoResolve (ec); + + if (resolved_type == null) + return null; + } + + type = probe_type_expr; + eclass = ExprClass.Value; + TypeSpec etype = expr.Type; + + if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) { + if (TypeManager.IsGenericParameter (type)) { + ec.Report.Error (413, loc, + "The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint", + probe_type_expr.GetSignatureForError ()); + } else { + ec.Report.Error (77, loc, + "The `as' operator cannot be used with a non-nullable value type `{0}'", + TypeManager.CSharpName (type)); + } + return null; + } + + if (expr.IsNull && type.IsNullableType) { + return Nullable.LiftedNull.CreateFromExpression (ec, this); + } + + // If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound + if (etype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return this; + } + + Expression e = Convert.ImplicitConversionStandard (ec, expr, type, loc); + if (e != null) { + e = EmptyCast.Create (e, type); + return ReducedExpression.Create (e, this).Resolve (ec); + } + + if (Convert.ExplicitReferenceConversionExists (etype, type)){ + if (TypeManager.IsGenericParameter (etype)) + expr = new BoxedCast (expr, etype); + + return this; + } + + if (InflatedTypeSpec.ContainsTypeParameter (etype) || InflatedTypeSpec.ContainsTypeParameter (type)) { + expr = new BoxedCast (expr, etype); + return this; + } + + ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion", + TypeManager.CSharpName (etype), TypeManager.CSharpName (type)); + + return null; + } + + protected override string OperatorName { + get { return "as"; } + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // This represents a typecast in the source language. + // + public class Cast : ShimExpression { + Expression target_type; + + public Cast (Expression cast_type, Expression expr, Location loc) + : base (expr) + { + this.target_type = cast_type; + this.loc = loc; + } + + public Expression TargetType { + get { return target_type; } + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + type = target_type.ResolveAsType (ec); + if (type == null) + return null; + + if (type.IsStatic) { + ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); + return null; + } + + eclass = ExprClass.Value; + + Constant c = expr as Constant; + if (c != null) { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; + } + + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, loc); + } + + var res = Convert.ExplicitConversion (ec, expr, type, loc); + if (res == expr) + return EmptyCast.Create (res, type); + + return res; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Cast target = (Cast) t; + + target.target_type = target_type.Clone (clonectx); + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ImplicitCast : ShimExpression + { + bool arrayAccess; + + public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess) + : base (expr) + { + this.loc = expr.Location; + this.type = target; + this.arrayAccess = arrayAccess; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (arrayAccess) + expr = ConvertExpressionToArrayIndex (ec, expr); + else + expr = Convert.ImplicitConversionRequired (ec, expr, type, loc); + + return expr; + } + } + + // + // C# 2.0 Default value expression + // + public class DefaultValueExpression : Expression + { + Expression expr; + + + public Expression Expr { + get { + return this.expr; + } + } + + public DefaultValueExpression (Expression expr, Location loc) + { + this.expr = expr; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = expr.ResolveAsType (ec); + if (type == null) + return null; + + if (type.IsStatic) { + ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type"); + } + + if (type.IsPointer) + return new NullLiteral (Location).ConvertImplicitly (type); + + if (TypeSpec.IsReferenceType (type)) + return new NullConstant (type, loc); + + Constant c = New.Constantify (type, expr.Location); + if (c != null) + return c; + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + LocalTemporary temp_storage = new LocalTemporary(type); + + temp_storage.AddressOf(ec, AddressOp.LoadStore); + ec.Emit(OpCodes.Initobj, type); + temp_storage.Emit(ec); + } + +#if NET_4_0 && !STATIC + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return SLE.Expression.Default (type.GetMetaInfo ()); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + DefaultValueExpression target = (DefaultValueExpression) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Binary operators + /// + public class Binary : Expression, IDynamicBinder + { + public class PredefinedOperator + { + protected readonly TypeSpec left; + protected readonly TypeSpec right; + public readonly Operator OperatorsMask; + public TypeSpec ReturnType; + + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : this (ltype, rtype, op_mask, ltype) + { + } + + public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) + : this (type, type, op_mask, return_type) + { + } + + public PredefinedOperator (TypeSpec type, Operator op_mask) + : this (type, type, op_mask, type) + { + } + + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type) + { + if ((op_mask & Operator.ValuesOnlyMask) != 0) + throw new InternalErrorException ("Only masked values can be used"); + + this.left = ltype; + this.right = rtype; + this.OperatorsMask = op_mask; + this.ReturnType = return_type; + } + + public virtual Expression ConvertResult (ResolveContext ec, Binary b) + { + b.type = ReturnType; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + // + // A user operators does not support multiple user conversions, but decimal type + // is considered to be predefined type therefore we apply predefined operators rules + // and then look for decimal user-operator implementation + // + if (left.BuiltinType == BuiltinTypeSpec.Type.Decimal) + return b.ResolveUserOperator (ec, b.left, b.right); + + var c = b.right as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.Subtraction || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator)))) + return ReducedExpression.Create (b.left, b).Resolve (ec); + if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger) + return ReducedExpression.Create (b.left, b).Resolve (ec); + return b; + } + + c = b.left as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator)))) + return ReducedExpression.Create (b.right, b).Resolve (ec); + if (b.oper == Operator.Multiply && c.IsOneInteger) + return ReducedExpression.Create (b.right, b).Resolve (ec); + return b; + } + + return b; + } + + public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype) + { + // + // We are dealing with primitive types only + // + return left == ltype && ltype == rtype; + } + + public virtual bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr) + { + // Quick path + if (left == lexpr.Type && right == rexpr.Type) + return true; + + return Convert.ImplicitConversionExists (ec, lexpr, left) && + Convert.ImplicitConversionExists (ec, rexpr, right); + } + + public PredefinedOperator ResolveBetterOperator (ResolveContext ec, PredefinedOperator best_operator) + { + int result = 0; + if (left != null && best_operator.left != null) { + result = OverloadResolver.BetterTypeConversion (ec, best_operator.left, left); + } + + // + // When second argument is same as the first one, the result is same + // + if (right != null && (left != right || best_operator.left != best_operator.right)) { + result |= OverloadResolver.BetterTypeConversion (ec, best_operator.right, right); + } + + if (result == 0 || result > 2) + return null; + + return result == 1 ? best_operator : this; + } + } + + sealed class PredefinedStringOperator : PredefinedOperator + { + public PredefinedStringOperator (TypeSpec type, Operator op_mask, TypeSpec retType) + : base (type, type, op_mask, retType) + { + } + + public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType) + : base (ltype, rtype, op_mask, retType) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + // + // Use original expression for nullable arguments + // + Nullable.Unwrap unwrap = b.left as Nullable.Unwrap; + if (unwrap != null) + b.left = unwrap.Original; + + unwrap = b.right as Nullable.Unwrap; + if (unwrap != null) + b.right = unwrap.Original; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + // + // Start a new concat expression using converted expression + // + return StringConcat.Create (ec, b.left, b.right, b.loc); + } + } + + sealed class PredefinedShiftOperator : PredefinedOperator + { + public PredefinedShiftOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : base (ltype, rtype, op_mask) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + + Expression expr_tree_expr = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + int right_mask = left.BuiltinType == BuiltinTypeSpec.Type.Int || left.BuiltinType == BuiltinTypeSpec.Type.UInt ? 0x1f : 0x3f; + + // + // b = b.left >> b.right & (0x1f|0x3f) + // + b.right = new Binary (Operator.BitwiseAnd, + b.right, new IntConstant (ec.BuiltinTypes, right_mask, b.right.Location), b.loc).Resolve (ec); + + // + // Expression tree representation does not use & mask + // + b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec); + b.type = ReturnType; + + // + // Optimize shift by 0 + // + var c = b.right as Constant; + if (c != null && c.IsDefaultValue) + return ReducedExpression.Create (b.left, b).Resolve (ec); + + return b; + } + } + + sealed class PredefinedEqualityOperator : PredefinedOperator + { + MethodSpec equal_method, inequal_method; + + public PredefinedEqualityOperator (TypeSpec arg, TypeSpec retType) + : base (arg, arg, Operator.EqualityMask, retType) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + b.type = ReturnType; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + Arguments args = new Arguments (2); + args.Add (new Argument (b.left)); + args.Add (new Argument (b.right)); + + MethodSpec method; + if (b.oper == Operator.Equality) { + if (equal_method == null) { + if (left.BuiltinType == BuiltinTypeSpec.Type.String) + equal_method = ec.Module.PredefinedMembers.StringEqual.Resolve (b.loc); + else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate) + equal_method = ec.Module.PredefinedMembers.DelegateEqual.Resolve (b.loc); + else + throw new NotImplementedException (left.GetSignatureForError ()); + } + + method = equal_method; + } else { + if (inequal_method == null) { + if (left.BuiltinType == BuiltinTypeSpec.Type.String) + inequal_method = ec.Module.PredefinedMembers.StringInequal.Resolve (b.loc); + else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate) + inequal_method = ec.Module.PredefinedMembers.DelegateInequal.Resolve (b.loc); + else + throw new NotImplementedException (left.GetSignatureForError ()); + } + + method = inequal_method; + } + + return new UserOperatorCall (method, args, b.CreateExpressionTree, b.loc); + } + } + + class PredefinedPointerOperator : PredefinedOperator + { + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : base (ltype, rtype, op_mask) + { + } + + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType) + : base (ltype, rtype, op_mask, retType) + { + } + + public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) + : base (type, op_mask, return_type) + { + } + + public override bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr) + { + if (left == null) { + if (!lexpr.Type.IsPointer) + return false; + } else { + if (!Convert.ImplicitConversionExists (ec, lexpr, left)) + return false; + } + + if (right == null) { + if (!rexpr.Type.IsPointer) + return false; + } else { + if (!Convert.ImplicitConversionExists (ec, rexpr, right)) + return false; + } + + return true; + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + if (left != null) { + b.left = EmptyCast.Create (b.left, left); + } else if (right != null) { + b.right = EmptyCast.Create (b.right, right); + } + + TypeSpec r_type = ReturnType; + Expression left_arg, right_arg; + if (r_type == null) { + if (left == null) { + left_arg = b.left; + right_arg = b.right; + r_type = b.left.Type; + } else { + left_arg = b.right; + right_arg = b.left; + r_type = b.right.Type; + } + } else { + left_arg = b.left; + right_arg = b.right; + } + + return new PointerArithmetic (b.oper, left_arg, right_arg, r_type, b.loc).Resolve (ec); + } + } + + [Flags] + public enum Operator { + Multiply = 0 | ArithmeticMask, + Division = 1 | ArithmeticMask, + Modulus = 2 | ArithmeticMask, + Addition = 3 | ArithmeticMask | AdditionMask, + Subtraction = 4 | ArithmeticMask | SubtractionMask, + + LeftShift = 5 | ShiftMask, + RightShift = 6 | ShiftMask, + + LessThan = 7 | ComparisonMask | RelationalMask, + GreaterThan = 8 | ComparisonMask | RelationalMask, + LessThanOrEqual = 9 | ComparisonMask | RelationalMask, + GreaterThanOrEqual = 10 | ComparisonMask | RelationalMask, + Equality = 11 | ComparisonMask | EqualityMask, + Inequality = 12 | ComparisonMask | EqualityMask, + + BitwiseAnd = 13 | BitwiseMask, + ExclusiveOr = 14 | BitwiseMask, + BitwiseOr = 15 | BitwiseMask, + + LogicalAnd = 16 | LogicalMask, + LogicalOr = 17 | LogicalMask, + + // + // Operator masks + // + ValuesOnlyMask = ArithmeticMask - 1, + ArithmeticMask = 1 << 5, + ShiftMask = 1 << 6, + ComparisonMask = 1 << 7, + EqualityMask = 1 << 8, + BitwiseMask = 1 << 9, + LogicalMask = 1 << 10, + AdditionMask = 1 << 11, + SubtractionMask = 1 << 12, + RelationalMask = 1 << 13 + } + + protected enum State + { + None = 0, + Compound = 1 << 1, + LeftNullLifted = 1 << 2, + RightNullLifted = 1 << 3 + } + + readonly Operator oper; + protected Expression left, right; + protected State state; + Expression enum_conversion; + + public Binary (Operator oper, Expression left, Expression right, bool isCompound, Location loc) + : this (oper, left, right, loc) + { + if (isCompound) + state |= State.Compound; + } + + public Binary (Operator oper, Expression left, Expression right, Location loc) + { + this.oper = oper; + this.left = left; + this.right = right; + this.loc = loc; + } + + #region Properties + + public bool IsCompound { + get { + return (state & State.Compound) != 0; + } + } + + public Operator Oper { + get { + return oper; + } + } + + public Expression Left { + get { return this.left; } + } + + public Expression Right { + get { return this.right; } + } + + #endregion + + /// + /// Returns a stringified representation of the Operator + /// + string OperName (Operator oper) + { + string s; + switch (oper){ + case Operator.Multiply: + s = "*"; + break; + case Operator.Division: + s = "/"; + break; + case Operator.Modulus: + s = "%"; + break; + case Operator.Addition: + s = "+"; + break; + case Operator.Subtraction: + s = "-"; + break; + case Operator.LeftShift: + s = "<<"; + break; + case Operator.RightShift: + s = ">>"; + break; + case Operator.LessThan: + s = "<"; + break; + case Operator.GreaterThan: + s = ">"; + break; + case Operator.LessThanOrEqual: + s = "<="; + break; + case Operator.GreaterThanOrEqual: + s = ">="; + break; + case Operator.Equality: + s = "=="; + break; + case Operator.Inequality: + s = "!="; + break; + case Operator.BitwiseAnd: + s = "&"; + break; + case Operator.BitwiseOr: + s = "|"; + break; + case Operator.ExclusiveOr: + s = "^"; + break; + case Operator.LogicalOr: + s = "||"; + break; + case Operator.LogicalAnd: + s = "&&"; + break; + default: + s = oper.ToString (); + break; + } + + if (IsCompound) + return s + "="; + + return s; + } + + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc) + { + new Binary (oper, left, right, loc).Error_OperatorCannotBeApplied (ec, left, right); + } + + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc) + { + if (left.Type == InternalType.FakeInternalType || right.Type == InternalType.FakeInternalType) + return; + + string l, r; + l = TypeManager.CSharpName (left.Type); + r = TypeManager.CSharpName (right.Type); + + ec.Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'", + oper, l, r); + } + + protected void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right) + { + Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc); + } + + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + switch (oper) { + case Operator.Addition: + return IsCompound ? "AddAssign" : "Add"; + case Operator.BitwiseAnd: + return IsCompound ? "AndAssign" : "And"; + case Operator.BitwiseOr: + return IsCompound ? "OrAssign" : "Or"; + case Operator.Division: + return IsCompound ? "DivideAssign" : "Divide"; + case Operator.ExclusiveOr: + return IsCompound ? "ExclusiveOrAssign" : "ExclusiveOr"; + case Operator.Equality: + return "Equal"; + case Operator.GreaterThan: + return "GreaterThan"; + case Operator.GreaterThanOrEqual: + return "GreaterThanOrEqual"; + case Operator.Inequality: + return "NotEqual"; + case Operator.LeftShift: + return IsCompound ? "LeftShiftAssign" : "LeftShift"; + case Operator.LessThan: + return "LessThan"; + case Operator.LessThanOrEqual: + return "LessThanOrEqual"; + case Operator.LogicalAnd: + return "And"; + case Operator.LogicalOr: + return "Or"; + case Operator.Modulus: + return IsCompound ? "ModuloAssign" : "Modulo"; + case Operator.Multiply: + return IsCompound ? "MultiplyAssign" : "Multiply"; + case Operator.RightShift: + return IsCompound ? "RightShiftAssign" : "RightShift"; + case Operator.Subtraction: + return IsCompound ? "SubtractAssign" : "Subtract"; + default: + throw new NotImplementedException ("Unknown expression type operator " + oper.ToString ()); + } + } + + static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op) + { + switch (op) { + case Operator.Addition: + return CSharp.Operator.OpType.Addition; + case Operator.BitwiseAnd: + case Operator.LogicalAnd: + return CSharp.Operator.OpType.BitwiseAnd; + case Operator.BitwiseOr: + case Operator.LogicalOr: + return CSharp.Operator.OpType.BitwiseOr; + case Operator.Division: + return CSharp.Operator.OpType.Division; + case Operator.Equality: + return CSharp.Operator.OpType.Equality; + case Operator.ExclusiveOr: + return CSharp.Operator.OpType.ExclusiveOr; + case Operator.GreaterThan: + return CSharp.Operator.OpType.GreaterThan; + case Operator.GreaterThanOrEqual: + return CSharp.Operator.OpType.GreaterThanOrEqual; + case Operator.Inequality: + return CSharp.Operator.OpType.Inequality; + case Operator.LeftShift: + return CSharp.Operator.OpType.LeftShift; + case Operator.LessThan: + return CSharp.Operator.OpType.LessThan; + case Operator.LessThanOrEqual: + return CSharp.Operator.OpType.LessThanOrEqual; + case Operator.Modulus: + return CSharp.Operator.OpType.Modulus; + case Operator.Multiply: + return CSharp.Operator.OpType.Multiply; + case Operator.RightShift: + return CSharp.Operator.OpType.RightShift; + case Operator.Subtraction: + return CSharp.Operator.OpType.Subtraction; + default: + throw new InternalErrorException (op.ToString ()); + } + } + + public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l) + { + OpCode opcode; + + switch (oper){ + case Operator.Multiply: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Mul_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Mul_Ovf_Un; + else + opcode = OpCodes.Mul; + } else + opcode = OpCodes.Mul; + + break; + + case Operator.Division: + if (IsUnsigned (l)) + opcode = OpCodes.Div_Un; + else + opcode = OpCodes.Div; + break; + + case Operator.Modulus: + if (IsUnsigned (l)) + opcode = OpCodes.Rem_Un; + else + opcode = OpCodes.Rem; + break; + + case Operator.Addition: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Add_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Add_Ovf_Un; + else + opcode = OpCodes.Add; + } else + opcode = OpCodes.Add; + break; + + case Operator.Subtraction: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Sub_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Sub_Ovf_Un; + else + opcode = OpCodes.Sub; + } else + opcode = OpCodes.Sub; + break; + + case Operator.RightShift: + if (IsUnsigned (l)) + opcode = OpCodes.Shr_Un; + else + opcode = OpCodes.Shr; + break; + + case Operator.LeftShift: + opcode = OpCodes.Shl; + break; + + case Operator.Equality: + opcode = OpCodes.Ceq; + break; + + case Operator.Inequality: + ec.Emit (OpCodes.Ceq); + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.LessThan: + if (IsUnsigned (l)) + opcode = OpCodes.Clt_Un; + else + opcode = OpCodes.Clt; + break; + + case Operator.GreaterThan: + if (IsUnsigned (l)) + opcode = OpCodes.Cgt_Un; + else + opcode = OpCodes.Cgt; + break; + + case Operator.LessThanOrEqual: + if (IsUnsigned (l) || IsFloat (l)) + ec.Emit (OpCodes.Cgt_Un); + else + ec.Emit (OpCodes.Cgt); + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.GreaterThanOrEqual: + if (IsUnsigned (l) || IsFloat (l)) + ec.Emit (OpCodes.Clt_Un); + else + ec.Emit (OpCodes.Clt); + + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.BitwiseOr: + opcode = OpCodes.Or; + break; + + case Operator.BitwiseAnd: + opcode = OpCodes.And; + break; + + case Operator.ExclusiveOr: + opcode = OpCodes.Xor; + break; + + default: + throw new InternalErrorException (oper.ToString ()); + } + + ec.Emit (opcode); + } + + static bool IsUnsigned (TypeSpec t) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Byte: + return true; + } + + return t.IsPointer; + } + + static bool IsFloat (TypeSpec t) + { + return t.BuiltinType == BuiltinTypeSpec.Type.Float || t.BuiltinType == BuiltinTypeSpec.Type.Double; + } + + Expression ResolveOperator (ResolveContext ec) + { + TypeSpec l = left.Type; + TypeSpec r = right.Type; + Expression expr; + bool primitives_only = false; + + // + // Handles predefined primitive types + // + if (BuiltinTypeSpec.IsPrimitiveType (l) && BuiltinTypeSpec.IsPrimitiveType (r)) { + if ((oper & Operator.ShiftMask) == 0) { + if (l.BuiltinType != BuiltinTypeSpec.Type.Bool && !DoBinaryOperatorPromotion (ec)) + return null; + + primitives_only = true; + } + } else { + // Pointers + if (l.IsPointer || r.IsPointer) + return ResolveOperatorPointer (ec, l, r); + + // Enums + bool lenum = l.IsEnum; + bool renum = r.IsEnum; + if (lenum || renum) { + expr = ResolveOperatorEnum (ec, lenum, renum, l, r); + + if (expr != null) + return expr; + } + + // Delegates + if ((oper == Operator.Addition || oper == Operator.Subtraction) && (l.IsDelegate || r.IsDelegate)) { + + expr = ResolveOperatorDelegate (ec, l, r); + + // TODO: Can this be ambiguous + if (expr != null) + return expr; + } + + // User operators + expr = ResolveUserOperator (ec, left, right); + if (expr != null) + return expr; + + // Predefined reference types equality + if ((oper & Operator.EqualityMask) != 0) { + expr = ResolveOperatorEquality (ec, l, r); + if (expr != null) + return expr; + } + } + + return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, primitives_only, null); + } + + // at least one of 'left' or 'right' is an enumeration constant (EnumConstant or SideEffectConstant or ...) + // if 'left' is not an enumeration constant, create one from the type of 'right' + Constant EnumLiftUp (ResolveContext ec, Constant left, Constant right, Location loc) + { + switch (oper) { + case Operator.BitwiseOr: + case Operator.BitwiseAnd: + case Operator.ExclusiveOr: + case Operator.Equality: + case Operator.Inequality: + case Operator.LessThan: + case Operator.LessThanOrEqual: + case Operator.GreaterThan: + case Operator.GreaterThanOrEqual: + if (TypeManager.IsEnumType (left.Type)) + return left; + + if (left.IsZeroInteger) + return left.TryReduce (ec, right.Type, loc); + + break; + + case Operator.Addition: + case Operator.Subtraction: + return left; + + case Operator.Multiply: + case Operator.Division: + case Operator.Modulus: + case Operator.LeftShift: + case Operator.RightShift: + if (TypeManager.IsEnumType (right.Type) || TypeManager.IsEnumType (left.Type)) + break; + return left; + } + + return null; + } + + // + // The `|' operator used on types which were extended is dangerous + // + void CheckBitwiseOrOnSignExtended (ResolveContext ec) + { + OpcodeCast lcast = left as OpcodeCast; + if (lcast != null) { + if (IsUnsigned (lcast.UnderlyingType)) + lcast = null; + } + + OpcodeCast rcast = right as OpcodeCast; + if (rcast != null) { + if (IsUnsigned (rcast.UnderlyingType)) + rcast = null; + } + + if (lcast == null && rcast == null) + return; + + // FIXME: consider constants + + ec.Report.Warning (675, 3, loc, + "The operator `|' used on the sign-extended type `{0}'. Consider casting to a smaller unsigned type first", + TypeManager.CSharpName (lcast != null ? lcast.UnderlyingType : rcast.UnderlyingType)); + } + + public static PredefinedOperator[] CreatePointerOperatorsTable (BuiltinTypes types) + { + return new PredefinedOperator[] { + // + // Pointer arithmetic: + // + // T* operator + (T* x, int y); T* operator - (T* x, int y); + // T* operator + (T* x, uint y); T* operator - (T* x, uint y); + // T* operator + (T* x, long y); T* operator - (T* x, long y); + // T* operator + (T* x, ulong y); T* operator - (T* x, ulong y); + // + new PredefinedPointerOperator (null, types.Int, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.UInt, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.Long, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.ULong, Operator.AdditionMask | Operator.SubtractionMask), + + // + // T* operator + (int y, T* x); + // T* operator + (uint y, T *x); + // T* operator + (long y, T *x); + // T* operator + (ulong y, T *x); + // + new PredefinedPointerOperator (types.Int, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.UInt, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.Long, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.ULong, null, Operator.AdditionMask, null), + + // + // long operator - (T* x, T *y) + // + new PredefinedPointerOperator (null, Operator.SubtractionMask, types.Long) + }; + } + + public static PredefinedOperator[] CreateStandardOperatorsTable (BuiltinTypes types) + { + TypeSpec bool_type = types.Bool; + return new PredefinedOperator[] { + new PredefinedOperator (types.Int, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.UInt, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.Long, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.ULong, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.Float, Operator.ArithmeticMask), + new PredefinedOperator (types.Double, Operator.ArithmeticMask), + new PredefinedOperator (types.Decimal, Operator.ArithmeticMask), + + new PredefinedOperator (types.Int, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.UInt, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Long, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.ULong, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Float, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Double, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Decimal, Operator.ComparisonMask, bool_type), + + new PredefinedStringOperator (types.String, Operator.AdditionMask, types.String), + new PredefinedStringOperator (types.String, types.Object, Operator.AdditionMask, types.String), + new PredefinedStringOperator (types.Object, types.String, Operator.AdditionMask, types.String), + + new PredefinedOperator (bool_type, Operator.BitwiseMask | Operator.LogicalMask | Operator.EqualityMask, bool_type), + + new PredefinedShiftOperator (types.Int, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.UInt, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.Long, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.ULong, types.Int, Operator.ShiftMask) + }; + } + + public static PredefinedOperator[] CreateEqualityOperatorsTable (BuiltinTypes types) + { + TypeSpec bool_type = types.Bool; + + return new PredefinedOperator[] { + new PredefinedEqualityOperator (types.String, bool_type), + new PredefinedEqualityOperator (types.Delegate, bool_type), + new PredefinedOperator (bool_type, Operator.EqualityMask, bool_type) + }; + } + + // + // Rules used during binary numeric promotion + // + static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, TypeSpec type) + { + Expression temp; + + Constant c = prim_expr as Constant; + if (c != null) { + temp = c.ConvertImplicitly (type); + if (temp != null) { + prim_expr = temp; + return true; + } + } + + if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) { + switch (prim_expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Long: + type = rc.BuiltinTypes.Long; + + if (type != second_expr.Type) { + c = second_expr as Constant; + if (c != null) + temp = c.ConvertImplicitly (type); + else + temp = Convert.ImplicitNumericConversion (second_expr, type); + if (temp == null) + return false; + second_expr = temp; + } + break; + } + } else if (type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + // + // A compile-time error occurs if the other operand is of type sbyte, short, int, or long + // + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.SByte: + return false; + } + } + + temp = Convert.ImplicitNumericConversion (prim_expr, type); + if (temp == null) + return false; + + prim_expr = temp; + return true; + } + + // + // 7.2.6.2 Binary numeric promotions + // + public bool DoBinaryOperatorPromotion (ResolveContext ec) + { + TypeSpec ltype = left.Type; + TypeSpec rtype = right.Type; + Expression temp; + + foreach (TypeSpec t in ec.BuiltinTypes.BinaryPromotionsTypes) { + if (t == ltype) + return t == rtype || DoNumericPromotion (ec, ref right, ref left, t); + + if (t == rtype) + return t == ltype || DoNumericPromotion (ec, ref left, ref right, t); + } + + TypeSpec int32 = ec.BuiltinTypes.Int; + if (ltype != int32) { + Constant c = left as Constant; + if (c != null) + temp = c.ConvertImplicitly (int32); + else + temp = Convert.ImplicitNumericConversion (left, int32); + + if (temp == null) + return false; + left = temp; + } + + if (rtype != int32) { + Constant c = right as Constant; + if (c != null) + temp = c.ConvertImplicitly (int32); + else + temp = Convert.ImplicitNumericConversion (right, int32); + + if (temp == null) + return false; + right = temp; + } + + return true; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (left == null) + return null; + + if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) { + left = ((ParenthesizedExpression) left).Expr; + left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type); + if (left == null) + return null; + + if (left.eclass == ExprClass.Type) { + ec.Report.Error (75, loc, "To cast a negative value, you must enclose the value in parentheses"); + return null; + } + } else + left = left.Resolve (ec); + + if (left == null) + return null; + + Constant lc = left as Constant; + + if (lc != null && lc.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && + ((oper == Operator.LogicalAnd && lc.IsDefaultValue) || + (oper == Operator.LogicalOr && !lc.IsDefaultValue))) { + + // FIXME: resolve right expression as unreachable + // right.Resolve (ec); + + ec.Report.Warning (429, 4, loc, "Unreachable expression code detected"); + return left; + } + + right = right.Resolve (ec); + if (right == null) + return null; + + eclass = ExprClass.Value; + Constant rc = right as Constant; + + // The conversion rules are ignored in enum context but why + if (!ec.HasSet (ResolveContext.Options.EnumScope) && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) { + lc = EnumLiftUp (ec, lc, rc, loc); + if (lc != null) + rc = EnumLiftUp (ec, rc, lc, loc); + } + + if (rc != null && lc != null) { + int prev_e = ec.Report.Errors; + Expression e = ConstantFold.BinaryFold (ec, oper, lc, rc, loc); + if (e != null || ec.Report.Errors != prev_e) + return e; + } + + // Comparison warnings + if ((oper & Operator.ComparisonMask) != 0) { + if (left.Equals (right)) { + ec.Report.Warning (1718, 3, loc, "A comparison made to same variable. Did you mean to compare something else?"); + } + CheckOutOfRangeComparison (ec, lc, right.Type); + CheckOutOfRangeComparison (ec, rc, left.Type); + } + + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + var lt = left.Type; + var rt = right.Type; + if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod || + rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) { + Error_OperatorCannotBeApplied (ec, left, right); + return null; + } + + Arguments args; + + // + // Special handling for logical boolean operators which require rhs not to be + // evaluated based on lhs value + // + if ((oper & Operator.LogicalMask) != 0) { + Expression cond_left, cond_right, expr; + + args = new Arguments (2); + + if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, ec.CurrentBlock, loc); + + var cond_args = new Arguments (1); + cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left).Resolve (ec))); + + // + // dynamic && bool => IsFalse (temp = left) ? temp : temp && right; + // dynamic || bool => IsTrue (temp = left) ? temp : temp || right; + // + left = temp.CreateReferenceExpression (ec, loc); + if (oper == Operator.LogicalAnd) { + expr = DynamicUnaryConversion.CreateIsFalse (ec, cond_args, loc); + cond_left = left; + } else { + expr = DynamicUnaryConversion.CreateIsTrue (ec, cond_args, loc); + cond_left = left; + } + + args.Add (new Argument (left)); + args.Add (new Argument (right)); + cond_right = new DynamicExpressionStatement (this, args, loc); + } else { + LocalVariable temp = LocalVariable.CreateCompilerGenerated (ec.BuiltinTypes.Bool, ec.CurrentBlock, loc); + + args.Add (new Argument (temp.CreateReferenceExpression (ec, loc).Resolve (ec))); + args.Add (new Argument (right)); + right = new DynamicExpressionStatement (this, args, loc); + + // + // bool && dynamic => (temp = left) ? temp && right : temp; + // bool || dynamic => (temp = left) ? temp : temp || right; + // + if (oper == Operator.LogicalAnd) { + cond_left = right; + cond_right = temp.CreateReferenceExpression (ec, loc); + } else { + cond_left = temp.CreateReferenceExpression (ec, loc); + cond_right = right; + } + + expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left)); + } + + return new Conditional (expr, cond_left, cond_right, loc).Resolve (ec); + } + + args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); + return new DynamicExpressionStatement (this, args, loc).Resolve (ec); + } + + if (ec.Module.Compiler.Settings.Version >= LanguageVersion.ISO_2 && + ((left.Type.IsNullableType && (right is NullLiteral || right.Type.IsNullableType || TypeSpec.IsValueType (right.Type))) || + (TypeSpec.IsValueType (left.Type) && right is NullLiteral) || + (right.Type.IsNullableType && (left is NullLiteral || left.Type.IsNullableType || TypeSpec.IsValueType (left.Type))) || + (TypeSpec.IsValueType (right.Type) && left is NullLiteral))) { + var lifted = new Nullable.LiftedBinaryOperator (oper, left, right, loc); + lifted.state = state; + return lifted.Resolve (ec); + } + + return DoResolveCore (ec, left, right); + } + + protected Expression DoResolveCore (ResolveContext ec, Expression left_orig, Expression right_orig) + { + Expression expr = ResolveOperator (ec); + if (expr == null) + Error_OperatorCannotBeApplied (ec, left_orig, right_orig); + + if (left == null || right == null) + throw new InternalErrorException ("Invalid conversion"); + + if (oper == Operator.BitwiseOr) + CheckBitwiseOrOnSignExtended (ec); + + return expr; + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var le = left.MakeExpression (ctx); + var re = right.MakeExpression (ctx); + bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope); + + switch (oper) { + case Operator.Addition: + return is_checked ? SLE.Expression.AddChecked (le, re) : SLE.Expression.Add (le, re); + case Operator.BitwiseAnd: + return SLE.Expression.And (le, re); + case Operator.BitwiseOr: + return SLE.Expression.Or (le, re); + case Operator.Division: + return SLE.Expression.Divide (le, re); + case Operator.Equality: + return SLE.Expression.Equal (le, re); + case Operator.ExclusiveOr: + return SLE.Expression.ExclusiveOr (le, re); + case Operator.GreaterThan: + return SLE.Expression.GreaterThan (le, re); + case Operator.GreaterThanOrEqual: + return SLE.Expression.GreaterThanOrEqual (le, re); + case Operator.Inequality: + return SLE.Expression.NotEqual (le, re); + case Operator.LeftShift: + return SLE.Expression.LeftShift (le, re); + case Operator.LessThan: + return SLE.Expression.LessThan (le, re); + case Operator.LessThanOrEqual: + return SLE.Expression.LessThanOrEqual (le, re); + case Operator.LogicalAnd: + return SLE.Expression.AndAlso (le, re); + case Operator.LogicalOr: + return SLE.Expression.OrElse (le, re); + case Operator.Modulus: + return SLE.Expression.Modulo (le, re); + case Operator.Multiply: + return is_checked ? SLE.Expression.MultiplyChecked (le, re) : SLE.Expression.Multiply (le, re); + case Operator.RightShift: + return SLE.Expression.RightShift (le, re); + case Operator.Subtraction: + return is_checked ? SLE.Expression.SubtractChecked (le, re) : SLE.Expression.Subtract (le, re); + default: + throw new NotImplementedException (oper.ToString ()); + } + } + + // + // D operator + (D x, D y) + // D operator - (D x, D y) + // + Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r) + { + if (l != r && !TypeSpecComparer.Variant.IsEqual (r, l)) { + Expression tmp; + if (right.eclass == ExprClass.MethodGroup || r == InternalType.AnonymousMethod || r == InternalType.NullLiteral) { + tmp = Convert.ImplicitConversionRequired (ec, right, l, loc); + if (tmp == null) + return null; + right = tmp; + r = right.Type; + } else if (left.eclass == ExprClass.MethodGroup || (l == InternalType.AnonymousMethod || l == InternalType.NullLiteral)) { + tmp = Convert.ImplicitConversionRequired (ec, left, r, loc); + if (tmp == null) + return null; + left = tmp; + l = left.Type; + } else { + return null; + } + } + + MethodSpec method = null; + Arguments args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); + + if (oper == Operator.Addition) { + method = ec.Module.PredefinedMembers.DelegateCombine.Resolve (loc); + } else if (oper == Operator.Subtraction) { + method = ec.Module.PredefinedMembers.DelegateRemove.Resolve (loc); + } + + if (method == null) + return new EmptyExpression (ec.BuiltinTypes.Decimal); + + MethodGroupExpr mg = MethodGroupExpr.CreatePredefined (method, ec.BuiltinTypes.Delegate, loc); + Expression expr = new UserOperatorCall (mg.BestCandidate, args, CreateExpressionTree, loc); + return new ClassCast (expr, l); + } + + // + // Enumeration operators + // + Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype) + { + // + // bool operator == (E x, E y); + // bool operator != (E x, E y); + // bool operator < (E x, E y); + // bool operator > (E x, E y); + // bool operator <= (E x, E y); + // bool operator >= (E x, E y); + // + // E operator & (E x, E y); + // E operator | (E x, E y); + // E operator ^ (E x, E y); + // + // U operator - (E e, E f) + // E operator - (E e, U x) + // E operator - (U x, E e) // LAMESPEC: Not covered by the specification + // + // E operator + (E e, U x) + // E operator + (U x, E e) + // + Expression ltemp = left; + Expression rtemp = right; + TypeSpec underlying_type; + TypeSpec underlying_type_result; + TypeSpec res_type; + Expression expr; + + // + // LAMESPEC: There is never ambiguous conversion between enum operators + // the one which contains more enum parameters always wins even if there + // is an implicit conversion involved + // + if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) { + if (renum) { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + expr = Convert.ImplicitConversion (ec, left, rtype, loc); + if (expr == null) + return null; + + left = expr; + ltype = expr.Type; + } else if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + expr = Convert.ImplicitConversion (ec, right, ltype, loc); + if (expr == null) + return null; + + right = expr; + rtype = expr.Type; + } else { + return null; + } + + if ((oper & Operator.BitwiseMask) != 0) { + res_type = ltype; + underlying_type_result = underlying_type; + } else { + res_type = null; + underlying_type_result = null; + } + } else if (oper == Operator.Subtraction) { + if (renum) { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + if (ltype != rtype) { + expr = Convert.ImplicitConversion (ec, left, rtype, left.Location); + if (expr == null) { + expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location); + if (expr == null) + return null; + + res_type = rtype; + } else { + res_type = underlying_type; + } + + left = expr; + } else { + res_type = underlying_type; + } + + underlying_type_result = underlying_type; + } else if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + expr = Convert.ImplicitConversion (ec, right, ltype, right.Location); + if (expr == null || expr is EnumConstant) { + expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location); + if (expr == null) + return null; + + res_type = ltype; + } else { + res_type = underlying_type; + } + + right = expr; + underlying_type_result = underlying_type; + } else { + return null; + } + } else if (oper == Operator.Addition) { + if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + res_type = ltype; + + if (rtype != underlying_type && (state & (State.RightNullLifted | State.LeftNullLifted)) == 0) { + expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location); + if (expr == null) + return null; + + right = expr; + } + } else { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + res_type = rtype; + if (ltype != underlying_type) { + expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location); + if (expr == null) + return null; + + left = expr; + } + } + + underlying_type_result = underlying_type; + } else { + return null; + } + + // Unwrap the constant correctly, so DoBinaryOperatorPromotion can do the magic + // with constants and expressions + if (left.Type != underlying_type) { + if (left is Constant) + left = ((Constant) left).ConvertExplicitly (false, underlying_type); + else + left = EmptyCast.Create (left, underlying_type); + } + + if (right.Type != underlying_type) { + if (right is Constant) + right = ((Constant) right).ConvertExplicitly (false, underlying_type); + else + right = EmptyCast.Create (right, underlying_type); + } + + // + // C# specification uses explicit cast syntax which means binary promotion + // should happen, however it seems that csc does not do that + // + if (!DoBinaryOperatorPromotion (ec)) { + left = ltemp; + right = rtemp; + return null; + } + + if (underlying_type_result != null && left.Type != underlying_type_result) { + enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (left.Type), underlying_type_result); + } + + expr = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, true, res_type); + if (expr == null) + return null; + + if (!IsCompound) + return expr; + + // + // Section: 7.16.2 + // + + // + // If the return type of the selected operator is implicitly convertible to the type of x + // + if (Convert.ImplicitConversionExists (ec, expr, ltype)) + return expr; + + // + // Otherwise, if the selected operator is a predefined operator, if the return type of the + // selected operator is explicitly convertible to the type of x, and if y is implicitly + // convertible to the type of x or the operator is a shift operator, then the operation + // is evaluated as x = (T)(x op y), where T is the type of x + // + expr = Convert.ExplicitConversion (ec, expr, ltype, loc); + if (expr == null) + return null; + + if (Convert.ImplicitConversionExists (ec, ltemp, ltype)) + return expr; + + return null; + } + + // + // 7.9.6 Reference type equality operators + // + Expression ResolveOperatorEquality (ResolveContext ec, TypeSpec l, TypeSpec r) + { + Expression result; + type = ec.BuiltinTypes.Bool; + + // + // a, Both operands are reference-type values or the value null + // b, One operand is a value of type T where T is a type-parameter and + // the other operand is the value null. Furthermore T does not have the + // value type constraint + // + // LAMESPEC: Very confusing details in the specification, basically any + // reference like type-parameter is allowed + // + var tparam_l = l as TypeParameterSpec; + var tparam_r = r as TypeParameterSpec; + if (tparam_l != null) { + if (right is NullLiteral && !tparam_l.HasSpecialStruct) { + left = new BoxedCast (left, ec.BuiltinTypes.Object); + return this; + } + + if (!tparam_l.IsReferenceType) + return null; + + l = tparam_l.GetEffectiveBase (); + left = new BoxedCast (left, l); + } else if (left is NullLiteral && tparam_r == null) { + if (!TypeSpec.IsReferenceType (r) || r.Kind == MemberKind.InternalCompilerType) + return null; + + return this; + } + + if (tparam_r != null) { + if (left is NullLiteral && !tparam_r.HasSpecialStruct) { + right = new BoxedCast (right, ec.BuiltinTypes.Object); + return this; + } + + if (!tparam_r.IsReferenceType) + return null; + + r = tparam_r.GetEffectiveBase (); + right = new BoxedCast (right, r); + } else if (right is NullLiteral) { + if (!TypeSpec.IsReferenceType (l) || l.Kind == MemberKind.InternalCompilerType) + return null; + + return this; + } + + // + // LAMESPEC: method groups can be compared when they convert to other side delegate + // + if (l.IsDelegate) { + if (right.eclass == ExprClass.MethodGroup) { + result = Convert.ImplicitConversion (ec, right, l, loc); + if (result == null) + return null; + + right = result; + r = l; + } else if (r.IsDelegate && l != r) { + return null; + } + } else if (left.eclass == ExprClass.MethodGroup && r.IsDelegate) { + result = Convert.ImplicitConversionRequired (ec, left, r, loc); + if (result == null) + return null; + + left = result; + l = r; + } + + // + // bool operator != (string a, string b) + // bool operator == (string a, string b) + // + // bool operator != (Delegate a, Delegate b) + // bool operator == (Delegate a, Delegate b) + // + // bool operator != (bool a, bool b) + // bool operator == (bool a, bool b) + // + // LAMESPEC: Reference equality comparison can apply to value types when + // they implement an implicit conversion to any of types above. + // + if (r.BuiltinType != BuiltinTypeSpec.Type.Object && l.BuiltinType != BuiltinTypeSpec.Type.Object) { + result = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryEquality, false, null); + if (result != null) + return result; + } + + // + // bool operator != (object a, object b) + // bool operator == (object a, object b) + // + // An explicit reference conversion exists from the + // type of either operand to the type of the other operand. + // + + // Optimize common path + if (l == r) { + return l.Kind == MemberKind.InternalCompilerType || l.Kind == MemberKind.Struct ? null : this; + } + + if (!Convert.ExplicitReferenceConversionExists (l, r) && + !Convert.ExplicitReferenceConversionExists (r, l)) + return null; + + // Reject allowed explicit conversions like int->object + if (!TypeSpec.IsReferenceType (l) || !TypeSpec.IsReferenceType (r)) + return null; + + if (l.BuiltinType == BuiltinTypeSpec.Type.String || l.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (l, CSharp.Operator.OpType.Equality, false) != null) + ec.Report.Warning (253, 2, loc, + "Possible unintended reference comparison. Consider casting the right side expression to type `{0}' to get value comparison", + l.GetSignatureForError ()); + + if (r.BuiltinType == BuiltinTypeSpec.Type.String || r.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (r, CSharp.Operator.OpType.Equality, false) != null) + ec.Report.Warning (252, 2, loc, + "Possible unintended reference comparison. Consider casting the left side expression to type `{0}' to get value comparison", + r.GetSignatureForError ()); + + return this; + } + + + Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r) + { + // + // bool operator == (void* x, void* y); + // bool operator != (void* x, void* y); + // bool operator < (void* x, void* y); + // bool operator > (void* x, void* y); + // bool operator <= (void* x, void* y); + // bool operator >= (void* x, void* y); + // + if ((oper & Operator.ComparisonMask) != 0) { + Expression temp; + if (!l.IsPointer) { + temp = Convert.ImplicitConversion (ec, left, r, left.Location); + if (temp == null) + return null; + left = temp; + } + + if (!r.IsPointer) { + temp = Convert.ImplicitConversion (ec, right, l, right.Location); + if (temp == null) + return null; + right = temp; + } + + type = ec.BuiltinTypes.Bool; + return this; + } + + return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryUnsafe, false, null); + } + + // + // Build-in operators method overloading + // + protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type) + { + PredefinedOperator best_operator = null; + TypeSpec l = left.Type; + TypeSpec r = right.Type; + Operator oper_mask = oper & ~Operator.ValuesOnlyMask; + + foreach (PredefinedOperator po in operators) { + if ((po.OperatorsMask & oper_mask) == 0) + continue; + + if (primitives_only) { + if (!po.IsPrimitiveApplicable (l, r)) + continue; + } else { + if (!po.IsApplicable (ec, left, right)) + continue; + } + + if (best_operator == null) { + best_operator = po; + if (primitives_only) + break; + + continue; + } + + best_operator = po.ResolveBetterOperator (ec, best_operator); + + if (best_operator == null) { + ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'", + OperName (oper), TypeManager.CSharpName (l), TypeManager.CSharpName (r)); + + best_operator = po; + break; + } + } + + if (best_operator == null) + return null; + + Expression expr = best_operator.ConvertResult (ec, this); + + // + // Optimize &/&& constant expressions with 0 value + // + if (oper == Operator.BitwiseAnd || oper == Operator.LogicalAnd) { + Constant rc = right as Constant; + Constant lc = left as Constant; + if (((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) && !(this is Nullable.LiftedBinaryOperator)) { + // + // The result is a constant with side-effect + // + Constant side_effect = rc == null ? + new SideEffectConstant (lc, right, loc) : + new SideEffectConstant (rc, left, loc); + + return ReducedExpression.Create (side_effect, expr); + } + } + + if (enum_type == null) + return expr; + + // + // HACK: required by enum_conversion + // + expr.Type = enum_type; + return EmptyCast.Create (expr, enum_type); + } + + // + // Performs user-operator overloading + // + protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression left, Expression right) + { + var op = ConvertBinaryToUserOperator (oper); + var l = left.Type; + if (l.IsNullableType) + l = Nullable.NullableInfo.GetUnderlyingType (l); + var r = right.Type; + if (r.IsNullableType) + r = Nullable.NullableInfo.GetUnderlyingType (r); + + IList left_operators = MemberCache.GetUserOperator (l, op, false); + IList right_operators = null; + + if (l != r) { + right_operators = MemberCache.GetUserOperator (r, op, false); + if (right_operators == null && left_operators == null) + return null; + } else if (left_operators == null) { + return null; + } + + Arguments args = new Arguments (2); + Argument larg = new Argument (left); + args.Add (larg); + Argument rarg = new Argument (right); + args.Add (rarg); + + // + // User-defined operator implementations always take precedence + // over predefined operator implementations + // + if (left_operators != null && right_operators != null) { + left_operators = CombineUserOperators (left_operators, right_operators); + } else if (right_operators != null) { + left_operators = right_operators; + } + + var res = new OverloadResolver (left_operators, OverloadResolver.Restrictions.ProbingOnly | + OverloadResolver.Restrictions.NoBaseMembers | OverloadResolver.Restrictions.BaseMembersIncluded, loc); + + var oper_method = res.ResolveOperator (ec, ref args); + if (oper_method == null) + return null; + + var llifted = (state & State.LeftNullLifted) != 0; + var rlifted = (state & State.RightNullLifted) != 0; + if ((Oper & Operator.EqualityMask) != 0) { + var parameters = oper_method.Parameters; + // LAMESPEC: No idea why this is not allowed + if ((left is Nullable.Unwrap || right is Nullable.Unwrap) && parameters.Types [0] != parameters.Types [1]) + return null; + + // Binary operation was lifted but we have found a user operator + // which requires value-type argument, we downgrade ourself back to + // binary operation + // LAMESPEC: The user operator is not called (it cannot be we are passing null to struct) + // but compilation succeeds + if ((llifted && !parameters.Types[0].IsStruct) || (rlifted && !parameters.Types[1].IsStruct)) { + state &= ~(State.LeftNullLifted | State.RightNullLifted); + } + } + + Expression oper_expr; + + // TODO: CreateExpressionTree is allocated every time + if ((oper & Operator.LogicalMask) != 0) { + oper_expr = new ConditionalLogicalOperator (oper_method, args, CreateExpressionTree, + oper == Operator.LogicalAnd, loc).Resolve (ec); + } else { + oper_expr = new UserOperatorCall (oper_method, args, CreateExpressionTree, loc); + } + + if (!llifted) + this.left = larg.Expr; + + if (!rlifted) + this.right = rarg.Expr; + + return oper_expr; + } + + // + // Merge two sets of user operators into one, they are mostly distinguish + // expect when they share base type and it contains an operator + // + static IList CombineUserOperators (IList left, IList right) + { + var combined = new List (left.Count + right.Count); + combined.AddRange (left); + foreach (var r in right) { + bool same = false; + foreach (var l in left) { + if (l.DeclaringType == r.DeclaringType) { + same = true; + break; + } + } + + if (!same) + combined.Add (r); + } + + return combined; + } + + void CheckOutOfRangeComparison (ResolveContext ec, Constant c, TypeSpec type) + { + if (c is IntegralConstant || c is CharConstant) { + try { + c.ConvertExplicitly (true, type); + } catch (OverflowException) { + ec.Report.Warning (652, 2, loc, + "A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'", + TypeManager.CSharpName (type)); + } + } + } + + /// + /// EmitBranchable is called from Statement.EmitBoolExpression in the + /// context of a conditional bool expression. This function will return + /// false if it is was possible to use EmitBranchable, or true if it was. + /// + /// The expression's code is generated, and we will generate a branch to `target' + /// if the resulting expression value is equal to isTrue + /// + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + // + // This is more complicated than it looks, but its just to avoid + // duplicated tests: basically, we allow ==, !=, >, <, >= and <= + // but on top of that we want for == and != to use a special path + // if we are comparing against null + // + if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) { + bool my_on_true = oper == Operator.Inequality ? on_true : !on_true; + + // + // put the constant on the rhs, for simplicity + // + if (left is Constant) { + Expression swap = right; + right = left; + left = swap; + } + + // + // brtrue/brfalse works with native int only + // + if (((Constant) right).IsZeroInteger && right.Type.BuiltinType != BuiltinTypeSpec.Type.Long && right.Type.BuiltinType != BuiltinTypeSpec.Type.ULong) { + left.EmitBranchable (ec, target, my_on_true); + return; + } + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) { + // right is a boolean, and it's not 'false' => it is 'true' + left.EmitBranchable (ec, target, !my_on_true); + return; + } + + } else if (oper == Operator.LogicalAnd) { + + if (on_true) { + Label tests_end = ec.DefineLabel (); + + left.EmitBranchable (ec, tests_end, false); + right.EmitBranchable (ec, target, true); + ec.MarkLabel (tests_end); + } else { + // + // This optimizes code like this + // if (true && i > 4) + // + if (!(left is Constant)) + left.EmitBranchable (ec, target, false); + + if (!(right is Constant)) + right.EmitBranchable (ec, target, false); + } + + return; + + } else if (oper == Operator.LogicalOr){ + if (on_true) { + left.EmitBranchable (ec, target, true); + right.EmitBranchable (ec, target, true); + + } else { + Label tests_end = ec.DefineLabel (); + left.EmitBranchable (ec, tests_end, true); + right.EmitBranchable (ec, target, false); + ec.MarkLabel (tests_end); + } + + return; + + } else if ((oper & Operator.ComparisonMask) == 0) { + base.EmitBranchable (ec, target, on_true); + return; + } + + left.Emit (ec); + right.Emit (ec); + + TypeSpec t = left.Type; + bool is_float = IsFloat (t); + bool is_unsigned = is_float || IsUnsigned (t); + + switch (oper){ + case Operator.Equality: + if (on_true) + ec.Emit (OpCodes.Beq, target); + else + ec.Emit (OpCodes.Bne_Un, target); + break; + + case Operator.Inequality: + if (on_true) + ec.Emit (OpCodes.Bne_Un, target); + else + ec.Emit (OpCodes.Beq, target); + break; + + case Operator.LessThan: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Blt_Un, target); + else + ec.Emit (OpCodes.Blt, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Bge_Un, target); + else + ec.Emit (OpCodes.Bge, target); + break; + + case Operator.GreaterThan: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Bgt_Un, target); + else + ec.Emit (OpCodes.Bgt, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Ble_Un, target); + else + ec.Emit (OpCodes.Ble, target); + break; + + case Operator.LessThanOrEqual: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Ble_Un, target); + else + ec.Emit (OpCodes.Ble, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Bgt_Un, target); + else + ec.Emit (OpCodes.Bgt, target); + break; + + + case Operator.GreaterThanOrEqual: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Bge_Un, target); + else + ec.Emit (OpCodes.Bge, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Blt_Un, target); + else + ec.Emit (OpCodes.Blt, target); + break; + default: + throw new InternalErrorException (oper.ToString ()); + } + } + + public override void Emit (EmitContext ec) + { + EmitOperator (ec, left.Type); + } + + protected virtual void EmitOperator (EmitContext ec, TypeSpec l) + { + // + // Handle short-circuit operators differently + // than the rest + // + if ((oper & Operator.LogicalMask) != 0) { + Label load_result = ec.DefineLabel (); + Label end = ec.DefineLabel (); + + bool is_or = oper == Operator.LogicalOr; + left.EmitBranchable (ec, load_result, is_or); + right.Emit (ec); + ec.Emit (OpCodes.Br_S, end); + + ec.MarkLabel (load_result); + ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + ec.MarkLabel (end); + return; + } + + // + // Optimize zero-based operations which cannot be optimized at expression level + // + if (oper == Operator.Subtraction) { + var lc = left as IntegralConstant; + if (lc != null && lc.IsDefaultValue) { + right.Emit (ec); + ec.Emit (OpCodes.Neg); + return; + } + } + + left.Emit (ec); + right.Emit (ec); + EmitOperatorOpcode (ec, oper, l); + + // + // Nullable enum could require underlying type cast and we cannot simply wrap binary + // expression because that would wrap lifted binary operation + // + if (enum_conversion != null) + enum_conversion.Emit (ec); + } + + public override void EmitSideEffect (EmitContext ec) + { + if ((oper & Operator.LogicalMask) != 0 || + (ec.HasSet (EmitContext.Options.CheckedScope) && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) { + base.EmitSideEffect (ec); + } else { + left.EmitSideEffect (ec); + right.EmitSideEffect (ec); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Binary target = (Binary) t; + + target.left = left.Clone (clonectx); + target.right = right.Clone (clonectx); + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (4); + + MemberAccess sle = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); + + CSharpBinderFlags flags = 0; + if (ec.HasSet (ResolveContext.Options.CheckedScope)) + flags = CSharpBinderFlags.CheckedContext; + + if ((oper & Operator.LogicalMask) != 0) + flags |= CSharpBinderFlags.BinaryOperationLogical; + + binder_args.Add (new Argument (new EnumConstant (new IntLiteral (ec.BuiltinTypes, (int) flags, loc), ec.Module.PredefinedTypes.BinderFlags.Resolve ()))); + binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (new MemberAccess (new TypeExpression (ec.Module.PredefinedTypes.Binder.TypeSpec, loc), "BinaryOperation", loc), binder_args); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return CreateExpressionTree (ec, null); + } + + Expression CreateExpressionTree (ResolveContext ec, Expression method) + { + string method_name; + bool lift_arg = false; + + switch (oper) { + case Operator.Addition: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "AddChecked"; + else + method_name = "Add"; + break; + case Operator.BitwiseAnd: + method_name = "And"; + break; + case Operator.BitwiseOr: + method_name = "Or"; + break; + case Operator.Division: + method_name = "Divide"; + break; + case Operator.Equality: + method_name = "Equal"; + lift_arg = true; + break; + case Operator.ExclusiveOr: + method_name = "ExclusiveOr"; + break; + case Operator.GreaterThan: + method_name = "GreaterThan"; + lift_arg = true; + break; + case Operator.GreaterThanOrEqual: + method_name = "GreaterThanOrEqual"; + lift_arg = true; + break; + case Operator.Inequality: + method_name = "NotEqual"; + lift_arg = true; + break; + case Operator.LeftShift: + method_name = "LeftShift"; + break; + case Operator.LessThan: + method_name = "LessThan"; + lift_arg = true; + break; + case Operator.LessThanOrEqual: + method_name = "LessThanOrEqual"; + lift_arg = true; + break; + case Operator.LogicalAnd: + method_name = "AndAlso"; + break; + case Operator.LogicalOr: + method_name = "OrElse"; + break; + case Operator.Modulus: + method_name = "Modulo"; + break; + case Operator.Multiply: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "MultiplyChecked"; + else + method_name = "Multiply"; + break; + case Operator.RightShift: + method_name = "RightShift"; + break; + case Operator.Subtraction: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "SubtractChecked"; + else + method_name = "Subtract"; + break; + + default: + throw new InternalErrorException ("Unknown expression tree binary operator " + oper); + } + + Arguments args = new Arguments (2); + args.Add (new Argument (left.CreateExpressionTree (ec))); + args.Add (new Argument (right.CreateExpressionTree (ec))); + if (method != null) { + if (lift_arg) + args.Add (new Argument (new BoolLiteral (ec.BuiltinTypes, false, loc))); + + args.Add (new Argument (method)); + } + + return CreateExpressionFactoryCall (ec, method_name, args); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string + // b, c, d... may be strings or objects. + // + public class StringConcat : Expression + { + Arguments arguments; + + StringConcat (Location loc) + { + this.loc = loc; + arguments = new Arguments (2); + } + + public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc) + { + if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved) + throw new ArgumentException (); + + var s = new StringConcat (loc); + s.type = rc.BuiltinTypes.String; + s.eclass = ExprClass.Value; + + s.Append (rc, left); + s.Append (rc, right); + return s; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Argument arg = arguments [0]; + return CreateExpressionAddCall (ec, arg, arg.CreateExpressionTree (ec), 1); + } + + // + // Creates nested calls tree from an array of arguments used for IL emit + // + Expression CreateExpressionAddCall (ResolveContext ec, Argument left, Expression left_etree, int pos) + { + Arguments concat_args = new Arguments (2); + Arguments add_args = new Arguments (3); + + concat_args.Add (left); + add_args.Add (new Argument (left_etree)); + + concat_args.Add (arguments [pos]); + add_args.Add (new Argument (arguments [pos].CreateExpressionTree (ec))); + + var methods = GetConcatMethodCandidates (); + if (methods == null) + return null; + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveMember (ec, ref concat_args); + if (method == null) + return null; + + add_args.Add (new Argument (new TypeOfMethod (method, loc))); + + Expression expr = CreateExpressionFactoryCall (ec, "Add", add_args); + if (++pos == arguments.Count) + return expr; + + left = new Argument (new EmptyExpression (method.ReturnType)); + return CreateExpressionAddCall (ec, left, expr, pos); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + void Append (ResolveContext rc, Expression operand) + { + // + // Constant folding + // + StringConstant sc = operand as StringConstant; + if (sc != null) { + if (arguments.Count != 0) { + Argument last_argument = arguments [arguments.Count - 1]; + StringConstant last_expr_constant = last_argument.Expr as StringConstant; + if (last_expr_constant != null) { + last_argument.Expr = new StringConstant (rc.BuiltinTypes, last_expr_constant.Value + sc.Value, sc.Location); + return; + } + } + } else { + // + // Multiple (3+) concatenation are resolved as multiple StringConcat instances + // + StringConcat concat_oper = operand as StringConcat; + if (concat_oper != null) { + arguments.AddRange (concat_oper.arguments); + return; + } + } + + arguments.Add (new Argument (operand)); + } + + IList GetConcatMethodCandidates () + { + return MemberCache.FindMembers (type, "Concat", true); + } + + public override void Emit (EmitContext ec) + { + var members = GetConcatMethodCandidates (); + var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveMember (new ResolveContext (ec.MemberContext), ref arguments); + if (method != null) + Invocation.EmitCall (ec, null, method, arguments, loc); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + if (arguments.Count != 2) + throw new NotImplementedException ("arguments.Count != 2"); + + var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) }); + return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat); + } + } + + // + // User-defined conditional logical operator + // + public class ConditionalLogicalOperator : UserOperatorCall { + readonly bool is_and; + Expression oper_expr; + + public ConditionalLogicalOperator (MethodSpec oper, Arguments arguments, Func expr_tree, bool is_and, Location loc) + : base (oper, arguments, expr_tree, loc) + { + this.is_and = is_and; + eclass = ExprClass.Unresolved; + } + + protected override Expression DoResolve (ResolveContext ec) + { + AParametersCollection pd = oper.Parameters; + if (!TypeSpecComparer.IsEqual (type, pd.Types[0]) || !TypeSpecComparer.IsEqual (type, pd.Types[1])) { + ec.Report.Error (217, loc, + "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator", + oper.GetSignatureForError ()); + return null; + } + + Expression left_dup = new EmptyExpression (type); + Expression op_true = GetOperatorTrue (ec, left_dup, loc); + Expression op_false = GetOperatorFalse (ec, left_dup, loc); + if (op_true == null || op_false == null) { + ec.Report.Error (218, loc, + "The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator", + TypeManager.CSharpName (type), oper.GetSignatureForError ()); + return null; + } + + oper_expr = is_and ? op_false : op_true; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + Label end_target = ec.DefineLabel (); + + // + // Emit and duplicate left argument + // + arguments [0].Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + arguments.RemoveAt (0); + + oper_expr.EmitBranchable (ec, end_target, true); + base.Emit (ec); + ec.MarkLabel (end_target); + } + } + + public class PointerArithmetic : Expression { + Expression left, right; + Binary.Operator op; + + // + // We assume that `l' is always a pointer + // + public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc) + { + type = t; + this.loc = loc; + left = l; + right = r; + this.op = op; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + + var pc = left.Type as PointerContainer; + if (pc != null && pc.Element.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + TypeSpec op_type = left.Type; + + // It must be either array or fixed buffer + TypeSpec element; + if (TypeManager.HasElementType (op_type)) { + element = TypeManager.GetElementType (op_type); + } else { + FieldExpr fe = left as FieldExpr; + if (fe != null) + element = ((FixedFieldSpec) (fe.Spec)).ElementType; + else + element = op_type; + } + + int size = BuiltinTypeSpec.GetSize(element); + TypeSpec rtype = right.Type; + + if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){ + // + // handle (pointer - pointer) + // + left.Emit (ec); + right.Emit (ec); + ec.Emit (OpCodes.Sub); + + if (size != 1){ + if (size == 0) + ec.Emit (OpCodes.Sizeof, element); + else + ec.EmitInt (size); + ec.Emit (OpCodes.Div); + } + ec.Emit (OpCodes.Conv_I8); + } else { + // + // handle + and - on (pointer op int) + // + Constant left_const = left as Constant; + if (left_const != null) { + // + // Optimize ((T*)null) pointer operations + // + if (left_const.IsDefaultValue) { + left = EmptyExpression.Null; + } else { + left_const = null; + } + } + + left.Emit (ec); + + var right_const = right as Constant; + if (right_const != null) { + // + // Optimize 0-based arithmetic + // + if (right_const.IsDefaultValue) + return; + + if (size != 0) + right = new IntConstant (ec.BuiltinTypes, size, right.Location); + else + right = new SizeOf (new TypeExpression (element, right.Location), right.Location); + + // TODO: Should be the checks resolve context sensitive? + ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope); + right = new Binary (Binary.Operator.Multiply, right, right_const, loc).Resolve (rc); + if (right == null) + return; + } + + right.Emit (ec); + switch (rtype.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + ec.Emit (OpCodes.Conv_I); + break; + case BuiltinTypeSpec.Type.UInt: + ec.Emit (OpCodes.Conv_U); + break; + } + + if (right_const == null && size != 1){ + if (size == 0) + ec.Emit (OpCodes.Sizeof, element); + else + ec.EmitInt (size); + if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long || rtype.BuiltinType == BuiltinTypeSpec.Type.ULong) + ec.Emit (OpCodes.Conv_I8); + + Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype); + } + + if (left_const == null) { + if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long) + ec.Emit (OpCodes.Conv_I); + else if (rtype.BuiltinType == BuiltinTypeSpec.Type.ULong) + ec.Emit (OpCodes.Conv_U); + + Binary.EmitOperatorOpcode (ec, op, op_type); + } + } + } + } + + // + // A boolean-expression is an expression that yields a result + // of type bool + // + public class BooleanExpression : ShimExpression + { + public BooleanExpression (Expression expr) + : base (expr) + { + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + // TODO: We should emit IsTrue (v4) instead of direct user operator + // call but that would break csc compatibility + return base.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // A boolean-expression is required to be of a type + // that can be implicitly converted to bool or of + // a type that implements operator true + + expr = expr.Resolve (ec); + if (expr == null) + return null; + + Assign ass = expr as Assign; + if (ass != null && ass.Source is Constant) { + ec.Report.Warning (665, 3, loc, + "Assignment in conditional expression is always constant. Did you mean to use `==' instead ?"); + } + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) + return expr; + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return DynamicUnaryConversion.CreateIsTrue (ec, args, loc).Resolve (ec); + } + + type = ec.BuiltinTypes.Bool; + Expression converted = Convert.ImplicitConversion (ec, expr, type, loc); + if (converted != null) + return converted; + + // + // If no implicit conversion to bool exists, try using `operator true' + // + converted = GetOperatorTrue (ec, expr, loc); + if (converted == null) { + expr.Error_ValueCannotBeConverted (ec, loc, type, false); + return null; + } + + return converted; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class BooleanExpressionFalse : Unary + { + public BooleanExpressionFalse (Expression expr) + : base (Operator.LogicalNot, expr, expr.Location) + { + } + + protected override Expression ResolveOperator (ResolveContext ec, Expression expr) + { + return GetOperatorFalse (ec, expr, loc) ?? base.ResolveOperator (ec, expr); + } + } + + /// + /// Implements the ternary conditional operator (?:) + /// + public class Conditional : Expression { + Expression expr, true_expr, false_expr; + + public Conditional (Expression expr, Expression true_expr, Expression false_expr, Location loc) + { + this.expr = expr; + this.true_expr = true_expr; + this.false_expr = false_expr; + this.loc = loc; + } + + public Expression Expr { + get { + return expr; + } + } + + public Expression TrueExpr { + get { + return true_expr; + } + } + + public Expression FalseExpr { + get { + return false_expr; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (3); + args.Add (new Argument (expr.CreateExpressionTree (ec))); + args.Add (new Argument (true_expr.CreateExpressionTree (ec))); + args.Add (new Argument (false_expr.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "Condition", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + true_expr = true_expr.Resolve (ec); + false_expr = false_expr.Resolve (ec); + + if (true_expr == null || false_expr == null || expr == null) + return null; + + eclass = ExprClass.Value; + TypeSpec true_type = true_expr.Type; + TypeSpec false_type = false_expr.Type; + type = true_type; + + // + // First, if an implicit conversion exists from true_expr + // to false_expr, then the result type is of type false_expr.Type + // + if (!TypeSpecComparer.IsEqual (true_type, false_type)) { + Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc); + if (conv != null && true_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) { + // + // Check if both can convert implicitly to each other's type + // + type = false_type; + + if (false_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) { + ec.Report.Error (172, true_expr.Location, + "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other", + true_type.GetSignatureForError (), false_type.GetSignatureForError ()); + return null; + } + + true_expr = conv; + } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) { + false_expr = conv; + } else { + ec.Report.Error (173, true_expr.Location, + "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'", + TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type)); + return null; + } + } + + // Dead code optimalization + Constant c = expr as Constant; + if (c != null){ + bool is_false = c.IsDefaultValue; + ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected"); + return ReducedExpression.Create ( + is_false ? false_expr : true_expr, this, + false_expr is Constant && true_expr is Constant).Resolve (ec); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + Label false_target = ec.DefineLabel (); + Label end_target = ec.DefineLabel (); + + expr.EmitBranchable (ec, false_target, false); + true_expr.Emit (ec); + + if (type.IsInterface) { + LocalBuilder temp = ec.GetTemporaryLocal (type); + ec.Emit (OpCodes.Stloc, temp); + ec.Emit (OpCodes.Ldloc, temp); + ec.FreeTemporaryLocal (temp, type); + } + + ec.Emit (OpCodes.Br, end_target); + ec.MarkLabel (false_target); + false_expr.Emit (ec); + ec.MarkLabel (end_target); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Conditional target = (Conditional) t; + + target.expr = expr.Clone (clonectx); + target.true_expr = true_expr.Clone (clonectx); + target.false_expr = false_expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference { + LocalTemporary temp; + + #region Abstract + public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae); + + public abstract bool IsLockedByStatement { get; set; } + + public abstract bool IsFixed { get; } + public abstract bool IsRef { get; } + public abstract string Name { get; } + public abstract void SetHasAddressTaken (); + + // + // Variable IL data, it has to be protected to encapsulate hoisted variables + // + protected abstract ILocalVariable Variable { get; } + + // + // Variable flow-analysis data + // + public abstract VariableInfo VariableInfo { get; } + #endregion + + public virtual void AddressOf (EmitContext ec, AddressOp mode) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.AddressOf (ec, mode); + return; + } + + Variable.EmitAddressOf (ec); + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (IsLockedByStatement) { + rc.Report.Warning (728, 2, loc, + "Possibly incorrect assignment to `{0}' which is the argument to a using or lock statement", + Name); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitSideEffect (EmitContext ec) + { + // do nothing + } + + // + // This method is used by parameters that are references, that are + // being passed as references: we only want to pass the pointer (that + // is already stored in the parameter, not the address of the pointer, + // and not the value of the variable). + // + public void EmitLoad (EmitContext ec) + { + Variable.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.Emit (ec, leave_copy); + return; + } + + EmitLoad (ec); + + if (IsRef) { + // + // If we are a reference, we loaded on the stack a pointer + // Now lets load the real value + // + ec.EmitLoadFromPtr (type); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + + if (IsRef) { + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, + bool prepare_for_load) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.EmitAssign (ec, source, leave_copy, prepare_for_load); + return; + } + + New n_source = source as New; + if (n_source != null) { + if (!n_source.Emit (ec, this)) { + if (leave_copy) { + EmitLoad (ec); + if (IsRef) + ec.EmitLoadFromPtr (type); + } + return; + } + } else { + if (IsRef) + EmitLoad (ec); + + source.Emit (ec); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (IsRef) { + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + + if (IsRef) + ec.EmitStoreFromPtr (type); + else + Variable.EmitAssign (ec); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + + public HoistedVariable GetHoistedVariable (ResolveContext rc) + { + return GetHoistedVariable (rc.CurrentAnonymousMethod); + } + + public HoistedVariable GetHoistedVariable (EmitContext ec) + { + return GetHoistedVariable (ec.CurrentAnonymousMethod); + } + + public override string GetSignatureForError () + { + return Name; + } + + public bool IsHoisted { + get { return GetHoistedVariable ((AnonymousExpression) null) != null; } + } + } + + // + // Resolved reference to a local variable + // + public class LocalVariableReference : VariableReference + { + public LocalVariable local_info; + + public LocalVariableReference (LocalVariable li, Location l) + { + this.local_info = li; + loc = l; + } + + public override VariableInfo VariableInfo { + get { return local_info.VariableInfo; } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return local_info.HoistedVariant; + } + + #region Properties + + // + // A local variable is always fixed + // + public override bool IsFixed { + get { + return true; + } + } + + public override bool IsLockedByStatement { + get { + return local_info.IsLocked; + } + set { + local_info.IsLocked = value; + } + } + + public override bool IsRef { + get { return false; } + } + + public override string Name { + get { return local_info.Name; } + } + + #endregion + + public bool VerifyAssigned (ResolveContext ec) + { + VariableInfo variable_info = local_info.VariableInfo; + return variable_info == null || variable_info.IsAssigned (ec, loc); + } + + public override void SetHasAddressTaken () + { + local_info.AddressTaken = true; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (); + + Arguments arg = new Arguments (1); + arg.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", arg); + } + + void DoResolveBase (ResolveContext ec) + { + VerifyAssigned (ec); + + // + // If we are referencing a variable from the external block + // flag it for capturing + // + if (ec.MustCaptureVariable (local_info)) { + if (local_info.AddressTaken) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc); + } else if (local_info.IsFixed) { + ec.Report.Error (1764, loc, + "Cannot use fixed local `{0}' inside an anonymous method, lambda expression or query expression", + GetSignatureForError ()); + } + + if (ec.IsVariableCapturingRequired) { + AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureLocalVariable (ec, local_info); + } + } + + eclass = ExprClass.Variable; + type = local_info.Type; + } + + protected override Expression DoResolve (ResolveContext ec) + { + local_info.SetIsUsed (); + + DoResolveBase (ec); + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + // is out param + if (right_side == EmptyExpression.OutAccess) + local_info.SetIsUsed (); + + if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) { + int code; + string msg; + if (right_side == EmptyExpression.OutAccess) { + code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberAccess) { + code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberOutAccess) { + code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'"; + } else if (right_side == EmptyExpression.UnaryAddress) { + code = 459; msg = "Cannot take the address of {1} `{0}'"; + } else { + code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'"; + } + ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ()); + } else if (VariableInfo != null) { + VariableInfo.SetAssigned (ec); + } + + DoResolveBase (ec); + + return base.DoResolveLValue (ec, right_side); + } + + public override int GetHashCode () + { + return local_info.GetHashCode (); + } + + public override bool Equals (object obj) + { + LocalVariableReference lvr = obj as LocalVariableReference; + if (lvr == null) + return false; + + return local_info == lvr.local_info; + } + + protected override ILocalVariable Variable { + get { return local_info; } + } + + public override string ToString () + { + return String.Format ("{0} ({1}:{2})", GetType (), Name, loc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This represents a reference to a parameter in the intermediate + /// representation. + /// + public class ParameterReference : VariableReference + { + protected ParametersBlock.ParameterInfo pi; + + public ParameterReference (ParametersBlock.ParameterInfo pi, Location loc) + { + this.pi = pi; + this.loc = loc; + } + + #region Properties + + public override bool IsLockedByStatement { + get { + return pi.IsLocked; + } + set { + pi.IsLocked = value; + } + } + + public override bool IsRef { + get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; } + } + + bool HasOutModifier { + get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return pi.Parameter.HoistedVariant; + } + + // + // A ref or out parameter is classified as a moveable variable, even + // if the argument given for the parameter is a fixed variable + // + public override bool IsFixed { + get { return !IsRef; } + } + + public override string Name { + get { return Parameter.Name; } + } + + public Parameter Parameter { + get { return pi.Parameter; } + } + + public override VariableInfo VariableInfo { + get { return pi.VariableInfo; } + } + + protected override ILocalVariable Variable { + get { return Parameter; } + } + + #endregion + + public bool IsAssigned (ResolveContext ec, Location loc) + { + // HACK: Variables are not captured in probing mode + if (ec.IsInProbingMode) + return true; + + if (!ec.DoFlowAnalysis || !HasOutModifier || ec.CurrentBranching.IsAssigned (VariableInfo)) + return true; + + ec.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name); + return false; + } + + public override void SetHasAddressTaken () + { + Parameter.HasAddressTaken = true; + } + + void SetAssigned (ResolveContext ec) + { + if (HasOutModifier && ec.DoFlowAnalysis) + ec.CurrentBranching.SetAssigned (VariableInfo); + } + + bool DoResolveBase (ResolveContext ec) + { + if (eclass != ExprClass.Unresolved) + return true; + + type = pi.ParameterType; + eclass = ExprClass.Variable; + + // + // If we are referencing a parameter from the external block + // flag it for capturing + // + if (ec.MustCaptureVariable (pi)) { + if (Parameter.HasAddressTaken) + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc); + + if (IsRef) { + ec.Report.Error (1628, loc, + "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier", + Name, ec.CurrentAnonymousMethod.ContainerType); + } + + if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) { + AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureParameter (ec, this); + } + } + + return true; + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + public override bool Equals (object obj) + { + ParameterReference pr = obj as ParameterReference; + if (pr == null) + return false; + + return Name == pr.Name; + } + + public override void AddressOf (EmitContext ec, AddressOp mode) + { + // + // ParameterReferences might already be a reference + // + if (IsRef) { + EmitLoad (ec); + return; + } + + base.AddressOf (ec, mode); + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // Nothing to clone + return; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (); + + return Parameter.ExpressionTreeVariableReference (); + } + + // + // Notice that for ref/out parameters, the type exposed is not the + // same type exposed externally. + // + // for "ref int a": + // externally we expose "int&" + // here we expose "int". + // + // We record this in "is_ref". This means that the type system can treat + // the type as it is expected, but when we generate the code, we generate + // the alternate kind of code. + // + protected override Expression DoResolve (ResolveContext ec) + { + if (!DoResolveBase (ec)) + return null; + + // HACK: Variables are not captured in probing mode + if (ec.IsInProbingMode) + return this; + + if (HasOutModifier && ec.DoFlowAnalysis && + (!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc)) + return null; + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (!DoResolveBase (ec)) + return null; + + SetAssigned (ec); + return base.DoResolveLValue (ec, right_side); + } + + static public void EmitLdArg (EmitContext ec, int x) + { + switch (x) { + case 0: ec.Emit (OpCodes.Ldarg_0); break; + case 1: ec.Emit (OpCodes.Ldarg_1); break; + case 2: ec.Emit (OpCodes.Ldarg_2); break; + case 3: ec.Emit (OpCodes.Ldarg_3); break; + default: + if (x > byte.MaxValue) + ec.Emit (OpCodes.Ldarg, x); + else + ec.Emit (OpCodes.Ldarg_S, (byte) x); + break; + } + } + } + + /// + /// Invocation of methods or delegates. + /// + public class Invocation : ExpressionStatement + { + protected Arguments arguments; + protected Expression expr; + protected MethodGroupExpr mg; + + // + // arguments is an ArrayList, but we do not want to typecast, + // as it might be null. + // + public Invocation (Expression expr, Arguments arguments) + { + this.expr = expr; + this.arguments = arguments; + if (expr != null) + loc = expr.Location; + } + + #region Properties + public Arguments Arguments { + get { + return arguments; + } + } + + public Expression Expression { + get { + return expr; + } + } + #endregion + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Invocation target = (Invocation) t; + + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + + target.expr = expr.Clone (clonectx); + } + + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Expression instance = mg.IsInstance ? + mg.InstanceExpression.CreateExpressionTree (ec) : + new NullLiteral (loc); + + var args = Arguments.CreateForExpressionTree (ec, arguments, + instance, + mg.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression member_expr; + var atn = expr as ATypeNameExpression; + if (atn != null) { + member_expr = atn.LookupNameExpression (ec, MemberLookupRestrictions.InvocableOnly | MemberLookupRestrictions.ReadAccess); + if (member_expr != null) + member_expr = member_expr.Resolve (ec); + } else { + member_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + } + + if (member_expr == null) + return null; + + // + // Next, evaluate all the expressions in the argument list + // + bool dynamic_arg = false; + if (arguments != null) + arguments.Resolve (ec, out dynamic_arg); + + TypeSpec expr_type = member_expr.Type; + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return DoResolveDynamic (ec, member_expr); + + mg = member_expr as MethodGroupExpr; + Expression invoke = null; + + if (mg == null) { + if (expr_type != null && TypeManager.IsDelegateType (expr_type)) { + invoke = new DelegateInvocation (member_expr, arguments, loc); + invoke = invoke.Resolve (ec); + if (invoke == null || !dynamic_arg) + return invoke; + } else { + if (member_expr is RuntimeValueExpression) { + ec.Report.Error (Report.RuntimeErrorId, loc, "Cannot invoke a non-delegate type `{0}'", + member_expr.Type.GetSignatureForError ()); ; + return null; + } + + MemberExpr me = member_expr as MemberExpr; + if (me == null) { + member_expr.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc); + return null; + } + + ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate", + member_expr.GetSignatureForError ()); + return null; + } + } + + if (invoke == null) { + mg = DoResolveOverload (ec); + if (mg == null) + return null; + } + + if (dynamic_arg) + return DoResolveDynamic (ec, member_expr); + + var method = mg.BestCandidate; + type = mg.BestCandidateReturnType; + + if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) { + if (mg.IsBase) + ec.Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor"); + else + ec.Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available"); + return null; + } + + IsSpecialMethodInvocation (ec, method, loc); + + eclass = ExprClass.Value; + return this; + } + + protected virtual Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr) + { + Arguments args; + DynamicMemberBinder dmb = memberExpr as DynamicMemberBinder; + if (dmb != null) { + args = dmb.Arguments; + if (arguments != null) + args.AddRange (arguments); + } else if (mg == null) { + if (arguments == null) + args = new Arguments (1); + else + args = arguments; + + args.Insert (0, new Argument (memberExpr)); + this.expr = null; + } else { + if (mg.IsBase) { + ec.Report.Error (1971, loc, + "The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access", + mg.Name); + return null; + } + + if (arguments == null) + args = new Arguments (1); + else + args = arguments; + + MemberAccess ma = expr as MemberAccess; + if (ma != null) { + var left_type = ma.LeftExpression as TypeExpr; + if (left_type != null) { + args.Insert (0, new Argument (new TypeOf (left_type.Type, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + } else { + // + // Any value type has to be pass as by-ref to get back the same + // instance on which the member was called + // + var mod = TypeSpec.IsValueType (ma.LeftExpression.Type) ? Argument.AType.Ref : Argument.AType.None; + args.Insert (0, new Argument (ma.LeftExpression.Resolve (ec), mod)); + } + } else { // is SimpleName + if (ec.IsStatic) { + args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + } else { + args.Insert (0, new Argument (new This (loc).Resolve (ec))); + } + } + } + + return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec); + } + + protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec) + { + return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None); + } + + static MetaType[] GetVarargsTypes (MethodSpec mb, Arguments arguments) + { + AParametersCollection pd = mb.Parameters; + + Argument a = arguments[pd.Count - 1]; + Arglist list = (Arglist) a.Expr; + + return list.ArgumentTypes; + } + + // + // If a member is a method or event, or if it is a constant, field or property of either a delegate type + // or the type dynamic, then the member is invocable + // + public static bool IsMemberInvocable (MemberSpec member) + { + switch (member.Kind) { + case MemberKind.Event: + return true; + case MemberKind.Field: + case MemberKind.Property: + var m = member as IInterfaceMemberSpec; + return m.MemberType.IsDelegate || m.MemberType.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + default: + return false; + } + } + + public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc) + { + if (!method.IsReservedMethod) + return false; + + if (ec.HasSet (ResolveContext.Options.InvokeSpecialName) || ec.CurrentMemberDefinition.IsCompilerGenerated) + return false; + + ec.Report.SymbolRelatedToPreviousError (method); + ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor", + method.GetSignatureForError ()); + + return true; + } + + // + // Used to decide whether call or callvirt is needed + // + static bool IsVirtualCallRequired (Expression instance, MethodSpec method) + { + // + // There are 2 scenarious where we emit callvirt + // + // Case 1: A method is virtual and it's not used to call base + // Case 2: A method instance expression can be null. In this casen callvirt ensures + // correct NRE exception when the method is called + // + var decl_type = method.DeclaringType; + if (decl_type.IsStruct || decl_type.IsEnum) + return false; + + if (instance is BaseThis) + return false; + + // + // It's non-virtual and will never be null + // + if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation)) + return false; + + return true; + } + + /// + /// is_base tells whether we want to force the use of the `call' + /// opcode instead of using callvirt. Call is required to call + /// a specific method, while callvirt will always use the most + /// recent method in the vtable. + /// + /// is_static tells whether this is an invocation on a static method + /// + /// instance_expr is an expression that represents the instance + /// it must be non-null if is_static is false. + /// + /// method is the method to invoke. + /// + /// Arguments is the list of arguments to pass to the method or constructor. + /// + public static void EmitCall (EmitContext ec, Expression instance_expr, + MethodSpec method, Arguments Arguments, Location loc) + { + EmitCall (ec, instance_expr, method, Arguments, loc, false, false); + } + + // `dup_args' leaves an extra copy of the arguments on the stack + // `omit_args' does not leave any arguments at all. + // So, basically, you could make one call with `dup_args' set to true, + // and then another with `omit_args' set to true, and the two calls + // would have the same set of arguments. However, each argument would + // only have been evaluated once. + public static void EmitCall (EmitContext ec, Expression instance_expr, + MethodSpec method, Arguments Arguments, Location loc, + bool dup_args, bool omit_args) + { + LocalTemporary this_arg = null; + + // Speed up the check by not doing it on not allowed targets + if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.Module.Compiler, loc)) + return; + + OpCode call_op; + TypeSpec iexpr_type; + + if (method.IsStatic) { + iexpr_type = null; + call_op = OpCodes.Call; + } else { + iexpr_type = instance_expr.Type; + + if (IsVirtualCallRequired (instance_expr, method)) { + call_op = OpCodes.Callvirt; + } else { + call_op = OpCodes.Call; + } + + // + // If this is ourselves, push "this" + // + if (!omit_args) { + TypeSpec t = iexpr_type; + + // + // Push the instance expression + // + if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && method.DeclaringType == iexpr_type))) || + iexpr_type.IsGenericParameter || method.DeclaringType.IsNullableType) { + // + // If the expression implements IMemoryLocation, then + // we can optimize and use AddressOf on the + // return. + // + // If not we have to use some temporary storage for + // it. + var iml = instance_expr as IMemoryLocation; + if (iml != null) { + iml.AddressOf (ec, AddressOp.Load); + } else { + LocalTemporary temp = new LocalTemporary (iexpr_type); + instance_expr.Emit (ec); + temp.Store (ec); + temp.AddressOf (ec, AddressOp.Load); + } + + // avoid the overhead of doing this all the time. + if (dup_args) + t = ReferenceContainer.MakeType (ec.Module, iexpr_type); + } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) { + instance_expr.Emit (ec); + ec.Emit (OpCodes.Box, iexpr_type); + t = iexpr_type = ec.BuiltinTypes.Object; + } else { + instance_expr.Emit (ec); + } + + if (dup_args) { + ec.Emit (OpCodes.Dup); + if (Arguments != null && Arguments.Count != 0) { + this_arg = new LocalTemporary (t); + this_arg.Store (ec); + } + } + } + } + + if (!omit_args && Arguments != null) { + var dup_arg_exprs = Arguments.Emit (ec, dup_args); + if (dup_args) { + this_arg.Emit (ec); + LocalTemporary lt; + foreach (var dup in dup_arg_exprs) { + dup.Emit (ec); + lt = dup as LocalTemporary; + if (lt != null) + lt.Release (ec); + } + } + } + + if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) { + ec.Emit (OpCodes.Constrained, iexpr_type); + } + + if (method.Parameters.HasArglist) { + var varargs_types = GetVarargsTypes (method, Arguments); + ec.Emit (call_op, method, varargs_types); + return; + } + + // + // If you have: + // this.DoFoo (); + // and DoFoo is not virtual, you can omit the callvirt, + // because you don't need the null checking behavior. + // + ec.Emit (call_op, method); + } + + public override void Emit (EmitContext ec) + { + mg.EmitCall (ec, arguments); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + + // + // Pop the return value if there is one + // + if (type.Kind != MemberKind.Void) + ec.Emit (OpCodes.Pop); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return MakeExpression (ctx, mg.InstanceExpression, mg.BestCandidate, arguments); + } + + public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args) + { +#if STATIC + throw new NotSupportedException (); +#else + var instance_expr = instance == null ? null : instance.MakeExpression (ctx); + return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx)); +#endif + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Implements simple new expression + // + public class New : ExpressionStatement, IMemoryLocation + { + protected Arguments arguments; + + // + // During bootstrap, it contains the RequestedType, + // but if `type' is not null, it *might* contain a NewDelegate + // (because of field multi-initialization) + // + protected Expression RequestedType; + + protected MethodSpec method; + + public New (Expression requested_type, Arguments arguments, Location l) + { + RequestedType = requested_type; + this.arguments = arguments; + loc = l; + } + + #region Properties + public Arguments Arguments { + get { + return arguments; + } + } + + public Expression TypeRequested { + get { + return RequestedType; + } + } + + // + // Returns true for resolved `new S()' + // + public bool IsDefaultStruct { + get { + return arguments == null && type.IsStruct && GetType () == typeof (New); + } + } + + #endregion + + /// + /// Converts complex core type syntax like 'new int ()' to simple constant + /// + public static Constant Constantify (TypeSpec t, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return new IntConstant (t, 0, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (t, 0, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (t, 0, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (t, 0, loc); + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (t, '\0', loc); + case BuiltinTypeSpec.Type.Bool: + return new BoolConstant (t, false, loc); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (t, 0, loc); + } + + if (t.IsEnum) + return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t), loc), t); + + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); + + return null; + } + + // + // Checks whether the type is an interface that has the + // [ComImport, CoClass] attributes and must be treated + // specially + // + public Expression CheckComImport (ResolveContext ec) + { + if (!type.IsInterface) + return null; + + // + // Turn the call into: + // (the-interface-stated) (new class-referenced-in-coclassattribute ()) + // + var real_class = type.MemberDefinition.GetAttributeCoClass (); + if (real_class == null) + return null; + + New proxy = new New (new TypeExpression (real_class, loc), arguments, loc); + Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc); + return cast.Resolve (ec); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + if (method == null) { + args = new Arguments (1); + args.Add (new Argument (new TypeOf (type, loc))); + } else { + args = Arguments.CreateForExpressionTree (ec, + arguments, new TypeOfMethod (method, loc)); + } + + return CreateExpressionFactoryCall (ec, "New", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = RequestedType.ResolveAsType (ec); + if (type == null) + return null; + + eclass = ExprClass.Value; + + if (type.IsPointer) { + ec.Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression", + TypeManager.CSharpName (type)); + return null; + } + + if (arguments == null) { + Constant c = Constantify (type, RequestedType.Location); + if (c != null) + return ReducedExpression.Create (c, this); + } + + if (TypeManager.IsDelegateType (type)) { + return (new NewDelegate (type, arguments, loc)).Resolve (ec); + } + + var tparam = type as TypeParameterSpec; + if (tparam != null) { + // + // Check whether the type of type parameter can be constructed. BaseType can be a struct for method overrides + // where type parameter constraint is inflated to struct + // + if ((tparam.SpecialConstraint & (SpecialConstraint.Struct | SpecialConstraint.Constructor)) == 0 && !tparam.BaseType.IsStruct) { + ec.Report.Error (304, loc, + "Cannot create an instance of the variable type `{0}' because it does not have the new() constraint", + TypeManager.CSharpName (type)); + } + + if ((arguments != null) && (arguments.Count != 0)) { + ec.Report.Error (417, loc, + "`{0}': cannot provide arguments when creating an instance of a variable type", + TypeManager.CSharpName (type)); + } + + return this; + } + + if (type.IsStatic) { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type)); + return null; + } + + if (type.IsInterface || type.IsAbstract){ + if (!TypeManager.IsGenericType (type)) { + RequestedType = CheckComImport (ec); + if (RequestedType != null) + return RequestedType; + } + + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type)); + return null; + } + + // + // Any struct always defines parameterless constructor + // + if (type.IsStruct && arguments == null) + return this; + + bool dynamic; + if (arguments != null) { + arguments.Resolve (ec, out dynamic); + } else { + dynamic = false; + } + + method = ConstructorLookup (ec, type, ref arguments, loc); + + if (dynamic) { + arguments.Insert (0, new Argument (new TypeOf (type, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + return new DynamicConstructorBinder (type, arguments, loc).Resolve (ec); + } + + return this; + } + + bool DoEmitTypeParameter (EmitContext ec) + { + var m = ec.Module.PredefinedMembers.ActivatorCreateInstance.Resolve (loc); + if (m == null) + return true; + + var ctor_factory = m.MakeGenericMethod (ec.MemberContext, type); + var tparam = (TypeParameterSpec) type; + + if (tparam.IsReferenceType) { + ec.Emit (OpCodes.Call, ctor_factory); + return true; + } + + // Allow DoEmit() to be called multiple times. + // We need to create a new LocalTemporary each time since + // you can't share LocalBuilders among ILGeneators. + LocalTemporary temp = new LocalTemporary (type); + + Label label_activator = ec.DefineLabel (); + Label label_end = ec.DefineLabel (); + + temp.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + + temp.Emit (ec); + ec.Emit (OpCodes.Box, type); + ec.Emit (OpCodes.Brfalse, label_activator); + + temp.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + temp.Emit (ec); + ec.Emit (OpCodes.Br_S, label_end); + + ec.MarkLabel (label_activator); + + ec.Emit (OpCodes.Call, ctor_factory); + ec.MarkLabel (label_end); + return true; + } + + // + // This Emit can be invoked in two contexts: + // * As a mechanism that will leave a value on the stack (new object) + // * As one that wont (init struct) + // + // If we are dealing with a ValueType, we have a few + // situations to deal with: + // + // * The target is a ValueType, and we have been provided + // the instance (this is easy, we are being assigned). + // + // * The target of New is being passed as an argument, + // to a boxing operation or a function that takes a + // ValueType. + // + // In this case, we need to create a temporary variable + // that is the argument of New. + // + // Returns whether a value is left on the stack + // + // *** Implementation note *** + // + // To benefit from this optimization, each assignable expression + // has to manually cast to New and call this Emit. + // + // TODO: It's worth to implement it for arrays and fields + // + public virtual bool Emit (EmitContext ec, IMemoryLocation target) + { + bool is_value_type = TypeSpec.IsValueType (type); + VariableReference vr = target as VariableReference; + + if (target != null && is_value_type && (vr != null || method == null)) { + target.AddressOf (ec, AddressOp.Store); + } else if (vr != null && vr.IsRef) { + vr.EmitLoad (ec); + } + + if (arguments != null) + arguments.Emit (ec); + + if (is_value_type) { + if (method == null) { + ec.Emit (OpCodes.Initobj, type); + return false; + } + + if (vr != null) { + ec.Emit (OpCodes.Call, method); + return false; + } + } + + if (type is TypeParameterSpec) + return DoEmitTypeParameter (ec); + + ec.Emit (OpCodes.Newobj, method); + return true; + } + + public override void Emit (EmitContext ec) + { + LocalTemporary v = null; + if (method == null && TypeSpec.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } + + if (!Emit (ec, v)) + v.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + LocalTemporary v = null; + if (method == null && TypeSpec.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } + + if (Emit (ec, v)) + ec.Emit (OpCodes.Pop); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + EmitAddressOf (ec, mode); + } + + protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode) + { + LocalTemporary value_target = new LocalTemporary (type); + + if (type is TypeParameterSpec) { + DoEmitTypeParameter (ec); + value_target.Store (ec); + value_target.AddressOf (ec, mode); + return value_target; + } + + value_target.AddressOf (ec, AddressOp.Store); + + if (method == null) { + ec.Emit (OpCodes.Initobj, type); + } else { + if (arguments != null) + arguments.Emit (ec); + + ec.Emit (OpCodes.Call, method); + } + + value_target.AddressOf (ec, mode); + return value_target; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + New target = (New) t; + + target.RequestedType = RequestedType.Clone (clonectx); + if (arguments != null){ + target.arguments = arguments.Clone (clonectx); + } + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx)); +#endif + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Array initializer expression, the expression is allowed in + // variable or field initialization only which makes it tricky as + // the type has to be infered based on the context either from field + // type or variable type (think of multiple declarators) + // + public class ArrayInitializer : Expression + { + List elements; + BlockVariableDeclaration variable; + + public ArrayInitializer (List init, Location loc) + { + elements = init; + this.loc = loc; + } + + public ArrayInitializer (int count, Location loc) + : this (new List (count), loc) + { + } + + public ArrayInitializer (Location loc) + : this (4, loc) + { + } + + #region Properties + + public int Count { + get { return elements.Count; } + } + + public Expression this [int index] { + get { + return elements [index]; + } + } + + public BlockVariableDeclaration VariableDeclaration { + get { + return variable; + } + set { + variable = value; + } + } + + public List Elements { + get { + return this.elements; + } + } + #endregion + + public void Add (Expression expr) + { + elements.Add (expr); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + var target = (ArrayInitializer) t; + + target.elements = new List (elements.Count); + foreach (var element in elements) + target.elements.Add (element.Clone (clonectx)); + } + + protected override Expression DoResolve (ResolveContext rc) + { + var current_field = rc.CurrentMemberDefinition as FieldBase; + TypeExpression type; + if (current_field != null) { + type = new TypeExpression (current_field.MemberType, current_field.Location); + } else if (variable != null) { + if (variable.TypeExpression is VarExpr) { + rc.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer"); + return EmptyExpression.Null; + } + + type = new TypeExpression (variable.Variable.Type, variable.Variable.Location); + } else { + throw new NotImplementedException ("Unexpected array initializer context"); + } + + return new ArrayCreation (type, this).Resolve (rc); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// 14.5.10.2: Represents an array creation expression. + /// + /// + /// + /// There are two possible scenarios here: one is an array creation + /// expression that specifies the dimensions and optionally the + /// initialization data and the other which does not need dimensions + /// specified but where initialization data is mandatory. + /// + public class ArrayCreation : Expression + { + FullNamedExpression requested_base_type; + ArrayInitializer initializers; + + // + // The list of Argument types. + // This is used to construct the `newarray' or constructor signature + // + protected List arguments; + + protected TypeSpec array_element_type; + int num_arguments = 0; + protected int dimensions; + protected readonly ComposedTypeSpecifier rank; + Expression first_emit; + LocalTemporary first_emit_temp; + + protected List array_data; + + Dictionary bounds; + + // The number of constants in array initializers + int const_initializers_count; + bool only_constant_initializers; + + public List Arguments { + get { return this.arguments; } + } + + public ComposedTypeSpecifier Rank { + get { return this.rank; } + } + + public FullNamedExpression NewType { + get { return this.requested_base_type; } + } + + public ArrayInitializer Initializers { + get { return this.initializers; } + } + + public ArrayCreation (FullNamedExpression requested_base_type, List exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l) + : this (requested_base_type, rank, initializers, l) + { + arguments = exprs; + num_arguments = arguments.Count; + } + + // + // For expressions like int[] foo = new int[] { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) + { + this.requested_base_type = requested_base_type; + this.rank = rank; + this.initializers = initializers; + this.loc = loc; + + if (rank != null) + num_arguments = rank.Dimension; + } + + // + // For compiler generated single dimensional arrays only + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc) + : this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc) + { + } + + // + // For expressions like int[] foo = { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers) + : this (requested_base_type, null, initializers, initializers.Location) + { + } + + protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + ec.Report.Error (248, loc, "Cannot create an array with a negative size"); + } + + bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) + { + if (initializers != null && bounds == null) { + // + // We use this to store all the date values in the order in which we + // will need to store them in the byte blob later + // + array_data = new List (); + bounds = new Dictionary (); + } + + if (specified_dims) { + Expression a = arguments [idx]; + a = a.Resolve (ec); + if (a == null) + return false; + + a = ConvertExpressionToArrayIndex (ec, a); + if (a == null) + return false; + + arguments[idx] = a; + + if (initializers != null) { + Constant c = a as Constant; + if (c == null && a is ArrayIndexCast) + c = ((ArrayIndexCast) a).Child as Constant; + + if (c == null) { + ec.Report.Error (150, a.Location, "A constant value is expected"); + return false; + } + + int value; + try { + value = System.Convert.ToInt32 (c.GetValue ()); + } catch { + ec.Report.Error (150, a.Location, "A constant value is expected"); + return false; + } + + // TODO: probe.Count does not fit ulong in + if (value != probe.Count) { + ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ()); + return false; + } + + bounds[idx] = value; + } + } + + if (initializers == null) + return true; + + for (int i = 0; i < probe.Count; ++i) { + var o = probe [i]; + if (o is ArrayInitializer) { + var sub_probe = o as ArrayInitializer; + if (idx + 1 >= dimensions){ + ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); + return false; + } + + bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); + if (!ret) + return false; + } else if (child_bounds > 1) { + ec.Report.Error (846, o.Location, "A nested array initializer was expected"); + } else { + Expression element = ResolveArrayElement (ec, o); + if (element == null) + continue; + + // Initializers with the default values can be ignored + Constant c = element as Constant; + if (c != null) { + if (!c.IsDefaultInitializer (array_element_type)) { + ++const_initializers_count; + } + } else { + only_constant_initializers = false; + } + + array_data.Add (element); + } + } + + return true; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + + if (array_data == null) { + args = new Arguments (arguments.Count + 1); + args.Add (new Argument (new TypeOf (array_element_type, loc))); + foreach (Expression a in arguments) + args.Add (new Argument (a.CreateExpressionTree (ec))); + + return CreateExpressionFactoryCall (ec, "NewArrayBounds", args); + } + + if (dimensions > 1) { + ec.Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer"); + return null; + } + + args = new Arguments (array_data == null ? 1 : array_data.Count + 1); + args.Add (new Argument (new TypeOf (array_element_type, loc))); + if (array_data != null) { + for (int i = 0; i < array_data.Count; ++i) { + Expression e = array_data [i]; + args.Add (new Argument (e.CreateExpressionTree (ec))); + } + } + + return CreateExpressionFactoryCall (ec, "NewArrayInit", args); + } + + void UpdateIndices (ResolveContext rc) + { + int i = 0; + for (var probe = initializers; probe != null;) { + Expression e = new IntConstant (rc.BuiltinTypes, probe.Count, Location.Null); + arguments.Add (e); + bounds[i++] = probe.Count; + + if (probe.Count > 0 && probe [0] is ArrayInitializer) { + probe = (ArrayInitializer) probe[0]; + } else if (dimensions > i) { + continue; + } else { + return; + } + } + } + + protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element) + { + element = element.Resolve (ec); + if (element == null) + return null; + + if (element is CompoundAssign.TargetExpression) { + if (first_emit != null) + throw new InternalErrorException ("Can only handle one mutator at a time"); + first_emit = element; + element = first_emit_temp = new LocalTemporary (element.Type); + } + + return Convert.ImplicitConversionRequired ( + ec, element, array_element_type, loc); + } + + protected bool ResolveInitializers (ResolveContext ec) + { + only_constant_initializers = true; + + if (arguments != null) { + bool res = true; + for (int i = 0; i < arguments.Count; ++i) { + res &= CheckIndices (ec, initializers, i, true, dimensions); + if (initializers != null) + break; + } + + return res; + } + + arguments = new List (); + + if (!CheckIndices (ec, initializers, 0, false, dimensions)) + return false; + + UpdateIndices (ec); + + return true; + } + + // + // Resolved the type of the array + // + bool ResolveArrayType (ResolveContext ec) + { + // + // Lookup the type + // + FullNamedExpression array_type_expr; + if (num_arguments > 0) { + array_type_expr = new ComposedCast (requested_base_type, rank); + } else { + array_type_expr = requested_base_type; + } + + type = array_type_expr.ResolveAsType (ec); + if (array_type_expr == null) + return false; + + var ac = type as ArrayContainer; + if (ac == null) { + ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead"); + return false; + } + + array_element_type = ac.Element; + dimensions = ac.Rank; + + return true; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (type != null) + return this; + + if (!ResolveArrayType (ec)) + return null; + + // + // validate the initializers and fill in any missing bits + // + if (!ResolveInitializers (ec)) + return null; + + eclass = ExprClass.Value; + return this; + } + + byte [] MakeByteBlob () + { + int factor; + byte [] data; + byte [] element; + int count = array_data.Count; + + TypeSpec element_type = array_element_type; + if (TypeManager.IsEnumType (element_type)) + element_type = EnumSpec.GetUnderlyingType (element_type); + + factor = BuiltinTypeSpec.GetSize (element_type); + if (factor == 0) + throw new Exception ("unrecognized type in MakeByteBlob: " + element_type); + + data = new byte [(count * factor + 3) & ~3]; + int idx = 0; + + for (int i = 0; i < count; ++i) { + var c = array_data[i] as Constant; + if (c == null) { + idx += factor; + continue; + } + + object v = c.GetValue (); + + switch (element_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + long lval = (long) v; + + for (int j = 0; j < factor; ++j) { + data[idx + j] = (byte) (lval & 0xFF); + lval = (lval >> 8); + } + break; + case BuiltinTypeSpec.Type.ULong: + ulong ulval = (ulong) v; + + for (int j = 0; j < factor; ++j) { + data[idx + j] = (byte) (ulval & 0xFF); + ulval = (ulval >> 8); + } + break; + case BuiltinTypeSpec.Type.Float: + element = BitConverter.GetBytes ((float) v); + + for (int j = 0; j < factor; ++j) + data[idx + j] = element[j]; + if (!BitConverter.IsLittleEndian) + System.Array.Reverse (data, idx, 4); + break; + case BuiltinTypeSpec.Type.Double: + element = BitConverter.GetBytes ((double) v); + + for (int j = 0; j < factor; ++j) + data[idx + j] = element[j]; + + // FIXME: Handle the ARM float format. + if (!BitConverter.IsLittleEndian) + System.Array.Reverse (data, idx, 8); + break; + case BuiltinTypeSpec.Type.Char: + int chval = (int) ((char) v); + + data[idx] = (byte) (chval & 0xff); + data[idx + 1] = (byte) (chval >> 8); + break; + case BuiltinTypeSpec.Type.Short: + int sval = (int) ((short) v); + + data[idx] = (byte) (sval & 0xff); + data[idx + 1] = (byte) (sval >> 8); + break; + case BuiltinTypeSpec.Type.UShort: + int usval = (int) ((ushort) v); + + data[idx] = (byte) (usval & 0xff); + data[idx + 1] = (byte) (usval >> 8); + break; + case BuiltinTypeSpec.Type.Int: + int val = (int) v; + + data[idx] = (byte) (val & 0xff); + data[idx + 1] = (byte) ((val >> 8) & 0xff); + data[idx + 2] = (byte) ((val >> 16) & 0xff); + data[idx + 3] = (byte) (val >> 24); + break; + case BuiltinTypeSpec.Type.UInt: + uint uval = (uint) v; + + data[idx] = (byte) (uval & 0xff); + data[idx + 1] = (byte) ((uval >> 8) & 0xff); + data[idx + 2] = (byte) ((uval >> 16) & 0xff); + data[idx + 3] = (byte) (uval >> 24); + break; + case BuiltinTypeSpec.Type.SByte: + data[idx] = (byte) (sbyte) v; + break; + case BuiltinTypeSpec.Type.Byte: + data[idx] = (byte) v; + break; + case BuiltinTypeSpec.Type.Bool: + data[idx] = (byte) ((bool) v ? 1 : 0); + break; + case BuiltinTypeSpec.Type.Decimal: + int[] bits = Decimal.GetBits ((decimal) v); + int p = idx; + + // FIXME: For some reason, this doesn't work on the MS runtime. + int[] nbits = new int[4]; + nbits[0] = bits[3]; + nbits[1] = bits[2]; + nbits[2] = bits[0]; + nbits[3] = bits[1]; + + for (int j = 0; j < 4; j++) { + data[p++] = (byte) (nbits[j] & 0xff); + data[p++] = (byte) ((nbits[j] >> 8) & 0xff); + data[p++] = (byte) ((nbits[j] >> 16) & 0xff); + data[p++] = (byte) (nbits[j] >> 24); + } + break; + default: + throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type); + } + + idx += factor; + } + + return data; + } + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + var initializers = new SLE.Expression [array_data.Count]; + for (var i = 0; i < initializers.Length; i++) { + if (array_data [i] == null) + initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ()); + else + initializers [i] = array_data [i].MakeExpression (ctx); + } + + return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers); +#endif + } +#endif +#if STATIC + // + // Emits the initializers for the array + // + void EmitStaticInitializers (EmitContext ec) + { + var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc); + if (m == null) + return; + + // + // First, the static data + // + byte [] data = MakeByteBlob (); + var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (data, loc); + + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldtoken, fb); + ec.Emit (OpCodes.Call, m); + } +#endif + + // + // Emits pieces of the array that can not be computed at compile + // time (variables and string locations). + // + // This always expect the top value on the stack to be the array + // + void EmitDynamicInitializers (EmitContext ec, bool emitConstants) + { + int dims = bounds.Count; + var current_pos = new int [dims]; + + for (int i = 0; i < array_data.Count; i++){ + + Expression e = array_data [i]; + var c = e as Constant; + + // Constant can be initialized via StaticInitializer + if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) { + TypeSpec etype = e.Type; + + ec.Emit (OpCodes.Dup); + + for (int idx = 0; idx < dims; idx++) + ec.EmitInt (current_pos [idx]); + + // + // If we are dealing with a struct, get the + // address of it, so we can store it. + // + if (dims == 1 && etype.IsStruct) { + switch (etype.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + break; + default: + ec.Emit (OpCodes.Ldelema, etype); + break; + } + } + + e.Emit (ec); + + ec.EmitArrayStore ((ArrayContainer) type); + } + + // + // Advance counter + // + for (int j = dims - 1; j >= 0; j--){ + current_pos [j]++; + if (current_pos [j] < bounds [j]) + break; + current_pos [j] = 0; + } + } + } + + public override void Emit (EmitContext ec) + { + if (first_emit != null) { + first_emit.Emit (ec); + first_emit_temp.Store (ec); + } + + foreach (Expression e in arguments) + e.Emit (ec); + + ec.EmitArrayNew ((ArrayContainer) type); + + if (initializers == null) + return; + +#if STATIC + // Emit static initializer for arrays which have contain more than 2 items and + // the static initializer will initialize at least 25% of array values or there + // is more than 10 items to be initialized + // NOTE: const_initializers_count does not contain default constant values. + if (const_initializers_count > 2 && (array_data.Count > 10 || const_initializers_count * 4 > (array_data.Count)) && + (BuiltinTypeSpec.IsPrimitiveType (array_element_type) || array_element_type.IsEnum)) { + EmitStaticInitializers (ec); + + if (!only_constant_initializers) + EmitDynamicInitializers (ec, false); + } else +#endif + { + EmitDynamicInitializers (ec, true); + } + + if (first_emit_temp != null) + first_emit_temp.Release (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // no multi dimensional or jagged arrays + if (arguments.Count != 1 || array_element_type.IsArray) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + // No array covariance, except for array -> object + if (type != targetType) { + if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + if (enc.Encode (type) == AttributeEncoder.EncodedTypeProperties.DynamicType) { + Attribute.Error_AttributeArgumentIsDynamic (rc, loc); + return; + } + } + + // Single dimensional array of 0 size + if (array_data == null) { + IntConstant ic = arguments[0] as IntConstant; + if (ic == null || !ic.IsDefaultValue) { + base.EncodeAttributeValue (rc, enc, targetType); + } else { + enc.Encode (0); + } + + return; + } + + enc.Encode (array_data.Count); + foreach (var element in array_data) { + element.EncodeAttributeValue (rc, enc, array_element_type); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ArrayCreation target = (ArrayCreation) t; + + if (requested_base_type != null) + target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx); + + if (arguments != null){ + target.arguments = new List (arguments.Count); + foreach (Expression e in arguments) + target.arguments.Add (e.Clone (clonectx)); + } + + if (initializers != null) + target.initializers = (ArrayInitializer) initializers.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Represents an implicitly typed array epxression + // + class ImplicitlyTypedArrayCreation : ArrayCreation + { + sealed class InferenceContext : TypeInferenceContext + { + class ExpressionBoundInfo : BoundInfo + { + readonly Expression expr; + + public ExpressionBoundInfo (Expression expr) + : base (expr.Type, BoundKind.Lower) + { + this.expr = expr; + } + + public override bool Equals (BoundInfo other) + { + // We are using expression not type for conversion check + // no optimization based on types is possible + return false; + } + + public override Expression GetTypeExpression () + { + return expr; + } + } + + public void AddExpression (Expression expr) + { + AddToBounds (new ExpressionBoundInfo (expr), 0); + } + } + + InferenceContext best_type_inference; + + public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) + : base (null, rank, initializers, loc) + { + } + + public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc) + : base (null, initializers, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (type != null) + return this; + + dimensions = rank.Dimension; + + best_type_inference = new InferenceContext (); + + if (!ResolveInitializers (ec)) + return null; + + best_type_inference.FixAllTypes (ec); + array_element_type = best_type_inference.InferredTypeArguments[0]; + best_type_inference = null; + + if (array_element_type == null || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod || + arguments.Count != rank.Dimension) { + ec.Report.Error (826, loc, + "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly"); + return null; + } + + // + // At this point we found common base type for all initializer elements + // but we have to be sure that all static initializer elements are of + // same type + // + UnifyInitializerElement (ec); + + type = ArrayContainer.MakeType (ec.Module, array_element_type, dimensions); + eclass = ExprClass.Value; + return this; + } + + // + // Converts static initializer only + // + void UnifyInitializerElement (ResolveContext ec) + { + for (int i = 0; i < array_data.Count; ++i) { + Expression e = array_data[i]; + if (e != null) + array_data [i] = Convert.ImplicitConversion (ec, e, array_element_type, Location.Null); + } + } + + protected override Expression ResolveArrayElement (ResolveContext ec, Expression element) + { + element = element.Resolve (ec); + if (element != null) + best_type_inference.AddExpression (element); + + return element; + } + } + + sealed class CompilerGeneratedThis : This + { + public CompilerGeneratedThis (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Variable; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return null; + } + } + + /// + /// Represents the `this' construct + /// + + public class This : VariableReference + { + sealed class ThisVariable : ILocalVariable + { + public static readonly ILocalVariable Instance = new ThisVariable (); + + public void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldarg_0); + } + + public void EmitAssign (EmitContext ec) + { + throw new InvalidOperationException (); + } + + public void EmitAddressOf (EmitContext ec) + { + ec.Emit (OpCodes.Ldarg_0); + } + } + + VariableInfo variable_info; + + public This (Location loc) + { + this.loc = loc; + } + + #region Properties + + public override string Name { + get { return "this"; } + } + + public override bool IsLockedByStatement { + get { + return false; + } + set { + } + } + + public override bool IsRef { + get { return type.IsStruct; } + } + + protected override ILocalVariable Variable { + get { return ThisVariable.Instance; } + } + + public override VariableInfo VariableInfo { + get { return variable_info; } + } + + public override bool IsFixed { + get { return false; } + } + + #endregion + + public void CheckStructThisDefiniteAssignment (ResolveContext rc) + { + if (variable_info != null && !variable_info.IsAssigned (rc)) { + rc.Report.Error (188, loc, + "The `this' object cannot be used before all of its fields are assigned to"); + } + } + + protected virtual void Error_ThisNotAvailable (ResolveContext ec) + { + if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer"); + } else if (ec.CurrentAnonymousMethod != null) { + ec.Report.Error (1673, loc, + "Anonymous methods inside structs cannot access instance members of `this'. " + + "Consider copying `this' to a local variable outside the anonymous method and using the local instead"); + } else { + ec.Report.Error (27, loc, "Keyword `this' is not available in the current context"); + } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + if (ae == null) + return null; + + AnonymousMethodStorey storey = ae.Storey; + while (storey != null) { + AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey; + if (temp == null) + return storey.HoistedThis; + + storey = temp; + } + + return null; + } + + public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous) + { + if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) + return false; + + if (ignoreAnonymous || ec.CurrentAnonymousMethod == null) + return true; + + if (ec.CurrentType.IsStruct && ec.CurrentIterator == null) + return false; + + return true; + } + + public virtual void ResolveBase (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = ec.CurrentType; + + if (!IsThisAvailable (ec, false)) { + Error_ThisNotAvailable (ec); + return; + } + + var block = ec.CurrentBlock; + if (block != null) { + if (block.ParametersBlock.TopBlock.ThisVariable != null) + variable_info = block.ParametersBlock.TopBlock.ThisVariable.VariableInfo; + + AnonymousExpression am = ec.CurrentAnonymousMethod; + if (am != null && ec.IsVariableCapturingRequired) { + am.SetHasThisAccess (); + } + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + + // Use typeless constant for ldarg.0 to save some + // space and avoid problems with anonymous stories + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + ResolveBase (ec); + + if (variable_info != null && type.IsStruct) { + CheckStructThisDefiniteAssignment (ec); + } + + return this; + } + + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + ResolveBase (ec); + + if (variable_info != null) + variable_info.SetAssigned (ec); + + if (type.IsClass){ + if (right_side == EmptyExpression.UnaryAddress) + ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only"); + else if (right_side == EmptyExpression.OutAccess) + ec.Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only"); + else + ec.Report.Error (1604, loc, "Cannot assign to `this' because it is read-only"); + } + + return this; + } + + public override int GetHashCode() + { + throw new NotImplementedException (); + } + + public override bool Equals (object obj) + { + This t = obj as This; + if (t == null) + return false; + + return true; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override void SetHasAddressTaken () + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents the `__arglist' construct + /// + public class ArglistAccess : Expression + { + public ArglistAccess (Location loc) + { + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = ec.Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (); + + if (ec.HasSet (ResolveContext.Options.FieldInitializerScope) || !ec.CurrentBlock.ParametersBlock.Parameters.HasArglist) { + ec.Report.Error (190, loc, + "The __arglist construct is valid only within a variable argument method"); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Arglist); + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // nothing. + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents the `__arglist (....)' construct + /// + public class Arglist : Expression + { + public Arguments Arguments { get; private set; } + + public Arglist (Location loc) + : this (null, loc) + { + } + + public Arglist (Arguments args, Location l) + { + Arguments = args; + loc = l; + } + + public MetaType[] ArgumentTypes { + get { + if (Arguments == null) + return MetaType.EmptyTypes; + + var retval = new MetaType[Arguments.Count]; + for (int i = 0; i < retval.Length; i++) + retval[i] = Arguments[i].Expr.Type.GetMetaInfo (); + + return retval; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1952, loc, "An expression tree cannot contain a method with variable arguments"); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = InternalType.Arglist; + if (Arguments != null) { + bool dynamic; // Can be ignored as there is always only 1 overload + Arguments.Resolve (ec, out dynamic); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + if (Arguments != null) + Arguments.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Arglist target = (Arglist) t; + + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RefValueExpr : ShimExpression + { + FullNamedExpression texpr; + + public FullNamedExpression FullNamedExpression { + get { return texpr;} + } + + public RefValueExpr (Expression expr, FullNamedExpression texpr, Location loc) + : base (expr) + { + this.texpr = texpr; + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + type = texpr.ResolveAsType (rc); + if (expr == null || type == null) + return null; + + expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc); + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Refanyval, type); + ec.EmitLoadFromPtr (type); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RefTypeExpr : ShimExpression + { + public RefTypeExpr (Expression expr, Location loc) + : base (expr) + { + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr == null) + return null; + + expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc); + if (expr == null) + return null; + + type = rc.BuiltinTypes.Type; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Refanytype); + var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class MakeRefExpr : ShimExpression + { + public MakeRefExpr (Expression expr, Location loc) + : base (expr) + { + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.ResolveLValue (rc, EmptyExpression.LValueMemberAccess); + type = rc.Module.PredefinedTypes.TypedReference.Resolve (); + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + ((IMemoryLocation) expr).AddressOf (ec, AddressOp.Load); + ec.Emit (OpCodes.Mkrefany, expr.Type); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the typeof operator + /// + public class TypeOf : Expression { + FullNamedExpression QueriedType; + TypeSpec typearg; + + public TypeOf (FullNamedExpression queried_type, Location l) + { + QueriedType = queried_type; + loc = l; + } + + // + // Use this constructor for any compiler generated typeof expression + // + public TypeOf (TypeSpec type, Location loc) + { + this.typearg = type; + this.loc = loc; + } + + #region Properties + public TypeSpec TypeArgument { + get { + return typearg; + } + } + + public FullNamedExpression TypeExpression { + get { + return QueriedType; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (eclass != ExprClass.Unresolved) + return this; + + if (typearg == null) { + // + // Pointer types are allowed without explicit unsafe, they are just tokens + // + using (ec.Set (ResolveContext.Options.UnsafeScope)) { + typearg = QueriedType.ResolveAsType (ec); + } + + if (typearg == null) + return null; + + if (typearg.Kind == MemberKind.Void && !(QueriedType is TypeExpression)) { + ec.Report.Error (673, loc, "System.Void cannot be used from C#. Use typeof (void) to get the void type object"); + } else if (typearg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Error (1962, QueriedType.Location, + "The typeof operator cannot be used on the dynamic type"); + } + } + + type = ec.BuiltinTypes.Type; + + // Even though what is returned is a type object, it's treated as a value by the compiler. + // In particular, 'typeof (Foo).X' is something totally different from 'Foo.X'. + eclass = ExprClass.Value; + return this; + } + + static bool ContainsDynamicType (TypeSpec type) + { + if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + var element_container = type as ElementTypeSpec; + if (element_container != null) + return ContainsDynamicType (element_container.Element); + + foreach (var t in type.TypeArguments) { + if (ContainsDynamicType (t)) { + return true; + } + } + + return false; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Target type is not System.Type therefore must be object + // and we need to use different encoding sequence + if (targetType != type) + enc.Encode (type); + + if (typearg is InflatedTypeSpec) { + var gt = typearg; + do { + if (InflatedTypeSpec.ContainsTypeParameter (gt)) { + rc.Module.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters", + typearg.GetSignatureForError ()); + return; + } + + gt = gt.DeclaringType; + } while (gt != null); + } + + if (ContainsDynamicType (typearg)) { + Attribute.Error_AttributeArgumentIsDynamic (rc, loc); + return; + } + + enc.EncodeTypeName (typearg); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, typearg); + var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + TypeOf target = (TypeOf) t; + if (QueriedType != null) + target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + sealed class TypeOfMethod : TypeOfMember + { + public TypeOfMethod (MethodSpec method, Location loc) + : base (method, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (member.IsConstructor) { + type = ec.Module.PredefinedTypes.ConstructorInfo.Resolve (); + } else { + type = ec.Module.PredefinedTypes.MethodInfo.Resolve (); + } + + if (type == null) + return null; + + return base.DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, member); + + base.Emit (ec); + ec.Emit (OpCodes.Castclass, type); + } + + protected override PredefinedMember GetTypeFromHandle (EmitContext ec) + { + return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle; + } + + protected override PredefinedMember GetTypeFromHandleGeneric (EmitContext ec) + { + return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle2; + } + } + + abstract class TypeOfMember : Expression where T : MemberSpec + { + protected readonly T member; + + protected TypeOfMember (T member, Location loc) + { + this.member = member; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric; + PredefinedMember p; + if (is_generic) { + p = GetTypeFromHandleGeneric (ec); + ec.Emit (OpCodes.Ldtoken, member.DeclaringType); + } else { + p = GetTypeFromHandle (ec); + } + + var mi = p.Resolve (loc); + if (mi != null) + ec.Emit (OpCodes.Call, mi); + } + + protected abstract PredefinedMember GetTypeFromHandle (EmitContext ec); + protected abstract PredefinedMember GetTypeFromHandleGeneric (EmitContext ec); + } + + sealed class TypeOfField : TypeOfMember + { + public TypeOfField (FieldSpec field, Location loc) + : base (field, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = ec.Module.PredefinedTypes.FieldInfo.Resolve (); + if (type == null) + return null; + + return base.DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, member); + base.Emit (ec); + } + + protected override PredefinedMember GetTypeFromHandle (EmitContext ec) + { + return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle; + } + + protected override PredefinedMember GetTypeFromHandleGeneric (EmitContext ec) + { + return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle2; + } + } + + /// + /// Implements the sizeof expression + /// + public class SizeOf : Expression { + public readonly Expression QueriedType; + TypeSpec type_queried; + + public SizeOf (Expression queried_type, Location l) + { + this.QueriedType = queried_type; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + type_queried = QueriedType.ResolveAsType (ec); + if (type_queried == null) + return null; + + if (TypeManager.IsEnumType (type_queried)) + type_queried = EnumSpec.GetUnderlyingType (type_queried); + + int size_of = BuiltinTypeSpec.GetSize (type_queried); + if (size_of > 0) { + return new IntConstant (ec.BuiltinTypes, size_of, loc); + } + + if (!TypeManager.VerifyUnmanaged (ec.Module, type_queried, loc)){ + return null; + } + + if (!ec.IsUnsafe) { + ec.Report.Error (233, loc, + "`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)", + TypeManager.CSharpName (type_queried)); + } + + type = ec.BuiltinTypes.Int; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Sizeof, type_queried); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the qualified-alias-member (::) expression. + /// + public class QualifiedAliasMember : MemberAccess + { + public readonly string alias; + public static readonly string GlobalAlias = "global"; + + public QualifiedAliasMember (string alias, string identifier, Location l) + : base (null, identifier, l) + { + this.alias = alias; + } + + public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l) + : base (null, identifier, targs, l) + { + this.alias = alias; + } + + public QualifiedAliasMember (string alias, string identifier, int arity, Location l) + : base (null, identifier, arity, l) + { + this.alias = alias; + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + if (alias == GlobalAlias) { + expr = ec.Module.GlobalRootNamespace; + return base.ResolveAsTypeOrNamespace (ec); + } + + int errors = ec.Module.Compiler.Report.Errors; + expr = ec.LookupNamespaceAlias (alias); + if (expr == null) { + if (errors == ec.Module.Compiler.Report.Errors) + ec.Module.Compiler.Report.Error (432, loc, "Alias `{0}' not found", alias); + return null; + } + + FullNamedExpression fne = base.ResolveAsTypeOrNamespace (ec); + if (fne == null) + return null; + + if (expr.eclass == ExprClass.Type) { + ec.Module.Compiler.Report.Error (431, loc, + "Alias `{0}' cannot be used with '::' since it denotes a type. Consider replacing '::' with '.'", alias); + + return null; + } + + return fne; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return ResolveAsTypeOrNamespace (ec); + } + + protected override void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) + { + rc.Module.Compiler.Report.Error (687, loc, + "A namespace alias qualifier `{0}' did not resolve to a namespace or a type", + GetSignatureForError ()); + } + + public override string GetSignatureForError () + { + string name = Name; + if (targs != null) { + name = Name + "<" + targs.GetSignatureForError () + ">"; + } + + return alias + "::" + name; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + return DoResolve (rc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the member access expression + /// + public class MemberAccess : ATypeNameExpression + { + protected Expression expr; + + public MemberAccess (Expression expr, string id) + : base (id, expr.Location) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, Location loc) + : base (identifier, loc) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc) + : base (identifier, args, loc) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, int arity, Location loc) + : base (identifier, arity, loc) + { + this.expr = expr; + } + + public Expression LeftExpression { + get { + return expr; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + return DoResolveName (ec, null); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolveName (ec, right_side); + } + + Expression DoResolveName (ResolveContext rc, Expression right_side) + { + Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None); + if (e == null) + return null; + + if (right_side != null) { + if (e is TypeExpr) { + e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc); + return null; + } + + e = e.ResolveLValue (rc, right_side); + } else { + e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type); + } + + return e; + } + + protected virtual void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + if (type == InternalType.NullLiteral && rc.IsRuntimeBinder) + rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value"); + else + Unary.Error_OperatorCannotBeApplied (rc, loc, ".", type); + } + + public static bool IsValidDotExpression (TypeSpec type) + { + const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | + MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; + + return (type.Kind & dot_kinds) != 0; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + var sn = expr as SimpleName; + const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type; + + // + // Resolve the expression with flow analysis turned off, we'll do the definite + // assignment checks later. This is because we don't know yet what the expression + // will resolve to - it may resolve to a FieldExpr and in this case we must do the + // definite assignment check on the actual field and not on the whole struct. + // + using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { + if (sn != null) { + expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity); + + // Call resolve on expression which does have type set as we need expression type + // TODO: I should probably ensure that the type is always set and leave resolve for the final + if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) { + using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) { + expr = expr.Resolve (rc); + } + } else if (expr is TypeParameterExpr) { + expr.Error_UnexpectedKind (rc, flags, sn.Location); + expr = null; + } + } else { + expr = expr.Resolve (rc, flags); + } + } + + if (expr == null) + return null; + + Namespace ns = expr as Namespace; + if (ns != null) { + var retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc); + + if (retval == null) { + ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc); + return null; + } + + if (HasTypeArguments) + return new GenericTypeExpr (retval.Type, targs, loc); + + return retval; + } + + MemberExpr me; + TypeSpec expr_type = expr.Type; + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + me = expr as MemberExpr; + if (me != null) + me.ResolveInstanceExpression (rc, null); + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new DynamicMemberBinder (Name, args, loc); + } + + if (!IsValidDotExpression (expr_type)) { + Error_OperatorCannotBeApplied (rc, expr_type); + return null; + } + + var lookup_arity = Arity; + bool errorMode = false; + Expression member_lookup; + while (true) { + member_lookup = MemberLookup (rc, errorMode, expr_type, Name, lookup_arity, restrictions, loc); + if (member_lookup == null) { + // + // Try to look for extension method when member lookup failed + // + if (MethodGroupExpr.IsExtensionMethodArgument (expr)) { + NamespaceContainer scope = null; + var methods = rc.LookupExtensionMethod (expr_type, Name, lookup_arity, ref scope); + if (methods != null) { + var emg = new ExtensionMethodGroupExpr (methods, scope, expr, loc); + if (HasTypeArguments) { + if (!targs.Resolve (rc)) + return null; + + emg.SetTypeArguments (rc, targs); + } + + // TODO: it should really skip the checks bellow + return emg.Resolve (rc); + } + } + } + + if (errorMode) { + if (member_lookup == null) { + var dep = expr_type.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } else if (expr is TypeExpr) { + base.Error_TypeDoesNotContainDefinition (rc, expr_type, Name); + } else { + Error_TypeDoesNotContainDefinition (rc, expr_type, Name); + } + + return null; + } + + if (member_lookup is MethodGroupExpr) { + // Leave it to overload resolution to report correct error + } else if (!(member_lookup is TypeExpr)) { + // TODO: rc.SymbolRelatedToPreviousError + ErrorIsInaccesible (rc, member_lookup.GetSignatureForError (), loc); + } + break; + } + + if (member_lookup != null) + break; + + lookup_arity = 0; + restrictions &= ~MemberLookupRestrictions.InvocableOnly; + errorMode = true; + } + + TypeExpr texpr = member_lookup as TypeExpr; + if (texpr != null) { + if (!(expr is TypeExpr)) { + me = expr as MemberExpr; + if (me == null || me.ProbeIdenticalTypeName (rc, expr, sn) == expr) { + rc.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", + Name, member_lookup.GetSignatureForError ()); + return null; + } + } + + if (!texpr.Type.IsAccessible (rc)) { + rc.Report.SymbolRelatedToPreviousError (member_lookup.Type); + ErrorIsInaccesible (rc, member_lookup.Type.GetSignatureForError (), loc); + return null; + } + + if (HasTypeArguments) { + return new GenericTypeExpr (member_lookup.Type, targs, loc); + } + + return member_lookup; + } + + me = member_lookup as MemberExpr; + + if (sn != null && me.IsStatic) + expr = me.ProbeIdenticalTypeName (rc, expr, sn); + + me = me.ResolveMemberAccess (rc, expr, sn); + + if (Arity > 0) { + if (!targs.Resolve (rc)) + return null; + + me.SetTypeArguments (rc, targs); + } + + if (sn != null && (!TypeSpec.IsValueType (expr_type) || me is PropertyExpr)) { + if (me.IsInstance) { + LocalVariableReference var = expr as LocalVariableReference; + if (var != null && !var.VerifyAssigned (rc)) + return null; + } + } + + return me; + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext rc) + { + FullNamedExpression fexpr = expr as FullNamedExpression; + if (fexpr == null) { + expr.ResolveAsType (rc); + return null; + } + + FullNamedExpression expr_resolved = fexpr.ResolveAsTypeOrNamespace (rc); + + if (expr_resolved == null) + return null; + + Namespace ns = expr_resolved as Namespace; + if (ns != null) { + FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc); + + if (retval == null) { + ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc); + } else if (HasTypeArguments) { + retval = new GenericTypeExpr (retval.Type, targs, loc); + if (retval.ResolveAsType (rc) == null) + return null; + } + + return retval; + } + + var tnew_expr = expr_resolved.ResolveAsType (rc); + if (tnew_expr == null) + return null; + + TypeSpec expr_type = tnew_expr; + if (TypeManager.IsGenericParameter (expr_type)) { + rc.Module.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'", + tnew_expr.GetSignatureForError ()); + return null; + } + + TypeSpec nested = null; + while (expr_type != null) { + nested = MemberCache.FindNestedType (expr_type, Name, Arity); + if (nested == null) { + if (expr_type == tnew_expr) { + Error_IdentifierNotFound (rc, expr_type, Name); + return null; + } + + expr_type = tnew_expr; + nested = MemberCache.FindNestedType (expr_type, Name, Arity); + ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc); + break; + } + + if (nested.IsAccessible (rc)) + break; + + // Keep looking after inaccessible candidate + expr_type = nested.DeclaringType.BaseType; + } + + TypeExpr texpr; + if (Arity > 0) { + if (HasTypeArguments) { + texpr = new GenericTypeExpr (nested, targs, loc); + } else { + texpr = new GenericOpenTypeExpr (nested, loc); + } + } else { + texpr = new TypeExpression (nested, loc); + } + + if (texpr.ResolveAsType (rc) == null) + return null; + + return texpr; + } + + protected virtual void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) + { + var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity)); + + if (nested != null) { + Error_TypeArgumentsCannotBeUsed (rc, nested, Arity, expr.Location); + return; + } + + var any_other_member = MemberLookup (rc, true, expr_type, Name, 0, MemberLookupRestrictions.None, loc); + if (any_other_member != null) { + any_other_member.Error_UnexpectedKind (rc.Module.Compiler.Report, null, "type", loc); + return; + } + + rc.Module.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", + Name, expr_type.GetSignatureForError ()); + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + if (ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2 && !ec.IsRuntimeBinder && MethodGroupExpr.IsExtensionMethodArgument (expr)) { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (1061, loc, + "Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found (are you missing a using directive or an assembly reference?)", + type.GetSignatureForError (), name); + return; + } + + base.Error_TypeDoesNotContainDefinition (ec, type, name); + } + + public override string GetSignatureForError () + { + return expr.GetSignatureForError () + "." + base.GetSignatureForError (); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + MemberAccess target = (MemberAccess) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements checked expressions + /// + public class CheckedExpr : Expression { + + public Expression Expr; + + public CheckedExpr (Expression e, Location l) + { + Expr = e; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + return Expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + Expr = Expr.Resolve (ec); + + if (Expr == null) + return null; + + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) + return Expr; + + eclass = Expr.eclass; + type = Expr.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Expr.EmitBranchable (ec, target, on_true); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + return Expr.MakeExpression (ctx); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CheckedExpr target = (CheckedExpr) t; + + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the unchecked expression + /// + public class UnCheckedExpr : Expression { + + public Expression Expr; + + public UnCheckedExpr (Expression e, Location l) + { + Expr = e; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + return Expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + Expr = Expr.Resolve (ec); + + if (Expr == null) + return null; + + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) + return Expr; + + eclass = Expr.eclass; + type = Expr.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Expr.EmitBranchable (ec, target, on_true); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + UnCheckedExpr target = (UnCheckedExpr) t; + + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// An Element Access expression. + /// + /// During semantic analysis these are transformed into + /// IndexerAccess, ArrayAccess or a PointerArithmetic. + /// + public class ElementAccess : Expression { + public Arguments Arguments; + public Expression Expr; + + public ElementAccess (Expression e, Arguments args, Location loc) + { + Expr = e; + this.loc = loc; + this.Arguments = args; + } + + // + // We perform some simple tests, and then to "split" the emit and store + // code we create an instance of a different class, and return that. + // + Expression CreateAccessExpression (ResolveContext ec) + { + if (type.IsArray) + return (new ArrayAccess (this, loc)); + + if (type.IsPointer) + return MakePointerAccess (ec, type); + + FieldExpr fe = Expr as FieldExpr; + if (fe != null) { + var ff = fe.Spec as FixedFieldSpec; + if (ff != null) { + return MakePointerAccess (ec, ff.ElementType); + } + } + + var indexers = MemberCache.FindMembers (type, MemberCache.IndexerNameAlias, false); + if (indexers != null || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return new IndexerExpr (indexers, type, this); + } + + ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'", + type.GetSignatureForError ()); + return null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, Arguments, + Expr.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "ArrayIndex", args); + } + + Expression MakePointerAccess (ResolveContext ec, TypeSpec type) + { + if (Arguments.Count != 1){ + ec.Report.Error (196, loc, "A pointer must be indexed by only one value"); + return null; + } + + if (Arguments [0] is NamedArgument) + Error_NamedArgument ((NamedArgument) Arguments[0], ec.Report); + + Expression p = new PointerArithmetic (Binary.Operator.Addition, Expr, Arguments [0].Expr.Resolve (ec), type, loc); + return new Indirection (p, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + type = Expr.Type; + + // TODO: Create 1 result for Resolve and ResolveLValue ? + var res = CreateAccessExpression (ec); + if (res == null) + return null; + + return res.Resolve (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + type = Expr.Type; + + var res = CreateAccessExpression (ec); + if (res == null) + return null; + + return res.ResolveLValue (ec, right_side); + } + + public override void Emit (EmitContext ec) + { + throw new Exception ("Should never be reached"); + } + + public static void Error_NamedArgument (NamedArgument na, Report Report) + { + Report.Error (1742, na.Location, "An element access expression cannot use named argument"); + } + + public override string GetSignatureForError () + { + return Expr.GetSignatureForError (); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ElementAccess target = (ElementAccess) t; + + target.Expr = Expr.Clone (clonectx); + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements array access + /// + public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation { + // + // Points to our "data" repository + // + ElementAccess ea; + + LocalTemporary temp, expr_copy; + Expression[] prepared_arguments; + bool prepared; + + public ArrayAccess (ElementAccess ea_data, Location l) + { + ea = ea_data; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return ea.CreateExpressionTree (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolve (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // dynamic is used per argument in ConvertExpressionToArrayIndex case + bool dynamic; + ea.Arguments.Resolve (ec, out dynamic); + + var ac = ea.Expr.Type as ArrayContainer; + int rank = ea.Arguments.Count; + if (ac.Rank != rank) { + ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'", + rank.ToString (), ac.Rank.ToString ()); + return null; + } + + type = ac.Element; + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, ea.Location); + } + + foreach (Argument a in ea.Arguments) { + if (a is NamedArgument) + ElementAccess.Error_NamedArgument ((NamedArgument) a, ec.Report); + + a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr); + } + + eclass = ExprClass.Variable; + + return this; + } + + protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)"); + } + + // + // Load the array arguments into the stack. + // + void LoadArrayAndArguments (EmitContext ec) + { + ea.Expr.Emit (ec); + ea.Arguments.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + var ac = ea.Expr.Type as ArrayContainer; + + if (prepared) { + ec.EmitLoadFromPtr (type); + } else { + if (prepared_arguments == null) { + LoadArrayAndArguments (ec); + } else { + expr_copy.Emit (ec); + LocalTemporary lt; + foreach (var expr in prepared_arguments) { + expr.Emit (ec); + lt = expr as LocalTemporary; + if (lt != null) + lt.Release (ec); + } + } + + ec.EmitArrayLoad (ac); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (this.type); + temp.Store (ec); + } + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + var ac = (ArrayContainer) ea.Expr.Type; + TypeSpec t = source.Type; + + // + // When we are dealing with a struct, get the address of it to avoid value copy + // Same cannot be done for reference type because array covariance and the + // check in ldelema requires to specify the type of array element stored at the index + // + if (t.IsStruct && ((prepare_for_load && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) { + LoadArrayAndArguments (ec); + ec.EmitArrayAddress (ac); + + if (prepare_for_load) { + ec.Emit (OpCodes.Dup); + } + + prepared = true; + } else if (prepare_for_load) { + ea.Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + + expr_copy = new LocalTemporary (ea.Expr.Type); + expr_copy.Store (ec); + prepared_arguments = ea.Arguments.Emit (ec, true); + } else { + LoadArrayAndArguments (ec); + } + + source.Emit (ec); + + if (expr_copy != null) { + expr_copy.Release (ec); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (this.type); + temp.Store (ec); + } + + if (prepared) { + ec.EmitStoreFromPtr (t); + } else { + ec.EmitArrayStore (ac); + } + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + public void EmitNew (EmitContext ec, New source, bool leave_copy) + { + if (!source.Emit (ec, this)) { + if (leave_copy) + throw new NotImplementedException (); + + return; + } + + throw new NotImplementedException (); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + var ac = (ArrayContainer) ea.Expr.Type; + + LoadArrayAndArguments (ec); + + if (ac.Element.IsGenericParameter && mode == AddressOp.Load) + ec.Emit (OpCodes.Readonly); + + ec.EmitArrayAddress (ac); + } + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if NET_4_0 + return SLE.Expression.ArrayAccess (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx)); +#else + throw new NotImplementedException (); +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return SLE.Expression.ArrayIndex (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx)); + } + + SLE.Expression[] MakeExpressionArguments (BuilderContext ctx) + { + using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + return Arguments.MakeExpression (ea.Arguments, ctx); + } + } + } + + // + // Indexer access expression + // + class IndexerExpr : PropertyOrIndexerExpr, OverloadResolver.IBaseMembersProvider + { + LocalTemporary prepared_value; + IList indexers; + Arguments arguments; + TypeSpec queried_type; + + public IndexerExpr (IList indexers, TypeSpec queriedType, ElementAccess ea) + : base (ea.Location) + { + this.indexers = indexers; + this.queried_type = queriedType; + this.InstanceExpression = ea.Expr; + this.arguments = ea.Arguments; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return best_candidate.DeclaringType; + } + } + + public override bool IsInstance { + get { + return true; + } + } + + public override bool IsStatic { + get { + return false; + } + } + + public override string Name { + get { + return "this"; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + InstanceExpression.CreateExpressionTree (ec), + new TypeOfMethod (Getter, loc)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + public override void Emit (EmitContext ec, bool leave_copy) + { + if (prepared) { + prepared_value.Emit (ec); + } else { + Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + prepared = prepare_for_load; + Expression value = source; + + if (prepared) { + Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc, true, false); + + prepared_value = new LocalTemporary (type); + prepared_value.Store (ec); + source.Emit (ec); + prepared_value.Release (ec); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } else if (leave_copy) { + temp = new LocalTemporary (Type); + source.Emit (ec); + temp.Store (ec); + value = temp; + } + + if (!prepared) + arguments.Add (new Argument (value)); + + Invocation.EmitCall (ec, InstanceExpression, Setter, arguments, loc, false, prepared); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + public override string GetSignatureForError () + { + return best_candidate.GetSignatureForError (); + } + + public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if STATIC + throw new NotSupportedException (); +#else + var value = new[] { source.MakeExpression (ctx) }; + var args = Arguments.MakeExpression (arguments, ctx).Concat (value); +#if NET_4_0 + return SLE.Expression.Block ( + SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo (), args), + value [0]); +#else + return args.First (); +#endif +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + var args = Arguments.MakeExpression (arguments, ctx); + return SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo (), args); +#endif + } + + protected override Expression OverloadResolve (ResolveContext rc, Expression right_side) + { + if (best_candidate != null) + return this; + + eclass = ExprClass.IndexerAccess; + + bool dynamic; + arguments.Resolve (rc, out dynamic); + + if (indexers == null && InstanceExpression.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + dynamic = true; + } else { + var res = new OverloadResolver (indexers, OverloadResolver.Restrictions.None, loc); + res.BaseMembersProvider = this; + + // TODO: Do I need 2 argument sets? + best_candidate = res.ResolveMember (rc, ref arguments); + if (best_candidate != null) + type = res.BestCandidateReturnType; + else if (!res.BestCandidateIsDynamic) + return null; + } + + // + // It has dynamic arguments + // + if (dynamic) { + Arguments args = new Arguments (arguments.Count + 1); + if (IsBase) { + rc.Report.Error (1972, loc, + "The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access"); + } else { + args.Add (new Argument (InstanceExpression)); + } + args.AddRange (arguments); + + best_candidate = null; + return new DynamicIndexBinder (args, loc); + } + + ResolveInstanceExpression (rc, right_side); + CheckProtectedMemberAccess (rc, best_candidate); + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + IndexerExpr target = (IndexerExpr) t; + + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "indexer", GetSignatureForError (), loc); + } + + #region IBaseMembersProvider Members + + IList OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType) + { + return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false); + } + + IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member) + { + if (queried_type == member.DeclaringType) + return null; + + var filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, ((IndexerSpec) member).Parameters, null); + return MemberCache.FindMember (queried_type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember; + } + + MethodGroupExpr OverloadResolver.IBaseMembersProvider.LookupExtensionMethod (ResolveContext rc) + { + return null; + } + + #endregion + } + + // + // A base access expression + // + public class BaseThis : This + { + public BaseThis (Location loc) + : base (loc) + { + } + + public BaseThis (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Variable; + } + + #region Properties + + public override string Name { + get { + return "base"; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (831, loc, "An expression tree may not contain a base access"); + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + var context_type = ec.CurrentType; + if (context_type.IsStruct) { + ec.Emit (OpCodes.Ldobj, context_type); + ec.Emit (OpCodes.Box, context_type); + } + } + + protected override void Error_ThisNotAvailable (ResolveContext ec) + { + if (ec.IsStatic) { + ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method"); + } else { + ec.Report.Error (1512, loc, "Keyword `base' is not available in the current context"); + } + } + + public override void ResolveBase (ResolveContext ec) + { + base.ResolveBase (ec); + type = ec.CurrentType.BaseType; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This class exists solely to pass the Type around and to be a dummy + /// that can be passed to the conversion functions (this is used by + /// foreach implementation to typecast the object return value from + /// get_Current into the proper type. All code has been generated and + /// we only care about the side effect conversions to be performed + /// + /// This is also now used as a placeholder where a no-action expression + /// is needed (the `New' class). + /// + class EmptyExpression : Expression + { + sealed class OutAccessExpression : EmptyExpression + { + public OutAccessExpression (TypeSpec t) + : base (t) + { + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + rc.Report.Error (206, right_side.Location, + "A property, indexer or dynamic member access may not be passed as `ref' or `out' parameter"); + + return null; + } + } + + public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression UnaryAddress = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression EventAddition = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression EventSubtraction = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression MissingValue = new EmptyExpression (InternalType.FakeInternalType); + public static readonly Expression Null = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression OutAccess = new OutAccessExpression (InternalType.FakeInternalType); + + public EmptyExpression (TypeSpec t) + { + type = t; + eclass = ExprClass.Value; + loc = Location.Null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + // nothing, as we only exist to not do anything. + } + + public override void EmitSideEffect (EmitContext ec) + { + } + } + + // + // Empty statement expression + // + public sealed class EmptyExpressionStatement : ExpressionStatement + { + public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement (); + + private EmptyExpressionStatement () + { + loc = Location.Null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return null; + } + + public override void EmitStatement (EmitContext ec) + { + // Do nothing + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + type = ec.BuiltinTypes.Object; + return this; + } + + public override void Emit (EmitContext ec) + { + // Do nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class ErrorExpression : EmptyExpression + { + public static readonly ErrorExpression Instance = new ErrorExpression (); + + private ErrorExpression () + : base (InternalType.FakeInternalType) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + return this; + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + } + } + + public class UserCast : Expression { + MethodSpec method; + Expression source; + + public UserCast (MethodSpec method, Expression source, Location l) + { + this.method = method; + this.source = source; + type = method.ReturnType; + loc = l; + } + + public Expression Source { + get { + return source; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (3); + args.Add (new Argument (source.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOf (type, loc))); + args.Add (new Argument (new TypeOfMethod (method, loc))); + return CreateExpressionFactoryCall (ec, "Convert", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + ObsoleteAttribute oa = method.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + source.Emit (ec); + ec.Emit (OpCodes.Call, method); + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (method); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ()); +#endif + } + } + + // + // Holds additional type specifiers like ?, *, [] + // + public class ComposedTypeSpecifier + { + public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null); + + public readonly int Dimension; + public readonly Location Location; + + public ComposedTypeSpecifier (int specifier, Location loc) + { + this.Dimension = specifier; + this.Location = loc; + } + + #region Properties + public bool IsNullable { + get { + return Dimension == -1; + } + } + + public bool IsPointer { + get { + return Dimension == -2; + } + } + + public ComposedTypeSpecifier Next { get; set; } + + #endregion + + public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc) + { + return new ComposedTypeSpecifier (dimension, loc); + } + + public static ComposedTypeSpecifier CreateNullable (Location loc) + { + return new ComposedTypeSpecifier (-1, loc); + } + + public static ComposedTypeSpecifier CreatePointer (Location loc) + { + return new ComposedTypeSpecifier (-2, loc); + } + + public string GetSignatureForError () + { + string s = + IsPointer ? "*" : + IsNullable ? "?" : + ArrayContainer.GetPostfixSignature (Dimension); + + return Next != null ? s + Next.GetSignatureForError () : s; + } + } + + // + // This class is used to "construct" the type during a typecast + // operation. Since the Type.GetType class in .NET can parse + // the type specification, we just use this to construct the type + // one bit at a time. + // + public class ComposedCast : TypeExpr { + FullNamedExpression left; + ComposedTypeSpecifier spec; + + public FullNamedExpression Left { + get { return this.left; } + } + + public ComposedTypeSpecifier Spec { + get { + return this.spec; + } + } + + public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec) + { + if (spec == null) + throw new ArgumentNullException ("spec"); + + this.left = left; + this.spec = spec; + this.loc = spec.Location; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + type = left.ResolveAsType (ec); + if (type == null) + return null; + + eclass = ExprClass.Type; + + var single_spec = spec; + + if (single_spec.IsNullable) { + type = new Nullable.NullableType (type, loc).ResolveAsType (ec); + if (type == null) + return null; + + single_spec = single_spec.Next; + } else if (single_spec.IsPointer) { + if (!TypeManager.VerifyUnmanaged (ec.Module, type, loc)) + return null; + + if (!ec.IsUnsafe) { + UnsafeError (ec.Module.Compiler.Report, loc); + } + + do { + type = PointerContainer.MakeType (ec.Module, type); + single_spec = single_spec.Next; + } while (single_spec != null && single_spec.IsPointer); + } + + if (single_spec != null && single_spec.Dimension > 0) { + if (type.IsSpecialRuntimeType) { + ec.Module.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ()); + } else if (type.IsStatic) { + ec.Module.Compiler.Report.SymbolRelatedToPreviousError (type); + ec.Module.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'", + type.GetSignatureForError ()); + } else { + MakeArray (ec.Module, single_spec); + } + } + + return type; + } + + void MakeArray (ModuleContainer module, ComposedTypeSpecifier spec) + { + if (spec.Next != null) + MakeArray (module, spec.Next); + + type = ArrayContainer.MakeType (module, type, spec.Dimension); + } + + public override string GetSignatureForError () + { + return left.GetSignatureForError () + spec.GetSignatureForError (); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class FixedBufferPtr : Expression + { + readonly Expression array; + + public FixedBufferPtr (Expression array, TypeSpec array_type, Location l) + { + this.type = array_type; + this.array = array; + this.loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + public override void Emit(EmitContext ec) + { + array.Emit (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = PointerContainer.MakeType (ec.Module, type); + eclass = ExprClass.Value; + return this; + } + } + + + // + // This class is used to represent the address of an array, used + // only by the Fixed statement, this generates "&a [0]" construct + // for fixed (char *pa = a) + // + class ArrayPtr : FixedBufferPtr + { + public ArrayPtr (Expression array, TypeSpec array_type, Location l): + base (array, array_type, l) + { + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.EmitInt (0); + ec.Emit (OpCodes.Ldelema, ((PointerContainer) type).Element); + } + } + + // + // Encapsulates a conversion rules required for array indexes + // + public class ArrayIndexCast : TypeCast + { + public ArrayIndexCast (Expression expr, TypeSpec returnType) + : base (expr, returnType) + { + if (expr.Type == returnType) // int -> int + throw new ArgumentException ("unnecessary array index conversion"); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.Set (ResolveContext.Options.CheckedScope)) { + return base.CreateExpressionTree (ec); + } + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + + switch (child.Type.BuiltinType) { + case BuiltinTypeSpec.Type.UInt: + ec.Emit (OpCodes.Conv_U); + break; + case BuiltinTypeSpec.Type.Long: + ec.Emit (OpCodes.Conv_Ovf_I); + break; + case BuiltinTypeSpec.Type.ULong: + ec.Emit (OpCodes.Conv_Ovf_I_Un); + break; + default: + throw new InternalErrorException ("Cannot emit cast to unknown array element type", type); + } + } + } + + // + // Implements the `stackalloc' keyword + // + public class StackAlloc : Expression { + TypeSpec otype; + Expression t; + Expression count; + + public Expression TypeExpression { + get { return this.t; } + } + + public Expression CountExpression { + get { return this.count; } + } + + public StackAlloc (Expression type, Expression count, Location l) + { + t = type; + this.count = count; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + count = count.Resolve (ec); + if (count == null) + return null; + + if (count.Type.BuiltinType != BuiltinTypeSpec.Type.UInt){ + count = Convert.ImplicitConversionRequired (ec, count, ec.BuiltinTypes.Int, loc); + if (count == null) + return null; + } + + Constant c = count as Constant; + if (c != null && c.IsNegative) { + ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc"); + } + + if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) { + ec.Report.Error (255, loc, "Cannot use stackalloc in finally or catch"); + } + + otype = t.ResolveAsType (ec); + if (otype == null) + return null; + + if (!TypeManager.VerifyUnmanaged (ec.Module, otype, loc)) + return null; + + type = PointerContainer.MakeType (ec.Module, otype); + eclass = ExprClass.Value; + + return this; + } + + public override void Emit (EmitContext ec) + { + int size = BuiltinTypeSpec.GetSize (otype); + + count.Emit (ec); + + if (size == 0) + ec.Emit (OpCodes.Sizeof, otype); + else + ec.EmitInt (size); + + ec.Emit (OpCodes.Mul_Ovf_Un); + ec.Emit (OpCodes.Localloc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + StackAlloc target = (StackAlloc) t; + target.count = count.Clone (clonectx); + target.t = t.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // An object initializer expression + // + public class ElementInitializer : Assign + { + public readonly string Name; + + public ElementInitializer (string name, Expression initializer, Location loc) + : base (null, initializer, loc) + { + this.Name = name; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ElementInitializer target = (ElementInitializer) t; + target.source = source.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + FieldExpr fe = target as FieldExpr; + if (fe != null) + args.Add (new Argument (fe.CreateTypeOfExpression ())); + else + args.Add (new Argument (((PropertyExpr)target).CreateSetterTypeOfExpression ())); + + args.Add (new Argument (source.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, + source is CollectionOrObjectInitializers ? "ListBind" : "Bind", + args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (source == null) + return EmptyExpressionStatement.Instance; + + var t = ec.CurrentInitializerVariable.Type; + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (ec.CurrentInitializerVariable)); + target = new DynamicMemberBinder (Name, args, loc); + } else { + + var member = MemberLookup (ec, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc); + if (member == null) { + member = Expression.MemberLookup (ec, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member != null) { + // TODO: ec.Report.SymbolRelatedToPreviousError (member); + ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + return null; + } + } + + if (member == null) { + Error_TypeDoesNotContainDefinition (ec, loc, t, Name); + return null; + } + + if (!(member is PropertyExpr || member is FieldExpr)) { + ec.Report.Error (1913, loc, + "Member `{0}' cannot be initialized. An object initializer may only be used for fields, or properties", + member.GetSignatureForError ()); + + return null; + } + + var me = member as MemberExpr; + if (me.IsStatic) { + ec.Report.Error (1914, loc, + "Static field or property `{0}' cannot be assigned in an object initializer", + me.GetSignatureForError ()); + } + + target = me; + me.InstanceExpression = ec.CurrentInitializerVariable; + } + + if (source is CollectionOrObjectInitializers) { + Expression previous = ec.CurrentInitializerVariable; + ec.CurrentInitializerVariable = target; + source = source.Resolve (ec); + ec.CurrentInitializerVariable = previous; + if (source == null) + return null; + + eclass = source.eclass; + type = source.Type; + return this; + } + + return base.DoResolve (ec); + } + + public override void EmitStatement (EmitContext ec) + { + if (source is CollectionOrObjectInitializers) + source.Emit (ec); + else + base.EmitStatement (ec); + } + } + + // + // A collection initializer expression + // + class CollectionElementInitializer : Invocation + { + public class ElementInitializerArgument : Argument + { + public ElementInitializerArgument (Expression e) + : base (e) + { + } + } + + sealed class AddMemberAccess : MemberAccess + { + public AddMemberAccess (Expression expr, Location loc) + : base (expr, "Add", loc) + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + if (TypeManager.HasElementType (type)) + return; + + base.Error_TypeDoesNotContainDefinition (ec, type, name); + } + } + + public CollectionElementInitializer (Expression argument) + : base (null, new Arguments (1)) + { + base.arguments.Add (new ElementInitializerArgument (argument)); + this.loc = argument.Location; + } + + public CollectionElementInitializer (List arguments, Location loc) + : base (null, new Arguments (arguments.Count)) + { + foreach (Expression e in arguments) + base.arguments.Add (new ElementInitializerArgument (e)); + + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (mg.CreateExpressionTree (ec))); + + var expr_initializers = new ArrayInitializer (arguments.Count, loc); + foreach (Argument a in arguments) + expr_initializers.Add (a.CreateExpressionTree (ec)); + + args.Add (new Argument (new ArrayCreation ( + CreateExpressionTypeExpression (ec, loc), expr_initializers, loc))); + return CreateExpressionFactoryCall (ec, "ElementInit", args); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CollectionElementInitializer target = (CollectionElementInitializer) t; + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + } + + protected override Expression DoResolve (ResolveContext ec) + { + base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc); + + return base.DoResolve (ec); + } + } + + // + // A block of object or collection initializers + // + public class CollectionOrObjectInitializers : ExpressionStatement + { + IList initializers; + bool is_collection_initialization; + + public static readonly CollectionOrObjectInitializers Empty = + new CollectionOrObjectInitializers (Array.AsReadOnly (new Expression [0]), Location.Null); + + public CollectionOrObjectInitializers (IList initializers, Location loc) + { + this.initializers = initializers; + this.loc = loc; + } + + public bool IsEmpty { + get { + return initializers.Count == 0; + } + } + + public bool IsCollectionInitializer { + get { + return is_collection_initialization; + } + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target; + + t.initializers = new List (initializers.Count); + foreach (var e in initializers) + t.initializers.Add (e.Clone (clonectx)); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + var expr_initializers = new ArrayInitializer (initializers.Count, loc); + foreach (Expression e in initializers) { + Expression expr = e.CreateExpressionTree (ec); + if (expr != null) + expr_initializers.Add (expr); + } + + return new ImplicitlyTypedArrayCreation (expr_initializers, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + List element_names = null; + for (int i = 0; i < initializers.Count; ++i) { + Expression initializer = initializers [i]; + ElementInitializer element_initializer = initializer as ElementInitializer; + + if (i == 0) { + if (element_initializer != null) { + element_names = new List (initializers.Count); + element_names.Add (element_initializer.Name); + } else if (initializer is CompletingExpression){ + initializer.Resolve (ec); + throw new InternalErrorException ("This line should never be reached"); + } else { + var t = ec.CurrentInitializerVariable.Type; + // LAMESPEC: The collection must implement IEnumerable only, no dynamic support + if (!t.ImplementsInterface (ec.BuiltinTypes.IEnumerable, false) && t.BuiltinType != BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " + + "object initializer because type `{1}' does not implement `{2}' interface", + ec.CurrentInitializerVariable.GetSignatureForError (), + TypeManager.CSharpName (ec.CurrentInitializerVariable.Type), + TypeManager.CSharpName (ec.BuiltinTypes.IEnumerable)); + return null; + } + is_collection_initialization = true; + } + } else { + if (is_collection_initialization != (element_initializer == null)) { + ec.Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration", + is_collection_initialization ? "collection initializer" : "object initializer"); + continue; + } + + if (!is_collection_initialization) { + if (element_names.Contains (element_initializer.Name)) { + ec.Report.Error (1912, element_initializer.Location, + "An object initializer includes more than one member `{0}' initialization", + element_initializer.Name); + } else { + element_names.Add (element_initializer.Name); + } + } + } + + Expression e = initializer.Resolve (ec); + if (e == EmptyExpressionStatement.Instance) + initializers.RemoveAt (i--); + else + initializers [i] = e; + } + + type = ec.CurrentInitializerVariable.Type; + if (is_collection_initialization) { + if (TypeManager.HasElementType (type)) { + ec.Report.Error (1925, loc, "Cannot initialize object of type `{0}' with a collection initializer", + TypeManager.CSharpName (type)); + } + } + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + EmitStatement (ec); + } + + public override void EmitStatement (EmitContext ec) + { + foreach (ExpressionStatement e in initializers) + e.EmitStatement (ec); + } + } + + // + // New expression with element/object initializers + // + public class NewInitialize : New + { + // + // This class serves as a proxy for variable initializer target instances. + // A real variable is assigned later when we resolve left side of an + // assignment + // + sealed class InitializerTargetExpression : Expression, IMemoryLocation + { + NewInitialize new_instance; + + public InitializerTargetExpression (NewInitialize newInstance) + { + this.type = newInstance.type; + this.loc = newInstance.loc; + this.eclass = newInstance.eclass; + this.new_instance = newInstance; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + // Should not be reached + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + Expression e = (Expression) new_instance.instance; + e.Emit (ec); + } + + #region IMemoryLocation Members + + public void AddressOf (EmitContext ec, AddressOp mode) + { + new_instance.instance.AddressOf (ec, mode); + } + + #endregion + } + + CollectionOrObjectInitializers initializers; + IMemoryLocation instance; + + public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) + : base (requested_type, arguments, l) + { + this.initializers = initializers; + } + + protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) + { + instance = base.EmitAddressOf (ec, Mode); + + if (!initializers.IsEmpty) + initializers.Emit (ec); + + return instance; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + base.CloneTo (clonectx, t); + + NewInitialize target = (NewInitialize) t; + target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (base.CreateExpressionTree (ec))); + if (!initializers.IsEmpty) + args.Add (new Argument (initializers.CreateExpressionTree (ec))); + + return CreateExpressionFactoryCall (ec, + initializers.IsCollectionInitializer ? "ListInit" : "MemberInit", + args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = base.DoResolve (ec); + if (type == null) + return null; + + Expression previous = ec.CurrentInitializerVariable; + ec.CurrentInitializerVariable = new InitializerTargetExpression (this); + initializers.Resolve (ec); + ec.CurrentInitializerVariable = previous; + return e; + } + + public override bool Emit (EmitContext ec, IMemoryLocation target) + { + bool left_on_stack = base.Emit (ec, target); + + if (initializers.IsEmpty) + return left_on_stack; + + LocalTemporary temp = target as LocalTemporary; + if (temp == null) { + if (!left_on_stack) { + VariableReference vr = target as VariableReference; + + // FIXME: This still does not work correctly for pre-set variables + if (vr != null && vr.IsRef) + target.AddressOf (ec, AddressOp.Load); + + ((Expression) target).Emit (ec); + left_on_stack = true; + } + + temp = new LocalTemporary (type); + } + + instance = temp; + if (left_on_stack) + temp.Store (ec); + + initializers.Emit (ec); + + if (left_on_stack) { + temp.Emit (ec); + temp.Release (ec); + } + + return left_on_stack; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class NewAnonymousType : New + { + static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0]; + + List parameters; + readonly TypeContainer parent; + AnonymousTypeClass anonymous_type; + + public List Parameters { + get { return this.parameters; } + } + + public NewAnonymousType (List parameters, TypeContainer parent, Location loc) + : base (null, null, loc) + { + this.parameters = parameters; + this.parent = parent; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + if (parameters == null) + return; + + NewAnonymousType t = (NewAnonymousType) target; + t.parameters = new List (parameters.Count); + foreach (AnonymousTypeParameter atp in parameters) + t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx)); + } + + AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList parameters) + { + AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters); + if (type != null) + return type; + + type = AnonymousTypeClass.Create (parent, parameters, loc); + if (type == null) + return null; + + type.CreateType (); + type.DefineType (); + type.ResolveTypeParameters (); + type.Define (); + type.EmitType (); + if (ec.Report.Errors == 0) + type.CloseType (); + + parent.Module.AddAnonymousType (type); + return type; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (parameters == null) + return base.CreateExpressionTree (ec); + + var init = new ArrayInitializer (parameters.Count, loc); + foreach (Property p in anonymous_type.Properties) + init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc)); + + var ctor_args = new ArrayInitializer (arguments.Count, loc); + foreach (Argument a in arguments) + ctor_args.Add (a.CreateExpressionTree (ec)); + + Arguments args = new Arguments (3); + args.Add (new Argument (new TypeOfMethod (method, loc))); + args.Add (new Argument (new ArrayCreation (CreateExpressionTypeExpression (ec, loc), ctor_args, loc))); + args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc))); + + return CreateExpressionFactoryCall (ec, "New", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression"); + return null; + } + + if (parameters == null) { + anonymous_type = CreateAnonymousType (ec, EmptyParameters); + RequestedType = new TypeExpression (anonymous_type.Definition, loc); + return base.DoResolve (ec); + } + + bool error = false; + arguments = new Arguments (parameters.Count); + TypeExpression [] t_args = new TypeExpression [parameters.Count]; + for (int i = 0; i < parameters.Count; ++i) { + Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec); + if (e == null) { + error = true; + continue; + } + + arguments.Add (new Argument (e)); + t_args [i] = new TypeExpression (e.Type, e.Location); + } + + if (error) + return null; + + anonymous_type = CreateAnonymousType (ec, parameters); + if (anonymous_type == null) + return null; + + RequestedType = new GenericTypeExpr (anonymous_type.Definition, new TypeArguments (t_args), loc); + return base.DoResolve (ec); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class AnonymousTypeParameter : ShimExpression + { + public readonly string Name; + + public AnonymousTypeParameter (Expression initializer, string name, Location loc) + : base (initializer) + { + this.Name = name; + this.loc = loc; + } + + public AnonymousTypeParameter (Parameter parameter) + : base (new SimpleName (parameter.Name, parameter.Location)) + { + this.Name = parameter.Name; + this.loc = parameter.Location; + } + + public override bool Equals (object o) + { + AnonymousTypeParameter other = o as AnonymousTypeParameter; + return other != null && Name == other.Name; + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = expr.Resolve (ec); + if (e == null) + return null; + + if (e.eclass == ExprClass.MethodGroup) { + Error_InvalidInitializer (ec, e.ExprClassName); + return null; + } + + type = e.Type; + if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) { + Error_InvalidInitializer (ec, e.GetSignatureForError ()); + return null; + } + + return e; + } + + protected virtual void Error_InvalidInitializer (ResolveContext ec, string initializer) + { + ec.Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'", + Name, initializer); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs new file mode 100644 index 0000000000..b818546951 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs @@ -0,0 +1,690 @@ +// +// field.cs: All field handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public class FieldDeclarator + { + public FieldDeclarator (SimpleMemberName name, Expression initializer) + { + this.Name = name; + this.Initializer = initializer; + } + + #region Properties + + public SimpleMemberName Name { get; private set; } + public Expression Initializer { get; private set; } + + #endregion + } + + // + // Abstract class for all fields + // + abstract public class FieldBase : MemberBase + { + protected FieldBuilder FieldBuilder; + protected FieldSpec spec; + public Status status; + protected Expression initializer; + protected List declarators; + + [Flags] + public enum Status : byte { + HAS_OFFSET = 4 // Used by FieldMember. + } + + static readonly string[] attribute_targets = new string [] { "field" }; + + protected FieldBase (DeclSpace parent, FullNamedExpression type, Modifiers mod, + Modifiers allowed_mod, MemberName name, Attributes attrs) + : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE, + name, attrs) + { + if ((mod & Modifiers.ABSTRACT) != 0) + Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead"); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Field; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + this.initializer = value; + } + } + + public FieldSpec Spec { + get { + return spec; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public List Declarators { + get { + return this.declarators; + } + } + #endregion + + public void AddDeclarator (FieldDeclarator declarator) + { + if (declarators == null) + declarators = new List (2); + + declarators.Add (declarator); + + // TODO: This will probably break + Parent.AddMember (this, declarator.Name.Value); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.FieldOffset) { + status |= Status.HAS_OFFSET; + + if (!Parent.PartialContainer.HasExplicitLayout) { + Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)"); + return; + } + + if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) { + Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields"); + return; + } + } + + if (a.Type == pa.FixedBuffer) { + Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead"); + return; + } + +#if false + if (a.Type == pa.MarshalAs) { + UnmanagedMarshal marshal = a.GetMarshal (this); + if (marshal != null) { + FieldBuilder.SetMarshal (marshal); + } + return; + } +#endif + if ((a.HasSecurityAttribute)) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public void SetCustomAttribute (MethodSpec ctor, byte[] data) + { + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data); + } + + protected override bool CheckBase () + { + if (!base.CheckBase ()) + return false; + + MemberSpec candidate; + bool overrides = false; + var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides); + if (conflict_symbol == null) + conflict_symbol = candidate; + + if (conflict_symbol == null) { + if ((ModFlags & Modifiers.NEW) != 0) { + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } + } else { + if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) { + Report.SymbolRelatedToPreviousError (conflict_symbol); + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), conflict_symbol.GetSignatureForError ()); + } + + if (conflict_symbol.IsAbstract) { + Report.SymbolRelatedToPreviousError (conflict_symbol); + Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'", + GetSignatureForError (), conflict_symbol.GetSignatureForError ()); + } + } + + return true; + } + + public virtual Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + return expr.ConvertImplicitly (MemberType); + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + if (MemberType.IsGenericParameter) + return; + + if (MemberType.IsStatic) + Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType, Report); + + CheckBase (); + IsTypePermitted (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "F:"; } + } + + public override void Emit () + { + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder); + } else if (!(Parent is CompilerGeneratedClass) && member_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location); + } + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder); + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) { + Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ()); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + base.Emit (); + } + + public static void Error_VariableOfStaticClass (Location loc, string variable_name, TypeSpec static_class, Report Report) + { + Report.SymbolRelatedToPreviousError (static_class); + Report.Error (723, loc, "`{0}': cannot declare variables of static types", + variable_name); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (!MemberType.IsCLSCompliant () || this is FixedField) { + Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + } + + // + // Field specification + // + public class FieldSpec : MemberSpec, IInterfaceMemberSpec + { + FieldInfo metaInfo; + TypeSpec memberType; + + public FieldSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo info, Modifiers modifiers) + : base (MemberKind.Field, declaringType, definition, modifiers) + { + this.metaInfo = info; + this.memberType = memberType; + } + + #region Properties + + public bool IsReadOnly { + get { + return (Modifiers & Modifiers.READONLY) != 0; + } + } + + public TypeSpec MemberType { + get { + return memberType; + } + } + +#endregion + + public FieldInfo GetMetaInfo () + { + if ((state & StateFlags.PendingMetaInflate) != 0) { + var decl_meta = DeclaringType.GetMetaInfo (); + if (DeclaringType.IsTypeBuilder) { + metaInfo = TypeBuilder.GetField (decl_meta, metaInfo); + } else { + var orig_token = metaInfo.MetadataToken; + metaInfo = decl_meta.GetField (Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + if (metaInfo.MetadataToken != orig_token) + throw new NotImplementedException ("Resolved to wrong meta token"); + + // What a stupid API, does not work because field handle is imported + // metaInfo = FieldInfo.GetFieldFromHandle (metaInfo.FieldHandle, DeclaringType.MetaInfo.TypeHandle); + } + + state &= ~StateFlags.PendingMetaInflate; + } + + return metaInfo; + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var fs = (FieldSpec) base.InflateMember (inflator); + fs.memberType = inflator.Inflate (memberType); + return fs; + } + + public FieldSpec Mutate (TypeParameterMutator mutator) + { + var decl = DeclaringType; + if (DeclaringType.IsGenericOrParentIsGeneric) + decl = mutator.Mutate (decl); + + if (decl == DeclaringType) + return this; + + var fs = (FieldSpec) MemberwiseClone (); + fs.declaringType = decl; + fs.state |= StateFlags.PendingMetaInflate; + + // Gets back FieldInfo in case of metaInfo was inflated + fs.metaInfo = MemberCache.GetMember (TypeParameterMutator.GetMemberDeclaringType (DeclaringType), this).metaInfo; + return fs; + } + + public override List ResolveMissingDependencies () + { + return memberType.ResolveMissingDependencies (); + } + } + + /// + /// Fixed buffer implementation + /// + public class FixedField : FieldBase + { + public const string FixedElementName = "FixedElementField"; + static int GlobalCounter = 0; + + TypeBuilder fixed_buffer_type; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.UNSAFE; + + public FixedField (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name, Attributes attrs) + : base (parent, type, mod, AllowedModifiers, name, attrs) + { + } + + #region Properties + + // + // Explicit struct layout set by parent + // + public CharSet? CharSet { + get; set; + } + + #endregion + + public override Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + return expr.ImplicitConversionRequired (rc, rc.BuiltinTypes.Int, Location); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!BuiltinTypeSpec.IsPrimitiveType (MemberType)) { + Report.Error (1663, Location, + "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double", + GetSignatureForError ()); + } else if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Fields.IndexOf (this); + foreach (var d in declarators) { + var f = new FixedField (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + f.initializer = d.Initializer; + ((ConstInitializer) f.initializer).Name = d.Name.Value; + Parent.PartialContainer.Fields.Insert (++index, f); + } + } + + // Create nested fixed buffer container + string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++); + fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, + TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, + Compiler.BuiltinTypes.ValueType.GetMetaInfo ()); + + var ffield = fixed_buffer_type.DefineField (FixedElementName, MemberType.GetMetaInfo (), FieldAttributes.Public); + + FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, ModifiersExtensions.FieldAttr (ModFlags)); + + var element_spec = new FieldSpec (null, this, MemberType, ffield, ModFlags); + spec = new FixedFieldSpec (Parent.Definition, this, FieldBuilder, element_spec, ModFlags); + + Parent.MemberCache.AddMember (spec); + return true; + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + if (!IsUnsafe) + Expression.UnsafeError (Report, Location); + + if (Parent.PartialContainer.Kind != MemberKind.Struct) { + Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs", + GetSignatureForError ()); + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void Emit() + { + ResolveContext rc = new ResolveContext (this); + IntConstant buffer_size_const = initializer.Resolve (rc) as IntConstant; + if (buffer_size_const == null) + return; + + int buffer_size = buffer_size_const.Value; + + if (buffer_size <= 0) { + Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ()); + return; + } + + EmitFieldSize (buffer_size); + +#if STATIC + if (Module.HasDefaultCharSet) + fixed_buffer_type.__SetAttributes (fixed_buffer_type.Attributes | Module.DefaultCharSetType); +#endif + + Module.PredefinedAttributes.UnsafeValueType.EmitAttribute (fixed_buffer_type); + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (fixed_buffer_type); + fixed_buffer_type.CreateType (); + + base.Emit (); + } + + void EmitFieldSize (int buffer_size) + { + int type_size = BuiltinTypeSpec.GetSize (MemberType); + + if (buffer_size > int.MaxValue / type_size) { + Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit", + GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType)); + return; + } + + AttributeEncoder encoder; + + var ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location); + if (ctor == null) + return; + + var field_size = Module.PredefinedMembers.StructLayoutSize.Resolve (Location); + var field_charset = Module.PredefinedMembers.StructLayoutCharSet.Resolve (Location); + if (field_size == null || field_charset == null) + return; + + var char_set = CharSet ?? Module.DefaultCharSet ?? 0; + + encoder = new AttributeEncoder (); + encoder.Encode ((short)LayoutKind.Sequential); + encoder.EncodeNamedArguments ( + new [] { field_size, field_charset }, + new Constant [] { + new IntConstant (Compiler.BuiltinTypes, buffer_size * type_size, Location), + new IntConstant (Compiler.BuiltinTypes, (int) char_set, Location) + } + ); + + fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + + // + // Don't emit FixedBufferAttribute attribute for private types + // + if ((ModFlags & Modifiers.PRIVATE) != 0) + return; + + ctor = Module.PredefinedMembers.FixedBufferAttributeCtor.Resolve (Location); + if (ctor == null) + return; + + encoder = new AttributeEncoder (); + encoder.EncodeTypeName (MemberType); + encoder.Encode (buffer_size); + encoder.EncodeEmptyNamedArguments (); + + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + } + + class FixedFieldSpec : FieldSpec + { + readonly FieldSpec element; + + public FixedFieldSpec (TypeSpec declaringType, IMemberDefinition definition, FieldInfo info, FieldSpec element, Modifiers modifiers) + : base (declaringType, definition, element.MemberType, info, modifiers) + { + this.element = element; + + // It's never CLS-Compliant + state &= ~StateFlags.CLSCompliant_Undetected; + } + + public FieldSpec Element { + get { + return element; + } + } + + public TypeSpec ElementType { + get { + return MemberType; + } + } + } + + // + // The Field class is used to represents class/struct fields during parsing. + // + public class Field : FieldBase { + // + // Modifiers allowed in a class declaration + // + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.VOLATILE | + Modifiers.UNSAFE | + Modifiers.READONLY; + + public Field (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name, + Attributes attrs) + : base (parent, type, mod, AllowedModifiers, name, attrs) + { + } + + bool CanBeVolatile () + { + switch (MemberType.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.UIntPtr: + case BuiltinTypeSpec.Type.IntPtr: + return true; + } + + if (TypeSpec.IsReferenceType (MemberType)) + return true; + + if (MemberType.IsEnum) + return true; + + return false; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + MetaType[] required_modifier = null; + if ((ModFlags & Modifiers.VOLATILE) != 0) { + var mod = Module.PredefinedTypes.IsVolatile.Resolve (); + if (mod != null) + required_modifier = new MetaType[] { mod.GetMetaInfo () }; + } + + FieldBuilder = Parent.TypeBuilder.DefineField ( + Name, member_type.GetMetaInfo (), required_modifier, null, ModifiersExtensions.FieldAttr (ModFlags)); + + spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags); + + // Don't cache inaccessible fields + if ((ModFlags & Modifiers.BACKING_FIELD) == 0) { + Parent.MemberCache.AddMember (spec); + } + + if (initializer != null) { + ((TypeContainer) Parent).RegisterFieldForInitialization (this, + new FieldInitializer (spec, initializer, this)); + } + + if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Fields.IndexOf (this); + foreach (var d in declarators) { + var f = new Field (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + if (d.Initializer != null) + f.initializer = d.Initializer; + + Parent.PartialContainer.Fields.Insert (++index, f); + } + } + +/* + if ((ModFlags & (Modifiers.STATIC | Modifiers.READONLY | Modifiers.COMPILER_GENERATED)) == Modifiers.STATIC) + Console.WriteLine ("{0}: {1}", Location.ToString (), GetSignatureForError ()); +*/ + return true; + } + + protected override void DoMemberTypeDependentChecks () + { + if ((ModFlags & Modifiers.BACKING_FIELD) != 0) + return; + + base.DoMemberTypeDependentChecks (); + + if ((ModFlags & Modifiers.VOLATILE) != 0) { + if (!CanBeVolatile ()) { + Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (MemberType)); + } + + if ((ModFlags & Modifiers.READONLY) != 0) { + Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly", + GetSignatureForError ()); + } + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if ((ModFlags & Modifiers.VOLATILE) != 0) { + Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ()); + } + + return true; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs new file mode 100644 index 0000000000..d864dc875e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs @@ -0,0 +1,1765 @@ +// +// flowanalyis.cs: The control flow analysis code +// +// Author: +// Martin Baulig (martin@ximian.com) +// Raja R Harinath (rharinath@novell.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Text; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + // + // A new instance of this class is created every time a new block is resolved + // and if there's branching in the block's control flow. + // + public abstract class FlowBranching + { + // + // The type of a FlowBranching. + // + public enum BranchingType : byte { + // Normal (conditional or toplevel) block. + Block, + + // Conditional. + Conditional, + + // A loop block. + Loop, + + // The statement embedded inside a loop + Embedded, + + // part of a block headed by a jump target + Labeled, + + // TryCatch block. + TryCatch, + + // TryFinally, Using, Lock, CollectionForeach + Exception, + + // Switch block. + Switch, + + // The toplevel block of a function + Toplevel, + + // An iterator block + Iterator + } + + // + // The type of one sibling of a branching. + // + public enum SiblingType : byte { + Block, + Conditional, + SwitchSection, + Try, + Catch, + Finally + } + + public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc) + { + switch (type) { + case BranchingType.Exception: + case BranchingType.Labeled: + case BranchingType.Toplevel: + case BranchingType.TryCatch: + throw new InvalidOperationException (); + + case BranchingType.Switch: + return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc); + + case BranchingType.Block: + return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); + + case BranchingType.Loop: + return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc); + + case BranchingType.Embedded: + return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc); + + default: + return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc); + } + } + + // + // The type of this flow branching. + // + public readonly BranchingType Type; + + // + // The block this branching is contained in. This may be null if it's not + // a top-level block and it doesn't declare any local variables. + // + public readonly Block Block; + + // + // The parent of this branching or null if this is the top-block. + // + public readonly FlowBranching Parent; + + // + // Start-Location of this flow branching. + // + public readonly Location Location; + + static int next_id = 0; + int id; + + // + // The vector contains a BitArray with information about which local variables + // and parameters are already initialized at the current code position. + // + public class UsageVector { + // + // The type of this branching. + // + public readonly SiblingType Type; + + // + // Start location of this branching. + // + public Location Location; + + // + // This is only valid for SwitchSection, Try, Catch and Finally. + // + public readonly Block Block; + + // + // The number of locals in this block. + // + public readonly int CountLocals; + + // + // If not null, then we inherit our state from this vector and do a + // copy-on-write. If null, then we're the first sibling in a top-level + // block and inherit from the empty vector. + // + public readonly UsageVector InheritsFrom; + + // + // This is used to construct a list of UsageVector's. + // + public UsageVector Next; + + // + // Private. + // + MyBitVector locals; + bool is_unreachable; + + static int next_id = 0; + int id; + + // + // Normally, you should not use any of these constructors. + // + public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals) + { + this.Type = type; + this.Block = block; + this.Location = loc; + this.InheritsFrom = parent; + this.CountLocals = num_locals; + + locals = num_locals == 0 + ? MyBitVector.Empty + : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals); + + if (parent != null) + is_unreachable = parent.is_unreachable; + + id = ++next_id; + + } + + public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc) + : this (type, parent, block, loc, parent.CountLocals) + { } + + private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc) + { + this.Type = SiblingType.Block; + this.Location = loc; + this.Block = block; + + this.is_unreachable = is_unreachable; + + this.locals = locals; + + id = ++next_id; + + } + + // + // This does a deep copy of the usage vector. + // + public UsageVector Clone () + { + UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals); + + retval.locals = locals.Clone (); + retval.is_unreachable = is_unreachable; + + return retval; + } + + public bool IsAssigned (VariableInfo var, bool ignoreReachability) + { + if (!ignoreReachability && !var.IsParameter && IsUnreachable) + return true; + + return var.IsAssigned (locals); + } + + public void SetAssigned (VariableInfo var) + { + if (!var.IsParameter && IsUnreachable) + return; + + var.SetAssigned (locals); + } + + public bool IsFieldAssigned (VariableInfo var, string name) + { + if (!var.IsParameter && IsUnreachable) + return true; + + return var.IsFieldAssigned (locals, name); + } + + public void SetFieldAssigned (VariableInfo var, string name) + { + if (!var.IsParameter && IsUnreachable) + return; + + var.SetFieldAssigned (locals, name); + } + + public bool IsUnreachable { + get { return is_unreachable; } + } + + public void ResetBarrier () + { + is_unreachable = false; + } + + public void Goto () + { + is_unreachable = true; + } + + public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc) + { + if (sibling_list.Next == null) + return sibling_list; + + MyBitVector locals = null; + bool is_unreachable = sibling_list.is_unreachable; + + if (!sibling_list.IsUnreachable) + locals &= sibling_list.locals; + + for (UsageVector child = sibling_list.Next; child != null; child = child.Next) { + is_unreachable &= child.is_unreachable; + + if (!child.IsUnreachable) + locals &= child.locals; + } + + return new UsageVector (locals, is_unreachable, null, loc); + } + + // + // Merges a child branching. + // + public UsageVector MergeChild (UsageVector child, bool overwrite) + { + Report.Debug (2, " MERGING CHILD EFFECTS", this, child, Type); + + bool new_isunr = child.is_unreachable; + + // + // We've now either reached the point after the branching or we will + // never get there since we always return or always throw an exception. + // + // If we can reach the point after the branching, mark all locals and + // parameters as initialized which have been initialized in all branches + // we need to look at (see above). + // + + if ((Type == SiblingType.SwitchSection) && !new_isunr) { + Report.Error (163, Location, + "Control cannot fall through from one " + + "case label to another"); + return child; + } + + locals |= child.locals; + + // throw away un-necessary information about variables in child blocks + if (locals.Count != CountLocals) + locals = new MyBitVector (locals, CountLocals); + + if (overwrite) + is_unreachable = new_isunr; + else + is_unreachable |= new_isunr; + + return child; + } + + public void MergeOrigins (UsageVector o_vectors) + { + Report.Debug (1, " MERGING BREAK ORIGINS", this); + + if (o_vectors == null) + return; + + if (IsUnreachable && locals != null) + locals.SetAll (true); + + for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { + Report.Debug (1, " MERGING BREAK ORIGIN", vector); + if (vector.IsUnreachable) + continue; + locals &= vector.locals; + is_unreachable &= vector.is_unreachable; + } + + Report.Debug (1, " MERGING BREAK ORIGINS DONE", this); + } + + // + // Debugging stuff. + // + + public override string ToString () + { + return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals); + } + } + + // + // Creates a new flow branching which is contained in `parent'. + // You should only pass non-null for the `block' argument if this block + // introduces any new variables - in this case, we need to create a new + // usage vector with a different size than our parent's one. + // + protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype, + Block block, Location loc) + { + Parent = parent; + Block = block; + Location = loc; + Type = type; + id = ++next_id; + + UsageVector vector; + if (Block != null) { + UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null; + vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots); + } else { + vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc); + } + + AddSibling (vector); + } + + public abstract UsageVector CurrentUsageVector { + get; + } + + // + // Creates a sibling of the current usage vector. + // + public virtual void CreateSibling (Block block, SiblingType type) + { + UsageVector vector = new UsageVector ( + type, Parent.CurrentUsageVector, block, Location); + AddSibling (vector); + + Report.Debug (1, " CREATED SIBLING", CurrentUsageVector); + } + + public void CreateSibling () + { + CreateSibling (null, SiblingType.Conditional); + } + + protected abstract void AddSibling (UsageVector uv); + + protected abstract UsageVector Merge (); + + public UsageVector MergeChild (FlowBranching child) + { + return CurrentUsageVector.MergeChild (child.Merge (), true); + } + + public virtual bool CheckRethrow (Location loc) + { + return Parent.CheckRethrow (loc); + } + + public virtual bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + return Parent.AddResumePoint (stmt, loc, out pc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddBreakOrigin (UsageVector vector, Location loc) + { + return Parent.AddBreakOrigin (vector, loc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddContinueOrigin (UsageVector vector, Location loc) + { + return Parent.AddContinueOrigin (vector, loc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) + { + return Parent.AddReturnOrigin (vector, stmt); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + return Parent.AddGotoOrigin (vector, goto_stmt); + } + + public bool IsAssigned (VariableInfo vi) + { + return CurrentUsageVector.IsAssigned (vi, false); + } + + public bool IsFieldAssigned (VariableInfo vi, string field_name) + { + return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name); + } + + protected static Report Report { + get { return RootContext.ToplevelTypes.Compiler.Report; } + } + + public void SetAssigned (VariableInfo vi) + { + CurrentUsageVector.SetAssigned (vi); + } + + public void SetFieldAssigned (VariableInfo vi, string name) + { + CurrentUsageVector.SetFieldAssigned (vi, name); + } + +#if DEBUG + public override string ToString () + { + StringBuilder sb = new StringBuilder (); + sb.Append (GetType ()); + sb.Append (" ("); + + sb.Append (id); + sb.Append (","); + sb.Append (Type); + if (Block != null) { + sb.Append (" - "); + sb.Append (Block.ID); + sb.Append (" - "); + sb.Append (Block.StartLocation); + } + sb.Append (" - "); + // sb.Append (Siblings.Length); + // sb.Append (" - "); + sb.Append (CurrentUsageVector); + sb.Append (")"); + return sb.ToString (); + } +#endif + + public string Name { + get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); } + } + } + + public class FlowBranchingBlock : FlowBranching + { + UsageVector sibling_list = null; + + public FlowBranchingBlock (FlowBranching parent, BranchingType type, + SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override UsageVector CurrentUsageVector { + get { return sibling_list; } + } + + protected override void AddSibling (UsageVector sibling) + { + if (sibling_list != null && sibling_list.Type == SiblingType.Block) + throw new InternalErrorException ("Blocks don't have sibling flow paths"); + sibling.Next = sibling_list; + sibling_list = sibling; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target); + if (stmt == null) + return Parent.AddGotoOrigin (vector, goto_stmt); + + // forward jump + goto_stmt.SetResolvedTarget (stmt); + stmt.AddUsageVector (vector); + return false; + } + + public static void Error_UnknownLabel (Location loc, string label, Report Report) + { + Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement", + label); + } + + protected override UsageVector Merge () + { + Report.Debug (2, " MERGING SIBLINGS", Name); + UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location); + Report.Debug (2, " MERGING SIBLINGS DONE", Name, vector); + return vector; + } + } + + public class FlowBranchingBreakable : FlowBranchingBlock + { + UsageVector break_origins; + + public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + vector = vector.Clone (); + vector.Next = break_origins; + break_origins = vector; + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + vector.MergeOrigins (break_origins); + return vector; + } + } + + public class FlowBranchingContinuable : FlowBranchingBlock + { + UsageVector continue_origins; + + public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + vector = vector.Clone (); + vector.Next = continue_origins; + continue_origins = vector; + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + vector.MergeOrigins (continue_origins); + return vector; + } + } + + public class FlowBranchingLabeled : FlowBranchingBlock + { + LabeledStatement stmt; + UsageVector actual; + + public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt) + : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc) + { + this.stmt = stmt; + CurrentUsageVector.MergeOrigins (stmt.JumpOrigins); + actual = CurrentUsageVector.Clone (); + + // stand-in for backward jumps + CurrentUsageVector.ResetBarrier (); + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + if (goto_stmt.Target != stmt.Name) + return Parent.AddGotoOrigin (vector, goto_stmt); + + // backward jump + goto_stmt.SetResolvedTarget (stmt); + actual.MergeOrigins (vector.Clone ()); + + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + + if (actual.IsUnreachable) + Report.Warning (162, 2, stmt.loc, "Unreachable code detected"); + + actual.MergeChild (vector, false); + return actual; + } + } + + public class FlowBranchingIterator : FlowBranchingBlock + { + readonly StateMachineInitializer iterator; + + public FlowBranchingIterator (FlowBranching parent, StateMachineInitializer iterator) + : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location) + { + this.iterator = iterator; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + pc = iterator.AddResumePoint (stmt); + return false; + } + } + + public class FlowBranchingToplevel : FlowBranchingBlock + { + UsageVector return_origins; + + public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt) + : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc) + { + } + + public override bool CheckRethrow (Location loc) + { + Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause"); + return false; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + throw new InternalErrorException ("A yield in a non-iterator block"); + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Report.Error (139, loc, "No enclosing loop out of which to break or continue"); + return false; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Report.Error (139, loc, "No enclosing loop out of which to break or continue"); + return false; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) + { + vector = vector.Clone (); + vector.Location = stmt.loc; + vector.Next = return_origins; + return_origins = vector; + return false; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + string name = goto_stmt.Target; + LabeledStatement s = Block.LookupLabel (name); + if (s != null) + throw new InternalErrorException ("Shouldn't get here"); + + if (Parent == null) { + Error_UnknownLabel (goto_stmt.loc, name, Report); + return false; + } + + int errors = Report.Errors; + Parent.AddGotoOrigin (vector, goto_stmt); + if (errors == Report.Errors) + Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method"); + return false; + } + + protected override UsageVector Merge () + { + for (UsageVector origin = return_origins; origin != null; origin = origin.Next) + Block.ParametersBlock.CheckOutParameters (origin, origin.Location); + + UsageVector vector = base.Merge (); + Block.ParametersBlock.CheckOutParameters (vector, Block.loc); + // Note: we _do_not_ merge in the return origins + return vector; + } + + public bool End () + { + return Merge ().IsUnreachable; + } + } + + public class FlowBranchingTryCatch : FlowBranchingBlock + { + TryCatch stmt; + public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt) + : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc) + { + this.stmt = stmt; + } + + public override bool CheckRethrow (Location loc) + { + return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (stmt, loc, out pc); + if (errors == Report.Errors) { + if (CurrentUsageVector.Next == null) + Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause"); + else + Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause"); + } + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Parent.AddBreakOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Parent.AddContinueOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + Parent.AddReturnOrigin (vector, exit_stmt); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + Parent.AddGotoOrigin (vector, goto_stmt); + return true; + } + } + + public class FlowBranchingException : FlowBranching + { + ExceptionStatement stmt; + UsageVector current_vector; + UsageVector try_vector; + UsageVector finally_vector; + + abstract class SavedOrigin { + public readonly SavedOrigin Next; + public readonly UsageVector Vector; + + protected SavedOrigin (SavedOrigin next, UsageVector vector) + { + Next = next; + Vector = vector.Clone (); + } + + protected abstract void DoPropagateFinally (FlowBranching parent); + public void PropagateFinally (UsageVector finally_vector, FlowBranching parent) + { + if (finally_vector != null) + Vector.MergeChild (finally_vector, false); + DoPropagateFinally (parent); + } + } + + class BreakOrigin : SavedOrigin { + Location Loc; + public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddBreakOrigin (Vector, Loc); + } + } + + class ContinueOrigin : SavedOrigin { + Location Loc; + public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddContinueOrigin (Vector, Loc); + } + } + + class ReturnOrigin : SavedOrigin { + public ExitStatement Stmt; + + public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddReturnOrigin (Vector, Stmt); + } + } + + class GotoOrigin : SavedOrigin { + public Goto Stmt; + + public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddGotoOrigin (Vector, Stmt); + } + } + + SavedOrigin saved_origins; + + public FlowBranchingException (FlowBranching parent, + ExceptionStatement stmt) + : base (parent, BranchingType.Exception, SiblingType.Try, + null, stmt.loc) + { + this.stmt = stmt; + } + + protected override void AddSibling (UsageVector sibling) + { + switch (sibling.Type) { + case SiblingType.Try: + try_vector = sibling; + break; + case SiblingType.Finally: + finally_vector = sibling; + break; + default: + throw new InvalidOperationException (); + } + current_vector = sibling; + } + + public override UsageVector CurrentUsageVector { + get { return current_vector; } + } + + public override bool CheckRethrow (Location loc) + { + if (!Parent.CheckRethrow (loc)) + return false; + if (finally_vector == null) + return true; + Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause"); + return false; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (this.stmt, loc, out pc); + if (errors == Report.Errors) { + if (finally_vector == null) + this.stmt.AddResumePoint (stmt, pc); + else + Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + } + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddBreakOrigin (vector, loc); + if (errors == Report.Errors) + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new BreakOrigin (saved_origins, vector, loc); + } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddContinueOrigin (vector, loc); + if (errors == Report.Errors) + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new ContinueOrigin (saved_origins, vector, loc); + } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddReturnOrigin (vector, exit_stmt); + if (errors == Report.Errors) + exit_stmt.Error_FinallyClause (Report); + } else { + saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt); + } + + // sets ec.NeedReturnLabel() + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target); + if (s != null) + throw new InternalErrorException ("Shouldn't get here"); + + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddGotoOrigin (vector, goto_stmt); + if (errors == Report.Errors) + Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt); + } + return true; + } + + protected override UsageVector Merge () + { + UsageVector vector = try_vector.Clone (); + + if (finally_vector != null) + vector.MergeChild (finally_vector, false); + + for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next) + origin.PropagateFinally (finally_vector, Parent); + + return vector; + } + } + + // + // This is used by the flow analysis code to keep track of the type of local variables + // and variables. + // + // The flow code uses a BitVector to keep track of whether a variable has been assigned + // or not. This is easy for fundamental types (int, char etc.) or reference types since + // you can only assign the whole variable as such. + // + // For structs, we also need to keep track of all its fields. To do this, we allocate one + // bit for the struct itself (it's used if you assign/access the whole struct) followed by + // one bit for each of its fields. + // + // This class computes this `layout' for each type. + // + public class TypeInfo + { + public readonly TypeSpec Type; + + // + // Total number of bits a variable of this type consumes in the flow vector. + // + public readonly int TotalLength; + + // + // Number of bits the simple fields of a variable of this type consume + // in the flow vector. + // + public readonly int Length; + + // + // This is only used by sub-structs. + // + public readonly int Offset; + + // + // If this is a struct. + // + public readonly bool IsStruct; + + // + // If this is a struct, all fields which are structs theirselves. + // + public TypeInfo[] SubStructInfo; + + readonly StructInfo struct_info; + private static Dictionary type_hash; + + static TypeInfo () + { + Reset (); + } + + public static void Reset () + { + type_hash = new Dictionary (); + StructInfo.field_type_hash = new Dictionary (); + } + + public static TypeInfo GetTypeInfo (TypeSpec type) + { + TypeInfo info; + if (type_hash.TryGetValue (type, out info)) + return info; + + info = new TypeInfo (type); + type_hash.Add (type, info); + return info; + } + + private TypeInfo (TypeSpec type) + { + this.Type = type; + + struct_info = StructInfo.GetStructInfo (type); + if (struct_info != null) { + Length = struct_info.Length; + TotalLength = struct_info.TotalLength; + SubStructInfo = struct_info.StructFields; + IsStruct = true; + } else { + Length = 0; + TotalLength = 1; + IsStruct = false; + } + } + + TypeInfo (StructInfo struct_info, int offset) + { + this.struct_info = struct_info; + this.Offset = offset; + this.Length = struct_info.Length; + this.TotalLength = struct_info.TotalLength; + this.SubStructInfo = struct_info.StructFields; + this.Type = struct_info.Type; + this.IsStruct = true; + } + + public int GetFieldIndex (string name) + { + if (struct_info == null) + return 0; + + return struct_info [name]; + } + + public TypeInfo GetSubStruct (string name) + { + if (struct_info == null) + return null; + + return struct_info.GetStructField (name); + } + + // + // A struct's constructor must always assign all fields. + // This method checks whether it actually does so. + // + public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc) + { + if (struct_info == null) + return true; + + bool ok = true; + FlowBranching branching = ec.CurrentBranching; + for (int i = 0; i < struct_info.Count; i++) { + var field = struct_info.Fields [i]; + + // Fixed size buffers are not subject to definite assignment checking + if (field is FixedFieldSpec) + continue; + + if (!branching.IsFieldAssigned (vi, field.Name)) { + if (field.MemberDefinition is Property.BackingField) { + ec.Report.Error (843, loc, + "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer", + field.GetSignatureForError ()); + } else { + ec.Report.Error (171, loc, + "Field `{0}' must be fully assigned before control leaves the constructor", + field.GetSignatureForError ()); + } + ok = false; + } + } + + return ok; + } + + public override string ToString () + { + return String.Format ("TypeInfo ({0}:{1}:{2}:{3})", + Type, Offset, Length, TotalLength); + } + + class StructInfo { + public readonly TypeSpec Type; + public readonly FieldSpec[] Fields; + public readonly TypeInfo[] StructFields; + public readonly int Count; + public readonly int CountPublic; + public readonly int CountNonPublic; + public readonly int Length; + public readonly int TotalLength; + public readonly bool HasStructFields; + + public static Dictionary field_type_hash; + private Dictionary struct_field_hash; + private Dictionary field_hash; + + protected bool InTransit = false; + + // Private constructor. To save memory usage, we only need to create one instance + // of this class per struct type. + private StructInfo (TypeSpec type) + { + this.Type = type; + + field_type_hash.Add (type, this); + + TypeContainer tc = type.MemberDefinition as TypeContainer; + + var public_fields = new List (); + var non_public_fields = new List (); + + if (tc != null) { + var fields = tc.Fields; + + if (fields != null) { + foreach (FieldBase field in fields) { + if ((field.ModFlags & Modifiers.STATIC) != 0) + continue; + if ((field.ModFlags & Modifiers.PUBLIC) != 0) + public_fields.Add (field.Spec); + else + non_public_fields.Add (field.Spec); + } + } + } + + CountPublic = public_fields.Count; + CountNonPublic = non_public_fields.Count; + Count = CountPublic + CountNonPublic; + + Fields = new FieldSpec[Count]; + public_fields.CopyTo (Fields, 0); + non_public_fields.CopyTo (Fields, CountPublic); + + struct_field_hash = new Dictionary (); + field_hash = new Dictionary (); + + Length = 0; + StructFields = new TypeInfo [Count]; + StructInfo[] sinfo = new StructInfo [Count]; + + InTransit = true; + + for (int i = 0; i < Count; i++) { + var field = Fields [i]; + + sinfo [i] = GetStructInfo (field.MemberType); + if (sinfo [i] == null) + field_hash.Add (field.Name, ++Length); + else if (sinfo [i].InTransit) { + sinfo [i] = null; + return; + } + } + + InTransit = false; + + TotalLength = Length + 1; + for (int i = 0; i < Count; i++) { + var field = Fields [i]; + + if (sinfo [i] == null) + continue; + + field_hash.Add (field.Name, TotalLength); + + HasStructFields = true; + StructFields [i] = new TypeInfo (sinfo [i], TotalLength); + struct_field_hash.Add (field.Name, StructFields [i]); + TotalLength += sinfo [i].TotalLength; + } + } + + public int this [string name] { + get { + int val; + if (!field_hash.TryGetValue (name, out val)) + return 0; + + return val; + } + } + + public TypeInfo GetStructField (string name) + { + TypeInfo ti; + if (struct_field_hash.TryGetValue (name, out ti)) + return ti; + + return null; + } + + public static StructInfo GetStructInfo (TypeSpec type) + { + if (!type.IsStruct || type.BuiltinType > 0) + return null; + + StructInfo info; + if (field_type_hash.TryGetValue (type, out info)) + return info; + + return new StructInfo (type); + } + } + } + + // + // This is used by the flow analysis code to store information about a single local variable + // or parameter. Depending on the variable's type, we need to allocate one or more elements + // in the BitVector - if it's a fundamental or reference type, we just need to know whether + // it has been assigned or not, but for structs, we need this information for each of its fields. + // + public class VariableInfo { + public readonly string Name; + public readonly TypeInfo TypeInfo; + + // + // The bit offset of this variable in the flow vector. + // + public readonly int Offset; + + // + // The number of bits this variable needs in the flow vector. + // The first bit always specifies whether the variable as such has been assigned while + // the remaining bits contain this information for each of a struct's fields. + // + public readonly int Length; + + // + // If this is a parameter of local variable. + // + public readonly bool IsParameter; + + public readonly LocalVariable LocalInfo; + + readonly VariableInfo Parent; + VariableInfo[] sub_info; + + bool is_ever_assigned; + public bool IsEverAssigned { + get { return is_ever_assigned; } + } + + protected VariableInfo (string name, TypeSpec type, int offset) + { + this.Name = name; + this.Offset = offset; + this.TypeInfo = TypeInfo.GetTypeInfo (type); + + Length = TypeInfo.TotalLength; + + Initialize (); + } + + protected VariableInfo (VariableInfo parent, TypeInfo type) + { + this.Name = parent.Name; + this.TypeInfo = type; + this.Offset = parent.Offset + type.Offset; + this.Parent = parent; + this.Length = type.TotalLength; + + this.IsParameter = parent.IsParameter; + this.LocalInfo = parent.LocalInfo; + + Initialize (); + } + + protected void Initialize () + { + TypeInfo[] sub_fields = TypeInfo.SubStructInfo; + if (sub_fields != null) { + sub_info = new VariableInfo [sub_fields.Length]; + for (int i = 0; i < sub_fields.Length; i++) { + if (sub_fields [i] != null) + sub_info [i] = new VariableInfo (this, sub_fields [i]); + } + } else + sub_info = new VariableInfo [0]; + } + + public VariableInfo (LocalVariable local_info, int offset) + : this (local_info.Name, local_info.Type, offset) + { + this.LocalInfo = local_info; + this.IsParameter = false; + } + + public VariableInfo (ParametersCompiled ip, int i, int offset) + : this (ip.FixedParameters [i].Name, ip.Types [i], offset) + { + this.IsParameter = true; + } + + public bool IsAssigned (ResolveContext ec) + { + return !ec.DoFlowAnalysis || + (ec.OmitStructFlowAnalysis && TypeInfo.Type.IsStruct) || + ec.CurrentBranching.IsAssigned (this); + } + + public bool IsAssigned (ResolveContext ec, Location loc) + { + if (IsAssigned (ec)) + return true; + + ec.Report.Error (165, loc, + "Use of unassigned local variable `" + Name + "'"); + ec.CurrentBranching.SetAssigned (this); + return false; + } + + public bool IsAssigned (MyBitVector vector) + { + if (vector == null) + return true; + + if (vector [Offset]) + return true; + + // FIXME: Fix SetFieldAssigned to set the whole range like SetAssigned below. Then, get rid of this stanza + for (VariableInfo parent = Parent; parent != null; parent = parent.Parent) { + if (vector [parent.Offset]) { + // 'parent' is assigned, but someone forgot to note that all its components are assigned too + parent.SetAssigned (vector); + return true; + } + } + + // Return unless this is a struct. + if (!TypeInfo.IsStruct) + return false; + + // Ok, so each field must be assigned. + for (int i = 0; i < TypeInfo.Length; i++) { + if (!vector [Offset + i + 1]) + return false; + } + + // Ok, now check all fields which are structs. + for (int i = 0; i < sub_info.Length; i++) { + VariableInfo sinfo = sub_info [i]; + if (sinfo == null) + continue; + + if (!sinfo.IsAssigned (vector)) + return false; + } + + vector [Offset] = true; + is_ever_assigned = true; + return true; + } + + public void SetAssigned (ResolveContext ec) + { + if (ec.DoFlowAnalysis) + ec.CurrentBranching.SetAssigned (this); + } + + public void SetAssigned (MyBitVector vector) + { + if (Length == 1) + vector [Offset] = true; + else + vector.SetRange (Offset, Length); + is_ever_assigned = true; + } + + public bool IsFieldAssigned (ResolveContext ec, string name, Location loc) + { + if (!ec.DoFlowAnalysis || + ec.OmitStructFlowAnalysis && TypeInfo.IsStruct || + ec.CurrentBranching.IsFieldAssigned (this, name)) + return true; + + ec.Report.Error (170, loc, + "Use of possibly unassigned field `" + name + "'"); + ec.CurrentBranching.SetFieldAssigned (this, name); + return false; + } + + public bool IsFieldAssigned (MyBitVector vector, string field_name) + { + int field_idx = TypeInfo.GetFieldIndex (field_name); + + if (field_idx == 0) + return true; + + return vector [Offset + field_idx]; + } + + public void SetFieldAssigned (ResolveContext ec, string name) + { + if (ec.DoFlowAnalysis) + ec.CurrentBranching.SetFieldAssigned (this, name); + } + + public void SetFieldAssigned (MyBitVector vector, string field_name) + { + int field_idx = TypeInfo.GetFieldIndex (field_name); + + if (field_idx == 0) + return; + + vector [Offset + field_idx] = true; + is_ever_assigned = true; + } + + public VariableInfo GetSubStruct (string name) + { + TypeInfo type = TypeInfo.GetSubStruct (name); + + if (type == null) + return null; + + return new VariableInfo (this, type); + } + + public override string ToString () + { + return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})", + Name, TypeInfo, Offset, Length, IsParameter); + } + } + + // + // This is a special bit vector which can inherit from another bit vector doing a + // copy-on-write strategy. The inherited vector may have a smaller size than the + // current one. + // + public class MyBitVector { + public readonly int Count; + public static readonly MyBitVector Empty = new MyBitVector (); + + // Invariant: vector != null => vector.Count == Count + // Invariant: vector == null || shared == null + // i.e., at most one of 'vector' and 'shared' can be non-null. They can both be null -- that means all-ones + // The object in 'shared' cannot be modified, while 'vector' can be freely modified + System.Collections.BitArray vector, shared; + + MyBitVector () + { + shared = new System.Collections.BitArray (0, false); + } + + public MyBitVector (MyBitVector InheritsFrom, int Count) + { + if (InheritsFrom != null) + shared = InheritsFrom.MakeShared (Count); + + this.Count = Count; + } + + System.Collections.BitArray MakeShared (int new_count) + { + // Post-condition: vector == null + + // ensure we don't leak out dirty bits from the BitVector we inherited from + if (new_count > Count && + ((shared != null && shared.Count > Count) || + (shared == null && vector == null))) + initialize_vector (); + + if (vector != null) { + shared = vector; + vector = null; + } + + return shared; + } + + // + // Get/set bit `index' in the bit vector. + // + public bool this [int index] { + get { + if (index >= Count) + // FIXME: Disabled due to missing anonymous method flow analysis + // throw new ArgumentOutOfRangeException (); + return true; + + if (vector != null) + return vector [index]; + if (shared == null) + return true; + if (index < shared.Count) + return shared [index]; + return false; + } + + set { + // Only copy the vector if we're actually modifying it. + if (this [index] != value) { + if (vector == null) + initialize_vector (); + vector [index] = value; + } + } + } + + // + // Performs an `or' operation on the bit vector. The `new_vector' may have a + // different size than the current one. + // + private MyBitVector Or (MyBitVector new_vector) + { + if (Count == 0 || new_vector.Count == 0) + return this; + + var o = new_vector.vector != null ? new_vector.vector : new_vector.shared; + + if (o == null) { + int n = new_vector.Count; + if (n < Count) { + for (int i = 0; i < n; ++i) + this [i] = true; + } else { + SetAll (true); + } + return this; + } + + if (Count == o.Count) { + if (vector == null) { + if (shared == null) + return this; + initialize_vector (); + } + vector.Or (o); + return this; + } + + int min = o.Count; + if (Count < min) + min = Count; + + for (int i = 0; i < min; i++) { + if (o [i]) + this [i] = true; + } + + return this; + } + + // + // Performs an `and' operation on the bit vector. The `new_vector' may have + // a different size than the current one. + // + private MyBitVector And (MyBitVector new_vector) + { + if (Count == 0) + return this; + + var o = new_vector.vector != null ? new_vector.vector : new_vector.shared; + + if (o == null) { + for (int i = new_vector.Count; i < Count; ++i) + this [i] = false; + return this; + } + + if (o.Count == 0) { + SetAll (false); + return this; + } + + if (Count == o.Count) { + if (vector == null) { + if (shared == null) { + shared = new_vector.MakeShared (Count); + return this; + } + initialize_vector (); + } + vector.And (o); + return this; + } + + int min = o.Count; + if (Count < min) + min = Count; + + for (int i = 0; i < min; i++) { + if (! o [i]) + this [i] = false; + } + + for (int i = min; i < Count; i++) + this [i] = false; + + return this; + } + + public static MyBitVector operator & (MyBitVector a, MyBitVector b) + { + if (a == b) + return a; + if (a == null) + return b.Clone (); + if (b == null) + return a.Clone (); + if (a.Count > b.Count) + return a.Clone ().And (b); + else + return b.Clone ().And (a); + } + + public static MyBitVector operator | (MyBitVector a, MyBitVector b) + { + if (a == b) + return a; + if (a == null) + return new MyBitVector (null, b.Count); + if (b == null) + return new MyBitVector (null, a.Count); + if (a.Count > b.Count) + return a.Clone ().Or (b); + else + return b.Clone ().Or (a); + } + + public MyBitVector Clone () + { + return Count == 0 ? Empty : new MyBitVector (this, Count); + } + + public void SetRange (int offset, int length) + { + if (offset > Count || offset + length > Count) + throw new ArgumentOutOfRangeException ("flow-analysis"); + + if (shared == null && vector == null) + return; + + int i = 0; + if (shared != null) { + if (offset + length <= shared.Count) { + for (; i < length; ++i) + if (!shared [i+offset]) + break; + if (i == length) + return; + } + initialize_vector (); + } + for (; i < length; ++i) + vector [i+offset] = true; + + } + + public void SetAll (bool value) + { + // Don't clobber Empty + if (Count == 0) + return; + shared = value ? null : Empty.MakeShared (Count); + vector = null; + } + + void initialize_vector () + { + // Post-condition: vector != null + if (shared == null) { + vector = new System.Collections.BitArray (Count, true); + return; + } + + vector = new System.Collections.BitArray (shared); + if (Count != vector.Count) + vector.Length = Count; + shared = null; + } + + StringBuilder Dump (StringBuilder sb) + { + var dump = vector == null ? shared : vector; + if (dump == null) + return sb.Append ("/"); + if (dump == shared) + sb.Append ("="); + for (int i = 0; i < dump.Count; i++) + sb.Append (dump [i] ? "1" : "0"); + return sb; + } + + public override string ToString () + { + return Dump (new StringBuilder ("{")).Append ("}").ToString (); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs new file mode 100644 index 0000000000..1975704777 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs @@ -0,0 +1,3407 @@ +// +// generic.cs: Generics support +// +// Authors: Martin Baulig (martin@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + public enum Variance + { + // + // Don't add or modify internal values, they are used as -/+ calculation signs + // + None = 0, + Covariant = 1, + Contravariant = -1 + } + + [Flags] + public enum SpecialConstraint + { + None = 0, + Constructor = 1 << 2, + Class = 1 << 3, + Struct = 1 << 4 + } + + public class SpecialContraintExpr : FullNamedExpression + { + public SpecialContraintExpr (SpecialConstraint constraint, Location loc) + { + this.loc = loc; + this.Constraint = constraint; + } + + public SpecialConstraint Constraint { get; private set; } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotImplementedException (); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + throw new NotImplementedException (); + } + } + + // + // A set of parsed constraints for a type parameter + // + public class Constraints + { + SimpleMemberName tparam; + List constraints; + Location loc; + bool resolved; + bool resolving; + + public IEnumerable ConstraintExpressions { + get { + return constraints; + } + } + + public Constraints (SimpleMemberName tparam, List constraints, Location loc) + { + this.tparam = tparam; + this.constraints = constraints; + this.loc = loc; + } + + #region Properties + + public Location Location { + get { + return loc; + } + } + + public SimpleMemberName TypeParameter { + get { + return tparam; + } + } + + #endregion + + public static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec bb, IMemberContext context, Location loc) + { + if (spec.HasSpecialClass && bb.IsStruct) { + context.Module.Compiler.Report.Error (455, loc, + "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'", + spec.Name, "class", bb.GetSignatureForError ()); + + return false; + } + + return CheckConflictingInheritedConstraint (spec, spec.BaseType, bb, context, loc); + } + + static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec ba, TypeSpec bb, IMemberContext context, Location loc) + { + if (ba == bb) + return true; + + if (TypeSpec.IsBaseClass (ba, bb, false) || TypeSpec.IsBaseClass (bb, ba, false)) + return true; + + context.Module.Compiler.Report.Error (455, loc, + "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'", + spec.Name, ba.GetSignatureForError (), bb.GetSignatureForError ()); + return false; + } + + public void CheckGenericConstraints (IMemberContext context, bool obsoleteCheck) + { + foreach (var c in constraints) { + if (c == null) + continue; + + var t = c.Type; + if (t == null) + continue; + + if (obsoleteCheck) { + ObsoleteAttribute obsolete_attr = t.GetAttributeObsolete (); + if (obsolete_attr != null) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, t.GetSignatureForError (), c.Location, context.Module.Compiler.Report); + } + + ConstraintChecker.Check (context, t, c.Location); + } + } + + // + // Resolve the constraints types with only possible early checks, return + // value `false' is reserved for recursive failure + // + public bool Resolve (IMemberContext context, TypeParameter tp) + { + if (resolved) + return true; + + if (resolving) + return false; + + resolving = true; + var spec = tp.Type; + List tparam_types = null; + bool iface_found = false; + + spec.BaseType = context.Module.Compiler.BuiltinTypes.Object; + + for (int i = 0; i < constraints.Count; ++i) { + var constraint = constraints[i]; + + if (constraint is SpecialContraintExpr) { + spec.SpecialConstraint |= ((SpecialContraintExpr) constraint).Constraint; + if (spec.HasSpecialStruct) + spec.BaseType = context.Module.Compiler.BuiltinTypes.ValueType; + + // Set to null as it does not have a type + constraints[i] = null; + continue; + } + + var type = constraint.ResolveAsType (context); + if (type == null) + continue; + + if (type.Arity > 0 && ((InflatedTypeSpec) type).HasDynamicArgument ()) { + context.Module.Compiler.Report.Error (1968, constraint.Location, + "A constraint cannot be the dynamic type `{0}'", type.GetSignatureForError ()); + continue; + } + + if (!context.CurrentMemberDefinition.IsAccessibleAs (type)) { + context.Module.Compiler.Report.SymbolRelatedToPreviousError (type); + context.Module.Compiler.Report.Error (703, loc, + "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'", + type.GetSignatureForError (), context.GetSignatureForError ()); + } + + if (type.IsInterface) { + if (!spec.AddInterface (type)) { + context.Module.Compiler.Report.Error (405, constraint.Location, + "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value); + } + + iface_found = true; + continue; + } + + + var constraint_tp = type as TypeParameterSpec; + if (constraint_tp != null) { + if (tparam_types == null) { + tparam_types = new List (2); + } else if (tparam_types.Contains (constraint_tp)) { + context.Module.Compiler.Report.Error (405, constraint.Location, + "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value); + continue; + } + + // + // Checks whether each generic method parameter constraint type + // is valid with respect to T + // + if (tp.IsMethodTypeParameter) { + TypeManager.CheckTypeVariance (type, Variance.Contravariant, context); + } + + var tp_def = constraint_tp.MemberDefinition as TypeParameter; + if (tp_def != null && !tp_def.ResolveConstraints (context)) { + context.Module.Compiler.Report.Error (454, constraint.Location, + "Circular constraint dependency involving `{0}' and `{1}'", + constraint_tp.GetSignatureForError (), tp.GetSignatureForError ()); + continue; + } + + // + // Checks whether there are no conflicts between type parameter constraints + // + // class Foo + // where T : A + // where U : B, T + // + // A and B are not convertible and only 1 class constraint is allowed + // + if (constraint_tp.HasTypeConstraint) { + if (spec.HasTypeConstraint || spec.HasSpecialStruct) { + if (!CheckConflictingInheritedConstraint (spec, constraint_tp.BaseType, context, constraint.Location)) + continue; + } else { + for (int ii = 0; ii < tparam_types.Count; ++ii) { + if (!tparam_types[ii].HasTypeConstraint) + continue; + + if (!CheckConflictingInheritedConstraint (spec, tparam_types[ii].BaseType, constraint_tp.BaseType, context, constraint.Location)) + break; + } + } + } + + if (constraint_tp.HasSpecialStruct) { + context.Module.Compiler.Report.Error (456, constraint.Location, + "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'", + constraint_tp.GetSignatureForError (), tp.GetSignatureForError ()); + continue; + } + + tparam_types.Add (constraint_tp); + continue; + } + + if (iface_found || spec.HasTypeConstraint) { + context.Module.Compiler.Report.Error (406, constraint.Location, + "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list", + type.GetSignatureForError ()); + } + + if (spec.HasSpecialStruct || spec.HasSpecialClass) { + context.Module.Compiler.Report.Error (450, constraint.Location, + "`{0}': cannot specify both a constraint class and the `class' or `struct' constraint", + type.GetSignatureForError ()); + } + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Array: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Enum: + case BuiltinTypeSpec.Type.ValueType: + case BuiltinTypeSpec.Type.Object: + context.Module.Compiler.Report.Error (702, constraint.Location, + "A constraint cannot be special class `{0}'", type.GetSignatureForError ()); + continue; + case BuiltinTypeSpec.Type.Dynamic: + context.Module.Compiler.Report.Error (1967, constraint.Location, + "A constraint cannot be the dynamic type"); + continue; + } + + if (type.IsSealed || !type.IsClass) { + context.Module.Compiler.Report.Error (701, loc, + "`{0}' is not a valid constraint. A constraint must be an interface, a non-sealed class or a type parameter", + TypeManager.CSharpName (type)); + continue; + } + + if (type.IsStatic) { + context.Module.Compiler.Report.Error (717, constraint.Location, + "`{0}' is not a valid constraint. Static classes cannot be used as constraints", + type.GetSignatureForError ()); + } + + spec.BaseType = type; + } + + if (tparam_types != null) + spec.TypeArguments = tparam_types.ToArray (); + + resolving = false; + resolved = true; + return true; + } + + public void VerifyClsCompliance (Report report) + { + foreach (var c in constraints) + { + if (c == null) + continue; + + if (!c.Type.IsCLSCompliant ()) { + report.SymbolRelatedToPreviousError (c.Type); + report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant", + c.Type.GetSignatureForError ()); + } + } + } + } + + // + // A type parameter for a generic type or generic method definition + // + public class TypeParameter : MemberCore, ITypeDefinition + { + static readonly string[] attribute_target = new string [] { "type parameter" }; + + Constraints constraints; + GenericTypeParameterBuilder builder; + TypeParameterSpec spec; + + public TypeParameter (DeclSpace parent, int index, MemberName name, Constraints constraints, Attributes attrs, Variance variance) + : base (parent, name, attrs) + { + this.constraints = constraints; + this.spec = new TypeParameterSpec (null, index, this, SpecialConstraint.None, variance, null); + } + + public TypeParameter (TypeParameterSpec spec, DeclSpace parent, TypeSpec parentSpec, MemberName name, Attributes attrs) + : base (parent, name, attrs) + { + this.spec = new TypeParameterSpec (parentSpec, spec.DeclaredPosition, spec.MemberDefinition, spec.SpecialConstraint, spec.Variance, null) { + BaseType = spec.BaseType, + InterfacesDefined = spec.InterfacesDefined, + TypeArguments = spec.TypeArguments + }; + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.GenericParameter; + } + } + + public IAssemblyDefinition DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + public override string DocCommentHeader { + get { + throw new InvalidOperationException ( + "Unexpected attempt to get doc comment from " + this.GetType ()); + } + } + + public bool IsMethodTypeParameter { + get { + return spec.IsMethodOwned; + } + } + + public string Namespace { + get { + return null; + } + } + + public TypeParameterSpec Type { + get { + return spec; + } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return null; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_target; + } + } + + public Variance Variance { + get { + return spec.Variance; + } + } + + public Constraints Constraints { + get { + return this.constraints; + } + } + + #endregion + + // + // This is called for each part of a partial generic type definition. + // + // If partial type parameters constraints are not null and we don't + // already have constraints they become our constraints. If we already + // have constraints, we must check that they're the same. + // + public bool AddPartialConstraints (TypeContainer part, TypeParameter tp) + { + if (builder == null) + throw new InvalidOperationException (); + + var new_constraints = tp.constraints; + if (new_constraints == null) + return true; + + // TODO: could create spec only + //tp.Define (null, -1, part.Definition); + tp.spec.DeclaringType = part.Definition; + if (!tp.ResolveConstraints (part)) + return false; + + if (constraints != null) + return spec.HasSameConstraintsDefinition (tp.Type); + + // Copy constraint from resolved part to partial container + spec.SpecialConstraint = tp.spec.SpecialConstraint; + spec.InterfacesDefined = tp.spec.InterfacesDefined; + spec.TypeArguments = tp.spec.TypeArguments; + spec.BaseType = tp.spec.BaseType; + + return true; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public void CheckGenericConstraints (bool obsoleteCheck) + { + if (constraints != null) + constraints.CheckGenericConstraints (this, obsoleteCheck); + } + + public TypeParameter CreateHoistedCopy (TypeContainer declaringType, TypeSpec declaringSpec) + { + return new TypeParameter (spec, declaringType, declaringSpec, MemberName, null); + } + + public override bool Define () + { + return true; + } + + // + // This is the first method which is called during the resolving + // process; we're called immediately after creating the type parameters + // with SRE (by calling `DefineGenericParameters()' on the TypeBuilder / + // MethodBuilder). + // + public void Define (GenericTypeParameterBuilder type, TypeSpec declaringType) + { + if (builder != null) + throw new InternalErrorException (); + + this.builder = type; + spec.DeclaringType = declaringType; + spec.SetMetaInfo (type); + } + + public void EmitConstraints (GenericTypeParameterBuilder builder) + { + var attr = GenericParameterAttributes.None; + if (spec.Variance == Variance.Contravariant) + attr |= GenericParameterAttributes.Contravariant; + else if (spec.Variance == Variance.Covariant) + attr |= GenericParameterAttributes.Covariant; + + if (spec.HasSpecialClass) + attr |= GenericParameterAttributes.ReferenceTypeConstraint; + else if (spec.HasSpecialStruct) + attr |= GenericParameterAttributes.NotNullableValueTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint; + + if (spec.HasSpecialConstructor) + attr |= GenericParameterAttributes.DefaultConstructorConstraint; + + if (spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object) + builder.SetBaseTypeConstraint (spec.BaseType.GetMetaInfo ()); + + if (spec.InterfacesDefined != null) + builder.SetInterfaceConstraints (spec.InterfacesDefined.Select (l => l.GetMetaInfo ()).ToArray ()); + + if (spec.TypeArguments != null) + builder.SetInterfaceConstraints (spec.TypeArguments.Select (l => l.GetMetaInfo ()).ToArray ()); + + builder.SetGenericParameterAttributes (attr); + } + + public override void Emit () + { + EmitConstraints (builder); + + if (OptAttributes != null) + OptAttributes.Emit (); + + base.Emit (); + } + + public void ErrorInvalidVariance (IMemberContext mc, Variance expected) + { + Report.SymbolRelatedToPreviousError (mc.CurrentMemberDefinition); + string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant"; + string gtype_variance; + switch (expected) { + case Variance.Contravariant: gtype_variance = "contravariantly"; break; + case Variance.Covariant: gtype_variance = "covariantly"; break; + default: gtype_variance = "invariantly"; break; + } + + Delegate d = mc as Delegate; + string parameters = d != null ? d.Parameters.GetSignatureForError () : ""; + + Report.Error (1961, Location, + "The {2} type parameter `{0}' must be {3} valid on `{1}{4}'", + GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance, parameters); + } + + public TypeSpec GetAttributeCoClass () + { + return null; + } + + public string GetAttributeDefaultMember () + { + throw new NotSupportedException (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + throw new NotSupportedException (); + } + + public override string GetSignatureForDocumentation () + { + throw new NotImplementedException (); + } + + public override string GetSignatureForError () + { + return MemberName.Name; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return spec.MemberDefinition.DeclaringAssembly == assembly; + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotSupportedException ("Not supported for compiled definition"); + } + + // + // Resolves all type parameter constraints + // + public bool ResolveConstraints (IMemberContext context) + { + if (constraints != null) + return constraints.Resolve (context, this); + + if (spec.BaseType == null) + spec.BaseType = context.Module.Compiler.BuiltinTypes.Object; + + return true; + } + + public static TypeParameter FindTypeParameter (TypeParameter[] tparams, string name) + { + foreach (var tp in tparams) { + if (tp.Name == name) + return tp; + } + + return null; + } + + public override bool IsClsComplianceRequired () + { + return false; + } + + public new void VerifyClsCompliance () + { + if (constraints != null) + constraints.VerifyClsCompliance (Report); + } + } + + [System.Diagnostics.DebuggerDisplay ("{DisplayDebugInfo()}")] + public class TypeParameterSpec : TypeSpec + { + public static readonly new TypeParameterSpec[] EmptyTypes = new TypeParameterSpec[0]; + + Variance variance; + SpecialConstraint spec; + readonly int tp_pos; + TypeSpec[] targs; + TypeSpec[] ifaces_defined; + + // + // Creates type owned type parameter + // + public TypeParameterSpec (TypeSpec declaringType, int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info) + : base (MemberKind.TypeParameter, declaringType, definition, info, Modifiers.PUBLIC) + { + this.variance = variance; + this.spec = spec; + state &= ~StateFlags.Obsolete_Undetected; + tp_pos = index; + } + + // + // Creates method owned type parameter + // + public TypeParameterSpec (int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info) + : this (null, index, definition, spec, variance, info) + { + } + + #region Properties + + public int DeclaredPosition { + get { + return tp_pos; + } + } + + public bool HasSpecialConstructor { + get { + return (spec & SpecialConstraint.Constructor) != 0; + } + } + + public bool HasSpecialClass { + get { + return (spec & SpecialConstraint.Class) != 0; + } + } + + public bool HasSpecialStruct { + get { + return (spec & SpecialConstraint.Struct) != 0; + } + } + + public bool HasTypeConstraint { + get { + var bt = BaseType.BuiltinType; + return bt != BuiltinTypeSpec.Type.Object && bt != BuiltinTypeSpec.Type.ValueType; + } + } + + public override IList Interfaces { + get { + if ((state & StateFlags.InterfacesExpanded) == 0) { + if (ifaces != null) { + for (int i = 0; i < ifaces.Count; ++i ) { + var iface_type = ifaces[i]; + if (iface_type.Interfaces != null) { + if (ifaces_defined == null) + ifaces_defined = ifaces.ToArray (); + + for (int ii = 0; ii < iface_type.Interfaces.Count; ++ii) { + var ii_iface_type = iface_type.Interfaces [ii]; + + AddInterface (ii_iface_type); + } + } + } + } + + if (ifaces_defined == null && ifaces != null) + ifaces_defined = ifaces.ToArray (); + + state |= StateFlags.InterfacesExpanded; + } + + return ifaces; + } + } + + // + // Unexpanded interfaces list + // + public TypeSpec[] InterfacesDefined { + get { + if (ifaces_defined == null && ifaces != null) + ifaces_defined = ifaces.ToArray (); + + return ifaces_defined; + } + set { + ifaces = ifaces_defined = value; + } + } + + public bool IsConstrained { + get { + return spec != SpecialConstraint.None || ifaces != null || targs != null || HasTypeConstraint; + } + } + + // + // Returns whether the type parameter is known to be a reference type + // + public new bool IsReferenceType { + get { + if ((spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) + return (spec & SpecialConstraint.Class) != 0; + + // + // Full check is needed (see IsValueType for details) + // + if (HasTypeConstraint && TypeSpec.IsReferenceType (BaseType)) + return true; + + if (targs != null) { + foreach (var ta in targs) { + // + // Secondary special constraints are ignored (I am not sure why) + // + var tp = ta as TypeParameterSpec; + if (tp != null && (tp.spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) + continue; + + if (TypeSpec.IsReferenceType (ta)) + return true; + } + } + + return false; + } + } + + // + // Returns whether the type parameter is known to be a value type + // + public new bool IsValueType { + get { + // + // Even if structs/enums cannot be used directly as constraints + // they can apear as constraint type when inheriting base constraint + // which has dependant type parameter constraint which has been + // inflated using value type + // + // class A : B { override void Foo () {} } + // class B { virtual void Foo () where U : T {} } + // + return HasSpecialStruct || TypeSpec.IsValueType (BaseType); + } + } + + public override string Name { + get { + return definition.Name; + } + } + + public bool IsMethodOwned { + get { + return DeclaringType == null; + } + } + + public SpecialConstraint SpecialConstraint { + get { + return spec; + } + set { + spec = value; + } + } + + // + // Types used to inflate the generic type + // + public new TypeSpec[] TypeArguments { + get { + return targs; + } + set { + targs = value; + } + } + + public Variance Variance { + get { + return variance; + } + } + + #endregion + + public void ChangeTypeArgumentToBaseType (int index) + { + BaseType = targs [index]; + if (targs.Length == 1) { + targs = null; + } else { + var copy = new TypeSpec[targs.Length - 1]; + if (index > 0) + Array.Copy (targs, copy, index); + + Array.Copy (targs, index + 1, copy, index, targs.Length - index - 1); + targs = copy; + } + } + + public string DisplayDebugInfo () + { + var s = GetSignatureForError (); + return IsMethodOwned ? s + "!!" : s + "!"; + } + + // + // Finds effective base class. The effective base class is always a class-type + // + public TypeSpec GetEffectiveBase () + { + if (HasSpecialStruct) + return BaseType; + + // + // If T has a class-type constraint C but no type-parameter constraints, its effective base class is C + // + if (BaseType != null && targs == null) { + // + // If T has a constraint V that is a value-type, use instead the most specific base type of V that is a class-type. + // + // LAMESPEC: Is System.ValueType always the most specific base type in this case? + // + // Note: This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method + // are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method. + // + return BaseType.IsStruct ? BaseType.BaseType : BaseType; + } + + var types = targs; + if (HasTypeConstraint) { + Array.Resize (ref types, types.Length + 1); + types[types.Length - 1] = BaseType; + } + + if (types != null) + return Convert.FindMostEncompassedType (types.Select (l => l.BaseType)); + + return BaseType; + } + + public override string GetSignatureForDocumentation () + { + int c = 0; + var type = DeclaringType; + while (type != null && type.DeclaringType != null) { + type = type.DeclaringType; + c += type.MemberDefinition.TypeParametersCount; + } + + var prefix = IsMethodOwned ? "``" : "`"; + return prefix + (c + DeclaredPosition); + } + + public override string GetSignatureForError () + { + return Name; + } + + // + // Constraints have to match by definition but not position, used by + // partial classes or methods + // + public bool HasSameConstraintsDefinition (TypeParameterSpec other) + { + if (spec != other.spec) + return false; + + if (BaseType != other.BaseType) + return false; + + if (!TypeSpecComparer.Override.IsSame (InterfacesDefined, other.InterfacesDefined)) + return false; + + if (!TypeSpecComparer.Override.IsSame (targs, other.targs)) + return false; + + return true; + } + + // + // Constraints have to match by using same set of types, used by + // implicit interface implementation + // + public bool HasSameConstraintsImplementation (TypeParameterSpec other) + { + if (spec != other.spec) + return false; + + // + // It can be same base type or inflated type parameter + // + // interface I { void Foo where U : T; } + // class A : I { void Foo where X : int {} } + // + bool found; + if (!TypeSpecComparer.Override.IsEqual (BaseType, other.BaseType)) { + if (other.targs == null) + return false; + + found = false; + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + + // Check interfaces implementation -> definition + if (InterfacesDefined != null) { + foreach (var iface in InterfacesDefined) { + found = false; + if (other.InterfacesDefined != null) { + foreach (var oiface in other.InterfacesDefined) { + if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { + found = true; + break; + } + } + } + + if (found) + continue; + + if (other.targs != null) { + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { + found = true; + break; + } + } + } + + if (!found) + return false; + } + } + + // Check interfaces implementation <- definition + if (other.InterfacesDefined != null) { + if (InterfacesDefined == null) + return false; + + foreach (var oiface in other.InterfacesDefined) { + found = false; + foreach (var iface in InterfacesDefined) { + if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + // Check type parameters implementation -> definition + if (targs != null) { + if (other.targs == null) + return false; + + foreach (var targ in targs) { + found = false; + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + // Check type parameters implementation <- definition + if (other.targs != null) { + foreach (var otarg in other.targs) { + // Ignore inflated type arguments, were checked above + if (!otarg.IsGenericParameter) + continue; + + if (targs == null) + return false; + + found = false; + foreach (var targ in targs) { + if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + return true; + } + + public static TypeParameterSpec[] InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec[] tparams) + { + return InflateConstraints (tparams, l => l, inflator); + } + + public static TypeParameterSpec[] InflateConstraints (TypeParameterSpec[] tparams, Func inflatorFactory, T arg) + { + TypeParameterSpec[] constraints = null; + TypeParameterInflator? inflator = null; + + for (int i = 0; i < tparams.Length; ++i) { + var tp = tparams[i]; + if (tp.HasTypeConstraint || tp.InterfacesDefined != null || tp.TypeArguments != null) { + if (constraints == null) { + constraints = new TypeParameterSpec[tparams.Length]; + Array.Copy (tparams, constraints, constraints.Length); + } + + // + // Using a factory to avoid possibly expensive inflator build up + // + if (inflator == null) + inflator = inflatorFactory (arg); + + constraints[i] = (TypeParameterSpec) constraints[i].InflateMember (inflator.Value); + } + } + + if (constraints == null) + constraints = tparams; + + return constraints; + } + + public void InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec tps) + { + tps.BaseType = inflator.Inflate (BaseType); + if (ifaces != null) { + tps.ifaces = new List (ifaces.Count); + for (int i = 0; i < ifaces.Count; ++i) + tps.ifaces.Add (inflator.Inflate (ifaces[i])); + } + + if (targs != null) { + tps.targs = new TypeSpec[targs.Length]; + for (int i = 0; i < targs.Length; ++i) + tps.targs[i] = inflator.Inflate (targs[i]); + } + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var tps = (TypeParameterSpec) MemberwiseClone (); + InflateConstraints (inflator, tps); + return tps; + } + + // + // Populates type parameter members using type parameter constraints + // The trick here is to be called late enough but not too late to + // populate member cache with all members from other types + // + protected override void InitializeMemberCache (bool onlyTypes) + { + cache = new MemberCache (); + + // + // For a type parameter the membercache is the union of the sets of members of the types + // specified as a primary constraint or secondary constraint + // + if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) + cache.AddBaseType (BaseType); + + if (ifaces != null) { + foreach (var iface_type in Interfaces) { + cache.AddInterface (iface_type); + } + } + + if (targs != null) { + foreach (var ta in targs) { + var b_type = ta.BaseType; + if (b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType) + cache.AddBaseType (b_type); + + if (ta.Interfaces != null) { + foreach (var iface_type in ta.Interfaces) { + cache.AddInterface (iface_type); + } + } + } + } + } + + public bool IsConvertibleToInterface (TypeSpec iface) + { + if (Interfaces != null) { + foreach (var t in Interfaces) { + if (t == iface) + return true; + } + } + + if (TypeArguments != null) { + foreach (var t in TypeArguments) { + if (((TypeParameterSpec) t).IsConvertibleToInterface (iface)) + return true; + } + } + + return false; + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + return mutator.Mutate (this); + } + } + + public struct TypeParameterInflator + { + readonly TypeSpec type; + readonly TypeParameterSpec[] tparams; + readonly TypeSpec[] targs; + readonly IModuleContext context; + + public TypeParameterInflator (TypeParameterInflator nested, TypeSpec type) + : this (nested.context, type, nested.tparams, nested.targs) + { + } + + public TypeParameterInflator (IModuleContext context, TypeSpec type, TypeParameterSpec[] tparams, TypeSpec[] targs) + { + if (tparams.Length != targs.Length) + throw new ArgumentException ("Invalid arguments"); + + this.context = context; + this.tparams = tparams; + this.targs = targs; + this.type = type; + } + + #region Properties + + public IModuleContext Context { + get { + return context; + } + } + + public TypeSpec TypeInstance { + get { + return type; + } + } + + // + // Type parameters to inflate + // + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + } + + #endregion + + public TypeSpec Inflate (TypeSpec type) + { + var tp = type as TypeParameterSpec; + if (tp != null) + return Inflate (tp); + + var ac = type as ArrayContainer; + if (ac != null) { + var et = Inflate (ac.Element); + if (et != ac.Element) + return ArrayContainer.MakeType (context.Module, et, ac.Rank); + + return ac; + } + + // + // When inflating a nested type, inflate its parent first + // in case it's using same type parameters (was inflated within the type) + // + TypeSpec[] targs; + int i = 0; + if (type.IsNested) { + var parent = Inflate (type.DeclaringType); + + // + // Keep the inflated type arguments + // + targs = type.TypeArguments; + + // + // When inflating imported nested type used inside same declaring type, we get TypeSpec + // because the import cache helps us to catch it. However, that means we have to look at + // type definition to get type argument (they are in fact type parameter in this case) + // + if (targs.Length == 0 && type.Arity > 0) + targs = type.MemberDefinition.TypeParameters; + + // + // Parent was inflated, find the same type on inflated type + // to use same cache for nested types on same generic parent + // + type = MemberCache.FindNestedType (parent, type.Name, type.Arity); + + // + // Handle the tricky case where parent shares local type arguments + // which means inflating inflated type + // + // class Test { + // public static Nested Foo () { return null; } + // + // public class Nested {} + // } + // + // return type of Test.Foo() has to be Test.Nested + // + if (targs.Length > 0) { + var inflated_targs = new TypeSpec[targs.Length]; + for (; i < targs.Length; ++i) + inflated_targs[i] = Inflate (targs[i]); + + type = type.MakeGenericType (context, inflated_targs); + } + + return type; + } + + // Nothing to do for non-generic type + if (type.Arity == 0) + return type; + + targs = new TypeSpec[type.Arity]; + + // + // Inflating using outside type arguments, var v = new Foo (), class Foo {} + // + if (type is InflatedTypeSpec) { + for (; i < targs.Length; ++i) + targs[i] = Inflate (type.TypeArguments[i]); + + type = type.GetDefinition (); + } else { + // + // Inflating parent using inside type arguments, class Foo { ITest foo; } + // + var args = type.MemberDefinition.TypeParameters; + foreach (var ds_tp in args) + targs[i++] = Inflate (ds_tp); + } + + return type.MakeGenericType (context, targs); + } + + public TypeSpec Inflate (TypeParameterSpec tp) + { + for (int i = 0; i < tparams.Length; ++i) + if (tparams [i] == tp) + return targs[i]; + + // This can happen when inflating nested types + // without type arguments specified + return tp; + } + } + + // + // Before emitting any code we have to change all MVAR references to VAR + // when the method is of generic type and has hoisted variables + // + public class TypeParameterMutator + { + readonly TypeParameter[] mvar; + readonly TypeParameter[] var; + Dictionary mutated_typespec; + + public TypeParameterMutator (TypeParameter[] mvar, TypeParameter[] var) + { + if (mvar.Length != var.Length) + throw new ArgumentException (); + + this.mvar = mvar; + this.var = var; + } + + #region Properties + + public TypeParameter[] MethodTypeParameters { + get { + return mvar; + } + } + + #endregion + + public static TypeSpec GetMemberDeclaringType (TypeSpec type) + { + if (type is InflatedTypeSpec) { + if (type.DeclaringType == null) + return type.GetDefinition (); + + var parent = GetMemberDeclaringType (type.DeclaringType); + type = MemberCache.GetMember (parent, type); + } + + return type; + } + + public TypeSpec Mutate (TypeSpec ts) + { + TypeSpec value; + if (mutated_typespec != null && mutated_typespec.TryGetValue (ts, out value)) + return value; + + value = ts.Mutate (this); + if (mutated_typespec == null) + mutated_typespec = new Dictionary (); + + mutated_typespec.Add (ts, value); + return value; + } + + public TypeParameterSpec Mutate (TypeParameterSpec tp) + { + for (int i = 0; i < mvar.Length; ++i) { + if (mvar[i].Type == tp) + return var[i].Type; + } + + return tp; + } + + public TypeSpec[] Mutate (TypeSpec[] targs) + { + TypeSpec[] mutated = new TypeSpec[targs.Length]; + bool changed = false; + for (int i = 0; i < targs.Length; ++i) { + mutated[i] = Mutate (targs[i]); + changed |= targs[i] != mutated[i]; + } + + return changed ? mutated : targs; + } + } + + /// + /// A TypeExpr which already resolved to a type parameter. + /// + public class TypeParameterExpr : TypeExpression + { + public TypeParameterExpr (TypeParameter type_parameter, Location loc) + : base (type_parameter.Type, loc) + { + this.eclass = ExprClass.TypeParameter; + } + } + + public class InflatedTypeSpec : TypeSpec + { + TypeSpec[] targs; + TypeParameterSpec[] constraints; + readonly TypeSpec open_type; + readonly IModuleContext context; + + public InflatedTypeSpec (IModuleContext context, TypeSpec openType, TypeSpec declaringType, TypeSpec[] targs) + : base (openType.Kind, declaringType, openType.MemberDefinition, null, openType.Modifiers) + { + if (targs == null) + throw new ArgumentNullException ("targs"); + +// this.state = openType.state; + this.context = context; + this.open_type = openType; + this.targs = targs; + + foreach (var arg in targs) { + if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + state |= StateFlags.HasDynamicElement; + break; + } + } + + if (open_type.Kind == MemberKind.MissingType) + MemberCache = MemberCache.Empty; + + if ((open_type.Modifiers & Modifiers.COMPILER_GENERATED) != 0) + state |= StateFlags.ConstraintsChecked; + } + + #region Properties + + public override TypeSpec BaseType { + get { + if (cache == null || (state & StateFlags.PendingBaseTypeInflate) != 0) + InitializeMemberCache (true); + + return base.BaseType; + } + } + + // + // Inflated type parameters with constraints array, mapping with type arguments is based on index + // + public TypeParameterSpec[] Constraints { + get { + if (constraints == null) { + constraints = TypeParameterSpec.InflateConstraints (MemberDefinition.TypeParameters, l => l.CreateLocalInflator (context), this); + } + + return constraints; + } + } + + // + // Used to cache expensive constraints validation on constructed types + // + public bool HasConstraintsChecked { + get { + return (state & StateFlags.ConstraintsChecked) != 0; + } + set { + state = value ? state | StateFlags.ConstraintsChecked : state & ~StateFlags.ConstraintsChecked; + } + } + + public override IList Interfaces { + get { + if (cache == null) + InitializeMemberCache (true); + + return base.Interfaces; + } + } + + public override bool IsExpressionTreeType { + get { + return (open_type.state & StateFlags.InflatedExpressionType) != 0; + } + } + + public override bool IsGenericIterateInterface { + get { + return (open_type.state & StateFlags.GenericIterateInterface) != 0; + } + } + + public override bool IsGenericTask { + get { + return (open_type.state & StateFlags.GenericTask) != 0; + } + } + + public override bool IsNullableType { + get { + return (open_type.state & StateFlags.InflatedNullableType) != 0; + } + } + + // + // Types used to inflate the generic type + // + public override TypeSpec[] TypeArguments { + get { + return targs; + } + } + + #endregion + + public static bool ContainsTypeParameter (TypeSpec type) + { + if (type.Kind == MemberKind.TypeParameter) + return true; + + var element_container = type as ElementTypeSpec; + if (element_container != null) + return ContainsTypeParameter (element_container.Element); + + foreach (var t in type.TypeArguments) { + if (ContainsTypeParameter (t)) { + return true; + } + } + + return false; + } + + TypeParameterInflator CreateLocalInflator (IModuleContext context) + { + TypeParameterSpec[] tparams_full; + TypeSpec[] targs_full = targs; + if (IsNested) { + // + // Special case is needed when we are inflating an open type (nested type definition) + // on inflated parent. Consider following case + // + // Foo.Bar => Foo.Bar + // + // Any later inflation of Foo.Bar has to also inflate T if used inside Bar + // + List merged_targs = null; + List merged_tparams = null; + + var type = DeclaringType; + + do { + if (type.TypeArguments.Length > 0) { + if (merged_targs == null) { + merged_targs = new List (); + merged_tparams = new List (); + if (targs.Length > 0) { + merged_targs.AddRange (targs); + merged_tparams.AddRange (open_type.MemberDefinition.TypeParameters); + } + } + merged_tparams.AddRange (type.MemberDefinition.TypeParameters); + merged_targs.AddRange (type.TypeArguments); + } + type = type.DeclaringType; + } while (type != null); + + if (merged_targs != null) { + // Type arguments are not in the right order but it should not matter in this case + targs_full = merged_targs.ToArray (); + tparams_full = merged_tparams.ToArray (); + } else if (targs.Length == 0) { + tparams_full = TypeParameterSpec.EmptyTypes; + } else { + tparams_full = open_type.MemberDefinition.TypeParameters; + } + } else if (targs.Length == 0) { + tparams_full = TypeParameterSpec.EmptyTypes; + } else { + tparams_full = open_type.MemberDefinition.TypeParameters; + } + + return new TypeParameterInflator (context, this, tparams_full, targs_full); + } + + MetaType CreateMetaInfo (TypeParameterMutator mutator) + { + // + // Converts nested type arguments into right order + // Foo.Bar => string, bool, int + // + var all = new List (); + TypeSpec type = this; + TypeSpec definition = type; + do { + if (type.GetDefinition().IsGeneric) { + all.InsertRange (0, + type.TypeArguments != TypeSpec.EmptyTypes ? + type.TypeArguments.Select (l => l.GetMetaInfo ()) : + type.MemberDefinition.TypeParameters.Select (l => l.GetMetaInfo ())); + } + + definition = definition.GetDefinition (); + type = type.DeclaringType; + } while (type != null); + + return definition.GetMetaInfo ().MakeGenericType (all.ToArray ()); + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return open_type.GetAttributeObsolete (); + } + + protected override bool IsNotCLSCompliant (out bool attrValue) + { + if (base.IsNotCLSCompliant (out attrValue)) + return true; + + foreach (var ta in TypeArguments) { + if (ta.MemberDefinition.CLSAttributeValue == false) + return true; + } + + return false; + } + + public override TypeSpec GetDefinition () + { + return open_type; + } + + public override MetaType GetMetaInfo () + { + if (info == null) + info = CreateMetaInfo (null); + + return info; + } + + public override string GetSignatureForError () + { + if (IsNullableType) + return targs[0].GetSignatureForError () + "?"; + + return base.GetSignatureForError (); + } + + protected override string GetTypeNameSignature () + { + if (targs.Length == 0 || MemberDefinition is AnonymousTypeClass) + return null; + + return "<" + TypeManager.CSharpName (targs) + ">"; + } + + public bool HasDynamicArgument () + { + for (int i = 0; i < targs.Length; ++i) { + var item = targs[i]; + + if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (item is InflatedTypeSpec) { + if (((InflatedTypeSpec) item).HasDynamicArgument ()) + return true; + + continue; + } + + if (item.IsArray) { + while (item.IsArray) { + item = ((ArrayContainer) item).Element; + } + + if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + } + } + + return false; + } + + protected override void InitializeMemberCache (bool onlyTypes) + { + if (cache == null) { + var open_cache = onlyTypes ? open_type.MemberCacheTypes : open_type.MemberCache; + + // Surprisingly, calling MemberCache on open type could meantime create cache on this type + // for imported type parameter constraints referencing nested type of this declaration + if (cache == null) + cache = new MemberCache (open_cache); + } + + var inflator = CreateLocalInflator (context); + + // + // Two stage inflate due to possible nested types recursive + // references + // + // class A { + // B b; + // class B { + // T Value; + // } + // } + // + // When resolving type of `b' members of `B' cannot be + // inflated because are not yet available in membercache + // + if ((state & StateFlags.PendingMemberCacheMembers) == 0) { + open_type.MemberCacheTypes.InflateTypes (cache, inflator); + + // + // Inflate any implemented interfaces + // + if (open_type.Interfaces != null) { + ifaces = new List (open_type.Interfaces.Count); + foreach (var iface in open_type.Interfaces) { + var iface_inflated = inflator.Inflate (iface); + if (iface_inflated == null) + continue; + + AddInterface (iface_inflated); + } + } + + // + // Handles the tricky case of recursive nested base generic type + // + // class A : Base.Nested> { + // class Nested {} + // } + // + // When inflating A. base type is not yet known, secondary + // inflation is required (not common case) once base scope + // is known + // + if (open_type.BaseType == null) { + if (IsClass) + state |= StateFlags.PendingBaseTypeInflate; + } else { + BaseType = inflator.Inflate (open_type.BaseType); + } + } else if ((state & StateFlags.PendingBaseTypeInflate) != 0) { + BaseType = inflator.Inflate (open_type.BaseType); + state &= ~StateFlags.PendingBaseTypeInflate; + } + + if (onlyTypes) { + state |= StateFlags.PendingMemberCacheMembers; + return; + } + + var tc = open_type.MemberDefinition as TypeContainer; + if (tc != null && !tc.HasMembersDefined) + throw new InternalErrorException ("Inflating MemberCache with undefined members"); + + if ((state & StateFlags.PendingBaseTypeInflate) != 0) { + BaseType = inflator.Inflate (open_type.BaseType); + state &= ~StateFlags.PendingBaseTypeInflate; + } + + state &= ~StateFlags.PendingMemberCacheMembers; + open_type.MemberCache.InflateMembers (cache, open_type, inflator); + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + var targs = TypeArguments; + if (targs != null) + targs = mutator.Mutate (targs); + + var decl = DeclaringType; + if (IsNested && DeclaringType.IsGenericOrParentIsGeneric) + decl = mutator.Mutate (decl); + + if (targs == TypeArguments && decl == DeclaringType) + return this; + + var mutated = (InflatedTypeSpec) MemberwiseClone (); + if (decl != DeclaringType) { + // Gets back MethodInfo in case of metaInfo was inflated + //mutated.info = MemberCache.GetMember (DeclaringType.GetDefinition (), this).info; + + mutated.declaringType = decl; + mutated.state |= StateFlags.PendingMetaInflate; + } + + if (targs != null) { + mutated.targs = targs; + mutated.info = null; + } + + return mutated; + } + } + + + // + // Tracks the type arguments when instantiating a generic type. It's used + // by both type arguments and type parameters + // + public class TypeArguments + { + List args; + TypeSpec[] atypes; + + public List Args { + get { return this.args; } + } + + public TypeArguments (params FullNamedExpression[] types) + { + this.args = new List (types); + } + + public void Add (FullNamedExpression type) + { + args.Add (type); + } + + // TODO: Kill this monster + public TypeParameterName[] GetDeclarations () + { + return args.ConvertAll (i => (TypeParameterName) i).ToArray (); + } + + /// + /// We may only be used after Resolve() is called and return the fully + /// resolved types. + /// + // TODO: Not needed, just return type from resolve + public TypeSpec[] Arguments { + get { + return atypes; + } + set { + atypes = value; + } + } + + public int Count { + get { + return args.Count; + } + } + + public virtual bool IsEmpty { + get { + return false; + } + } + + public string GetSignatureForError() + { + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < Count; ++i) { + var expr = args[i]; + if (expr != null) + sb.Append (expr.GetSignatureForError ()); + + if (i + 1 < Count) + sb.Append (','); + } + + return sb.ToString (); + } + + /// + /// Resolve the type arguments. + /// + public virtual bool Resolve (IMemberContext ec) + { + if (atypes != null) + return atypes.Length != 0; + + int count = args.Count; + bool ok = true; + + atypes = new TypeSpec [count]; + + for (int i = 0; i < count; i++){ + var te = args[i].ResolveAsType (ec); + if (te == null) { + ok = false; + continue; + } + + atypes[i] = te; + + if (te.IsStatic) { + ec.Module.Compiler.Report.Error (718, args[i].Location, "`{0}': static classes cannot be used as generic arguments", + te.GetSignatureForError ()); + ok = false; + } + + if (te.IsPointer || te.IsSpecialRuntimeType) { + ec.Module.Compiler.Report.Error (306, args[i].Location, + "The type `{0}' may not be used as a type argument", + te.GetSignatureForError ()); + ok = false; + } + } + + if (!ok) + atypes = TypeSpec.EmptyTypes; + + return ok; + } + + public TypeArguments Clone () + { + TypeArguments copy = new TypeArguments (); + foreach (var ta in args) + copy.args.Add (ta); + + return copy; + } + } + + public class UnboundTypeArguments : TypeArguments + { + public UnboundTypeArguments (int arity) + : base (new FullNamedExpression[arity]) + { + } + + public override bool IsEmpty { + get { + return true; + } + } + + public override bool Resolve (IMemberContext ec) + { + // Nothing to be resolved + return true; + } + } + + public class TypeParameterName : SimpleName + { + Attributes attributes; + Variance variance; + + public TypeParameterName (string name, Attributes attrs, Location loc) + : this (name, attrs, Variance.None, loc) + { + } + + public TypeParameterName (string name, Attributes attrs, Variance variance, Location loc) + : base (name, loc) + { + attributes = attrs; + this.variance = variance; + } + + public Attributes OptAttributes { + get { + return attributes; + } + } + + public Variance Variance { + get { + return variance; + } + } + } + + // + // A type expression of generic type with type arguments + // + class GenericTypeExpr : TypeExpr + { + TypeArguments args; + TypeSpec open_type; + + /// + /// Instantiate the generic type `t' with the type arguments `args'. + /// Use this constructor if you already know the fully resolved + /// generic type. + /// + public GenericTypeExpr (TypeSpec open_type, TypeArguments args, Location l) + { + this.open_type = open_type; + loc = l; + this.args = args; + } + + public TypeArguments TypeArguments { + get { return args; } + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpName (type); + } + + public override TypeSpec ResolveAsType (IMemberContext mc) + { + if (eclass != ExprClass.Unresolved) + return type; + + if (!args.Resolve (mc)) + return null; + + TypeSpec[] atypes = args.Arguments; + + // + // Now bind the parameters + // + var inflated = open_type.MakeGenericType (mc, atypes); + type = inflated; + eclass = ExprClass.Type; + + // + // The constraints can be checked only when full type hierarchy is known + // + if (!inflated.HasConstraintsChecked && mc.Module.HasTypesFullyDefined) { + var constraints = inflated.Constraints; + if (constraints != null) { + var cc = new ConstraintChecker (mc); + if (cc.CheckAll (open_type, atypes, constraints, loc)) { + inflated.HasConstraintsChecked = true; + } + } + } + + return type; + } + + public override bool Equals (object obj) + { + GenericTypeExpr cobj = obj as GenericTypeExpr; + if (cobj == null) + return false; + + if ((type == null) || (cobj.type == null)) + return false; + + return type == cobj.type; + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + } + + // + // Generic type with unbound type arguments, used for typeof (G<,,>) + // + class GenericOpenTypeExpr : TypeExpression + { + public GenericOpenTypeExpr (TypeSpec type, /*UnboundTypeArguments args,*/ Location loc) + : base (type.GetDefinition (), loc) + { + } + } + + struct ConstraintChecker + { + IMemberContext mc; + bool ignore_inferred_dynamic; + bool recursive_checks; + + public ConstraintChecker (IMemberContext ctx) + { + this.mc = ctx; + ignore_inferred_dynamic = false; + recursive_checks = false; + } + + #region Properties + + public bool IgnoreInferredDynamic { + get { + return ignore_inferred_dynamic; + } + set { + ignore_inferred_dynamic = value; + } + } + + #endregion + + // + // Checks the constraints of open generic type against type + // arguments. This version is used for types which could not be + // checked immediatelly during construction because the type + // hierarchy was not yet fully setup (before Emit phase) + // + public static bool Check (IMemberContext mc, TypeSpec type, Location loc) + { + // + // Check declaring type first if there is any + // + if (type.DeclaringType != null && !Check (mc, type.DeclaringType, loc)) + return false; + + while (type is ElementTypeSpec) + type = ((ElementTypeSpec) type).Element; + + if (type.Arity == 0) + return true; + + var gtype = type as InflatedTypeSpec; + if (gtype == null) + return true; + + var constraints = gtype.Constraints; + if (constraints == null) + return true; + + if (gtype.HasConstraintsChecked) + return true; + + var cc = new ConstraintChecker (mc); + cc.recursive_checks = true; + + if (cc.CheckAll (gtype.GetDefinition (), type.TypeArguments, constraints, loc)) { + gtype.HasConstraintsChecked = true; + return true; + } + + return false; + } + + // + // Checks all type arguments againts type parameters constraints + // NOTE: It can run in probing mode when `mc' is null + // + public bool CheckAll (MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc) + { + for (int i = 0; i < tparams.Length; i++) { + if (ignore_inferred_dynamic && targs[i].BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + var targ = targs[i]; + if (!CheckConstraint (context, targ, tparams [i], loc)) + return false; + + if (!recursive_checks) + continue; + + if (!Check (mc, targ, loc)) + return false; + } + + return true; + } + + bool CheckConstraint (MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc) + { + // + // First, check the `class' and `struct' constraints. + // + if (tparam.HasSpecialClass && !TypeSpec.IsReferenceType (atype)) { + if (mc != null) { + mc.Module.Compiler.Report.Error (452, loc, + "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + + return false; + } + + if (tparam.HasSpecialStruct && (!TypeSpec.IsValueType (atype) || atype.IsNullableType)) { + if (mc != null) { + mc.Module.Compiler.Report.Error (453, loc, + "The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + + return false; + } + + bool ok = true; + + // + // Check the class constraint + // + if (tparam.HasTypeConstraint) { + var dep = tparam.BaseType.GetMissingDependencies (); + if (dep != null) { + if (mc == null) + return false; + + ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc); + ok = false; + } + + if (!CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + + // + // Check the interfaces constraints + // + if (tparam.Interfaces != null) { + if (atype.IsNullableType) { + if (mc == null) + return false; + + mc.Module.Compiler.Report.Error (313, loc, + "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint", + atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ()); + ok = false; + } else { + foreach (TypeSpec iface in tparam.Interfaces) { + var dep = iface.GetMissingDependencies (); + if (dep != null) { + if (mc == null) + return false; + + ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc); + ok = false; + + // return immediately to avoid duplicate errors because we are scanning + // expanded interface list + return false; + } + + if (!CheckConversion (mc, context, atype, tparam, iface, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + } + } + + // + // Check the type parameter constraint + // + if (tparam.TypeArguments != null) { + foreach (var ta in tparam.TypeArguments) { + if (!CheckConversion (mc, context, atype, tparam, ta, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + } + + // + // Finally, check the constructor constraint. + // + if (!tparam.HasSpecialConstructor) + return ok; + + if (!HasDefaultConstructor (atype)) { + if (mc != null) { + mc.Module.Compiler.Report.SymbolRelatedToPreviousError (atype); + mc.Module.Compiler.Report.Error (310, loc, + "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + return false; + } + + return ok; + } + + static bool HasDynamicTypeArgument (TypeSpec[] targs) + { + for (int i = 0; i < targs.Length; ++i) { + var targ = targs [i]; + if (targ.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (HasDynamicTypeArgument (targ.TypeArguments)) + return true; + } + + return false; + } + + bool CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc) + { + if (atype == ttype) + return true; + + if (atype.IsGenericParameter) { + var tps = (TypeParameterSpec) atype; + if (Convert.ImplicitTypeParameterConversion (null, tps, ttype) != null) + return true; + + // + // LAMESPEC: Identity conversion with inflated type parameter + // It's not clear from the spec what rule should apply to inherited + // inflated type parameter. The specification allows only type parameter + // conversion but that's clearly not enough + // + if (tps.HasTypeConstraint && tps.BaseType == ttype) + return true; + + } else if (TypeSpec.IsValueType (atype)) { + if (Convert.ImplicitBoxingConversion (null, atype, ttype) != null) + return true; + } else { + var expr = new EmptyExpression (atype); + if (Convert.ImplicitStandardConversionExists (expr, ttype)) + return true; + } + + // + // When partial/full type inference finds a dynamic type argument delay + // the constraint check to runtime, it can succeed for real underlying + // dynamic type + // + if (ignore_inferred_dynamic && HasDynamicTypeArgument (ttype.TypeArguments)) + return true; + + if (mc != null) { + mc.Module.Compiler.Report.SymbolRelatedToPreviousError (tparam); + if (atype.IsGenericParameter) { + mc.Module.Compiler.Report.Error (314, loc, + "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'", + atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); + } else if (TypeSpec.IsValueType (atype)) { + mc.Module.Compiler.Report.Error (315, loc, + "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'", + atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); + } else { + mc.Module.Compiler.Report.Error (311, loc, + "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'", + atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); + } + } + + return false; + } + + bool HasDefaultConstructor (TypeSpec atype) + { + var tp = atype as TypeParameterSpec; + if (tp != null) { + return tp.HasSpecialConstructor || tp.HasSpecialStruct; + } + + if (atype.IsStruct || atype.IsEnum) + return true; + + if (atype.IsAbstract) + return false; + + var tdef = atype.GetDefinition (); + + var found = MemberCache.FindMember (tdef, + MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), + BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly); + + return found != null && (found.Modifiers & Modifiers.PUBLIC) != 0; + } + } + + /// + /// A generic method definition. + /// + public class GenericMethod : DeclSpace + { + ParametersCompiled parameters; + + public GenericMethod (NamespaceContainer ns, DeclSpace parent, MemberName name, + FullNamedExpression return_type, ParametersCompiled parameters) + : base (ns, parent, name, null) + { + this.parameters = parameters; + } + + public GenericMethod (NamespaceContainer ns, DeclSpace parent, MemberName name, TypeParameter[] tparams, + FullNamedExpression return_type, ParametersCompiled parameters) + : this (ns, parent, name, return_type, parameters) + { + this.type_params = tparams; + } + + public override TypeParameter[] CurrentTypeParameters { + get { + return base.type_params; + } + } + + protected override TypeAttributes TypeAttr { + get { + throw new NotSupportedException (); + } + } + + public override void DefineType () + { + throw new Exception (); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + throw new NotSupportedException (); + } + + public override bool Define () + { + throw new NotSupportedException (); + } + + /// + /// Define and resolve the type parameters. + /// We're called from Method.Define(). + /// + public bool Define (MethodOrOperator m) + { + TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations (); + string[] snames = new string [names.Length]; + var block = m.Block; + for (int i = 0; i < names.Length; i++) { + string type_argument_name = names[i].Name; + + if (block == null) { + int idx = parameters.GetParameterIndexByName (type_argument_name); + if (idx >= 0) { + var b = m.Block; + if (b == null) + b = new ToplevelBlock (Compiler, Location); + + b.Error_AlreadyDeclaredTypeParameter (type_argument_name, parameters[i].Location); + } + } else { + INamedBlockVariable variable = null; + block.GetLocalName (type_argument_name, m.Block, ref variable); + if (variable != null) + variable.Block.Error_AlreadyDeclaredTypeParameter (type_argument_name, variable.Location); + } + + snames[i] = type_argument_name; + } + + GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames); + for (int i = 0; i < TypeParameters.Length; i++) + TypeParameters [i].Define (gen_params [i], null); + + return true; + } + + public void EmitAttributes () + { + if (OptAttributes != null) + OptAttributes.Emit (); + } + + public override string GetSignatureForError () + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method | AttributeTargets.ReturnValue; + } + } + + public override string DocCommentHeader { + get { return "M:"; } + } + + public new void VerifyClsCompliance () + { + foreach (TypeParameter tp in TypeParameters) { + tp.VerifyClsCompliance (); + } + } + } + + public partial class TypeManager + { + public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member) + { + var tp = t as TypeParameterSpec; + if (tp != null) { + Variance v = tp.Variance; + if (expected == Variance.None && v != expected || + expected == Variance.Covariant && v == Variance.Contravariant || + expected == Variance.Contravariant && v == Variance.Covariant) { + ((TypeParameter)tp.MemberDefinition).ErrorInvalidVariance (member, expected); + } + + return expected; + } + + if (t.TypeArguments.Length > 0) { + var targs_definition = t.MemberDefinition.TypeParameters; + TypeSpec[] targs = GetTypeArguments (t); + for (int i = 0; i < targs.Length; ++i) { + Variance v = targs_definition[i].Variance; + CheckTypeVariance (targs[i], (Variance) ((int)v * (int)expected), member); + } + + return expected; + } + + if (t.IsArray) + return CheckTypeVariance (GetElementType (t), expected, member); + + return Variance.None; + } + } + + // + // Implements C# type inference + // + class TypeInference + { + // + // Tracks successful rate of type inference + // + int score = int.MaxValue; + readonly Arguments arguments; + readonly int arg_count; + + public TypeInference (Arguments arguments) + { + this.arguments = arguments; + if (arguments != null) + arg_count = arguments.Count; + } + + public int InferenceScore { + get { + return score; + } + } + + public TypeSpec[] InferMethodArguments (ResolveContext ec, MethodSpec method) + { + var method_generic_args = method.GenericDefinition.TypeParameters; + TypeInferenceContext context = new TypeInferenceContext (method_generic_args); + if (!context.UnfixedVariableExists) + return TypeSpec.EmptyTypes; + + AParametersCollection pd = method.Parameters; + if (!InferInPhases (ec, context, pd)) + return null; + + return context.InferredTypeArguments; + } + + // + // Implements method type arguments inference + // + bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersCollection methodParameters) + { + int params_arguments_start; + if (methodParameters.HasParams) { + params_arguments_start = methodParameters.Count - 1; + } else { + params_arguments_start = arg_count; + } + + TypeSpec [] ptypes = methodParameters.Types; + + // + // The first inference phase + // + TypeSpec method_parameter = null; + for (int i = 0; i < arg_count; i++) { + Argument a = arguments [i]; + if (a == null) + continue; + + if (i < params_arguments_start) { + method_parameter = methodParameters.Types [i]; + } else if (i == params_arguments_start) { + if (arg_count == params_arguments_start + 1 && TypeManager.HasElementType (a.Type)) + method_parameter = methodParameters.Types [params_arguments_start]; + else + method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]); + + ptypes = (TypeSpec[]) ptypes.Clone (); + ptypes [i] = method_parameter; + } + + // + // When a lambda expression, an anonymous method + // is used an explicit argument type inference takes a place + // + AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression; + if (am != null) { + if (am.ExplicitTypeInference (ec, tic, method_parameter)) + --score; + continue; + } + + if (a.IsByRef) { + score -= tic.ExactInference (a.Type, method_parameter); + continue; + } + + if (a.Expr.Type == InternalType.NullLiteral) + continue; + + if (TypeSpec.IsValueType (method_parameter)) { + score -= tic.LowerBoundInference (a.Type, method_parameter); + continue; + } + + // + // Otherwise an output type inference is made + // + score -= tic.OutputTypeInference (ec, a.Expr, method_parameter); + } + + // + // Part of the second phase but because it happens only once + // we don't need to call it in cycle + // + bool fixed_any = false; + if (!tic.FixIndependentTypeArguments (ec, ptypes, ref fixed_any)) + return false; + + return DoSecondPhase (ec, tic, ptypes, !fixed_any); + } + + bool DoSecondPhase (ResolveContext ec, TypeInferenceContext tic, TypeSpec[] methodParameters, bool fixDependent) + { + bool fixed_any = false; + if (fixDependent && !tic.FixDependentTypes (ec, ref fixed_any)) + return false; + + // If no further unfixed type variables exist, type inference succeeds + if (!tic.UnfixedVariableExists) + return true; + + if (!fixed_any && fixDependent) + return false; + + // For all arguments where the corresponding argument output types + // contain unfixed type variables but the input types do not, + // an output type inference is made + for (int i = 0; i < arg_count; i++) { + + // Align params arguments + TypeSpec t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i]; + + if (!TypeManager.IsDelegateType (t_i)) { + if (!t_i.IsExpressionTreeType) + continue; + + t_i = TypeManager.GetTypeArguments (t_i) [0]; + } + + var mi = Delegate.GetInvokeMethod (t_i); + TypeSpec rtype = mi.ReturnType; + + if (tic.IsReturnTypeNonDependent (ec, mi, rtype)) + score -= tic.OutputTypeInference (ec, arguments [i].Expr, t_i); + } + + + return DoSecondPhase (ec, tic, methodParameters, true); + } + } + + public class TypeInferenceContext + { + protected enum BoundKind + { + Exact = 0, + Lower = 1, + Upper = 2 + } + + protected class BoundInfo : IEquatable + { + public readonly TypeSpec Type; + public readonly BoundKind Kind; + + public BoundInfo (TypeSpec type, BoundKind kind) + { + this.Type = type; + this.Kind = kind; + } + + public override int GetHashCode () + { + return Type.GetHashCode (); + } + + public virtual Expression GetTypeExpression () + { + return new TypeExpression (Type, Location.Null); + } + + #region IEquatable Members + + public virtual bool Equals (BoundInfo other) + { + return Type == other.Type && Kind == other.Kind; + } + + #endregion + } + + readonly TypeSpec[] tp_args; + readonly TypeSpec[] fixed_types; + readonly List[] bounds; + bool failed; + + // TODO MemberCache: Could it be TypeParameterSpec[] ?? + public TypeInferenceContext (TypeSpec[] typeArguments) + { + if (typeArguments.Length == 0) + throw new ArgumentException ("Empty generic arguments"); + + fixed_types = new TypeSpec [typeArguments.Length]; + for (int i = 0; i < typeArguments.Length; ++i) { + if (typeArguments [i].IsGenericParameter) { + if (bounds == null) { + bounds = new List [typeArguments.Length]; + tp_args = new TypeSpec [typeArguments.Length]; + } + tp_args [i] = typeArguments [i]; + } else { + fixed_types [i] = typeArguments [i]; + } + } + } + + // + // Used together with AddCommonTypeBound fo implement + // 7.4.2.13 Finding the best common type of a set of expressions + // + public TypeInferenceContext () + { + fixed_types = new TypeSpec [1]; + tp_args = new TypeSpec [1]; + tp_args[0] = InternalType.Arglist; // it can be any internal type + bounds = new List [1]; + } + + public TypeSpec[] InferredTypeArguments { + get { + return fixed_types; + } + } + + public void AddCommonTypeBound (TypeSpec type) + { + AddToBounds (new BoundInfo (type, BoundKind.Lower), 0); + } + + protected void AddToBounds (BoundInfo bound, int index) + { + // + // Some types cannot be used as type arguments + // + if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || + bound.Type == InternalType.MethodGroup) + return; + + var a = bounds [index]; + if (a == null) { + a = new List (2); + a.Add (bound); + bounds [index] = a; + return; + } + + if (a.Contains (bound)) + return; + + a.Add (bound); + } + + bool AllTypesAreFixed (TypeSpec[] types) + { + foreach (TypeSpec t in types) { + if (t.IsGenericParameter) { + if (!IsFixed (t)) + return false; + continue; + } + + if (TypeManager.IsGenericType (t)) + return AllTypesAreFixed (TypeManager.GetTypeArguments (t)); + } + + return true; + } + + // + // 26.3.3.8 Exact Inference + // + public int ExactInference (TypeSpec u, TypeSpec v) + { + // If V is an array type + if (v.IsArray) { + if (!u.IsArray) + return 0; + + // TODO MemberCache: GetMetaInfo () + if (u.GetMetaInfo ().GetArrayRank () != v.GetMetaInfo ().GetArrayRank ()) + return 0; + + return ExactInference (TypeManager.GetElementType (u), TypeManager.GetElementType (v)); + } + + // If V is constructed type and U is constructed type + if (TypeManager.IsGenericType (v)) { + if (!TypeManager.IsGenericType (u)) + return 0; + + TypeSpec [] ga_u = TypeManager.GetTypeArguments (u); + TypeSpec [] ga_v = TypeManager.GetTypeArguments (v); + if (ga_u.Length != ga_v.Length) + return 0; + + int score = 0; + for (int i = 0; i < ga_u.Length; ++i) + score += ExactInference (ga_u [i], ga_v [i]); + + return score > 0 ? 1 : 0; + } + + // If V is one of the unfixed type arguments + int pos = IsUnfixed (v); + if (pos == -1) + return 0; + + AddToBounds (new BoundInfo (u, BoundKind.Exact), pos); + return 1; + } + + public bool FixAllTypes (ResolveContext ec) + { + for (int i = 0; i < tp_args.Length; ++i) { + if (!FixType (ec, i)) + return false; + } + return true; + } + + // + // All unfixed type variables Xi are fixed for which all of the following hold: + // a, There is at least one type variable Xj that depends on Xi + // b, Xi has a non-empty set of bounds + // + public bool FixDependentTypes (ResolveContext ec, ref bool fixed_any) + { + for (int i = 0; i < tp_args.Length; ++i) { + if (fixed_types[i] != null) + continue; + + if (bounds[i] == null) + continue; + + if (!FixType (ec, i)) + return false; + + fixed_any = true; + } + + return true; + } + + // + // All unfixed type variables Xi which depend on no Xj are fixed + // + public bool FixIndependentTypeArguments (ResolveContext ec, TypeSpec[] methodParameters, ref bool fixed_any) + { + var types_to_fix = new List (tp_args); + for (int i = 0; i < methodParameters.Length; ++i) { + TypeSpec t = methodParameters[i]; + + if (!TypeManager.IsDelegateType (t)) { + if (!t.IsExpressionTreeType) + continue; + + t = TypeManager.GetTypeArguments (t) [0]; + } + + if (t.IsGenericParameter) + continue; + + var invoke = Delegate.GetInvokeMethod (t); + TypeSpec rtype = invoke.ReturnType; + while (rtype.IsArray) + rtype = ((ArrayContainer) rtype).Element; + + if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype)) + continue; + + // Remove dependent types, they cannot be fixed yet + RemoveDependentTypes (types_to_fix, rtype); + } + + foreach (TypeSpec t in types_to_fix) { + if (t == null) + continue; + + int idx = IsUnfixed (t); + if (idx >= 0 && !FixType (ec, idx)) { + return false; + } + } + + fixed_any = types_to_fix.Count > 0; + return true; + } + + // + // 26.3.3.10 Fixing + // + public bool FixType (ResolveContext ec, int i) + { + // It's already fixed + if (fixed_types[i] != null) + throw new InternalErrorException ("Type argument has been already fixed"); + + if (failed) + return false; + + var candidates = bounds [i]; + if (candidates == null) + return false; + + if (candidates.Count == 1) { + TypeSpec t = candidates[0].Type; + if (t == InternalType.NullLiteral) + return false; + + fixed_types [i] = t; + return true; + } + + // + // Determines a unique type from which there is + // a standard implicit conversion to all the other + // candidate types. + // + TypeSpec best_candidate = null; + int cii; + int candidates_count = candidates.Count; + for (int ci = 0; ci < candidates_count; ++ci) { + BoundInfo bound = candidates [ci]; + for (cii = 0; cii < candidates_count; ++cii) { + if (cii == ci) + continue; + + BoundInfo cbound = candidates[cii]; + + // Same type parameters with different bounds + if (cbound.Type == bound.Type) { + if (bound.Kind != BoundKind.Exact) + bound = cbound; + + continue; + } + + if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) { + if (cbound.Kind == BoundKind.Lower) { + if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) { + break; + } + + continue; + } + if (cbound.Kind == BoundKind.Upper) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + continue; + } + + if (bound.Kind != BoundKind.Exact) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + bound = cbound; + continue; + } + + break; + } + + if (bound.Kind == BoundKind.Lower) { + if (cbound.Kind == BoundKind.Lower) { + if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) { + break; + } + } else { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + bound = cbound; + } + + continue; + } + + if (bound.Kind == BoundKind.Upper) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + } else { + throw new NotImplementedException ("variance conversion"); + } + } + + if (cii != candidates_count) + continue; + + // + // We already have the best candidate, break if thet are different + // + // Dynamic is never ambiguous as we prefer dynamic over other best candidate types + // + if (best_candidate != null) { + + if (best_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + if (bound.Type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && best_candidate != bound.Type) + return false; + } + + best_candidate = bound.Type; + } + + if (best_candidate == null) + return false; + + fixed_types[i] = best_candidate; + return true; + } + + public bool HasBounds (int pos) + { + return bounds[pos] != null; + } + + // + // Uses inferred or partially infered types to inflate delegate type argument. Returns + // null when type parameter has not been fixed + // + public TypeSpec InflateGenericArgument (IModuleContext context, TypeSpec parameter) + { + var tp = parameter as TypeParameterSpec; + if (tp != null) { + // + // Type inference works on generic arguments (MVAR) only + // + if (!tp.IsMethodOwned) + return parameter; + + // + // Ensure the type parameter belongs to same container + // + if (tp.DeclaredPosition < tp_args.Length && tp_args[tp.DeclaredPosition] == parameter) + return fixed_types[tp.DeclaredPosition] ?? parameter; + + return parameter; + } + + var gt = parameter as InflatedTypeSpec; + if (gt != null) { + var inflated_targs = new TypeSpec [gt.TypeArguments.Length]; + for (int ii = 0; ii < inflated_targs.Length; ++ii) { + var inflated = InflateGenericArgument (context, gt.TypeArguments [ii]); + if (inflated == null) + return null; + + inflated_targs[ii] = inflated; + } + + return gt.GetDefinition ().MakeGenericType (context, inflated_targs); + } + + return parameter; + } + + // + // Tests whether all delegate input arguments are fixed and generic output type + // requires output type inference + // + public bool IsReturnTypeNonDependent (ResolveContext ec, MethodSpec invoke, TypeSpec returnType) + { + while (returnType.IsArray) + returnType = ((ArrayContainer) returnType).Element; + + if (returnType.IsGenericParameter) { + if (IsFixed (returnType)) + return false; + } else if (TypeManager.IsGenericType (returnType)) { + if (TypeManager.IsDelegateType (returnType)) { + invoke = Delegate.GetInvokeMethod (returnType); + return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType); + } + + TypeSpec[] g_args = TypeManager.GetTypeArguments (returnType); + + // At least one unfixed return type has to exist + if (AllTypesAreFixed (g_args)) + return false; + } else { + return false; + } + + // All generic input arguments have to be fixed + AParametersCollection d_parameters = invoke.Parameters; + return AllTypesAreFixed (d_parameters.Types); + } + + bool IsFixed (TypeSpec type) + { + return IsUnfixed (type) == -1; + } + + int IsUnfixed (TypeSpec type) + { + if (!type.IsGenericParameter) + return -1; + + for (int i = 0; i < tp_args.Length; ++i) { + if (tp_args[i] == type) { + if (fixed_types[i] != null) + break; + + return i; + } + } + + return -1; + } + + // + // 26.3.3.9 Lower-bound Inference + // + public int LowerBoundInference (TypeSpec u, TypeSpec v) + { + return LowerBoundInference (u, v, false); + } + + // + // Lower-bound (false) or Upper-bound (true) inference based on inversed argument + // + int LowerBoundInference (TypeSpec u, TypeSpec v, bool inversed) + { + // If V is one of the unfixed type arguments + int pos = IsUnfixed (v); + if (pos != -1) { + AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos); + return 1; + } + + // If U is an array type + var u_ac = u as ArrayContainer; + if (u_ac != null) { + var v_ac = v as ArrayContainer; + if (v_ac != null) { + if (u_ac.Rank != v_ac.Rank) + return 0; + + if (TypeSpec.IsValueType (u_ac.Element)) + return ExactInference (u_ac.Element, v_ac.Element); + + return LowerBoundInference (u_ac.Element, v_ac.Element, inversed); + } + + if (u_ac.Rank != 1 || !v.IsGenericIterateInterface) + return 0; + + var v_i = TypeManager.GetTypeArguments (v) [0]; + if (TypeSpec.IsValueType (u_ac.Element)) + return ExactInference (u_ac.Element, v_i); + + return LowerBoundInference (u_ac.Element, v_i); + } + + if (TypeManager.IsGenericType (v)) { + // + // if V is a constructed type C and there is a unique type C + // such that U is identical to, inherits from (directly or indirectly), + // or implements (directly or indirectly) C + // + var u_candidates = new List (); + var open_v = v.MemberDefinition; + + for (TypeSpec t = u; t != null; t = t.BaseType) { + if (open_v == t.MemberDefinition) + u_candidates.Add (t); + + // + // Using this trick for dynamic type inference, the spec says the type arguments are "unknown" but + // that would complicate the process a lot, instead I treat them as dynamic + // + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + u_candidates.Add (t); + + if (t.Interfaces != null) { + foreach (var iface in t.Interfaces) { + if (open_v == iface.MemberDefinition) + u_candidates.Add (iface); + } + } + } + + TypeSpec [] unique_candidate_targs = null; + TypeSpec[] ga_v = TypeManager.GetTypeArguments (v); + foreach (TypeSpec u_candidate in u_candidates) { + // + // The unique set of types U1..Uk means that if we have an interface I, + // class U : I, I then no type inference is made when inferring + // type I by applying type U because T could be int or long + // + if (unique_candidate_targs != null) { + TypeSpec[] second_unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate); + if (TypeSpecComparer.Equals (unique_candidate_targs, second_unique_candidate_targs)) { + unique_candidate_targs = second_unique_candidate_targs; + continue; + } + + // + // This should always cause type inference failure + // + failed = true; + return 1; + } + + // + // A candidate is dynamic type expression, to simplify things use dynamic + // for all type parameter of this type. For methods like this one + // + // void M (IList, IList) + // + // dynamic becomes both T and U when the arguments are of dynamic type + // + if (u_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + unique_candidate_targs = new TypeSpec[ga_v.Length]; + for (int i = 0; i < unique_candidate_targs.Length; ++i) + unique_candidate_targs[i] = u_candidate; + } else { + unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate); + } + } + + if (unique_candidate_targs != null) { + var ga_open_v = open_v.TypeParameters; + int score = 0; + for (int i = 0; i < unique_candidate_targs.Length; ++i) { + Variance variance = ga_open_v [i].Variance; + + TypeSpec u_i = unique_candidate_targs [i]; + if (variance == Variance.None || TypeSpec.IsValueType (u_i)) { + if (ExactInference (u_i, ga_v [i]) == 0) + ++score; + } else { + bool upper_bound = (variance == Variance.Contravariant && !inversed) || + (variance == Variance.Covariant && inversed); + + if (LowerBoundInference (u_i, ga_v [i], upper_bound) == 0) + ++score; + } + } + return score; + } + } + + return 0; + } + + // + // 26.3.3.6 Output Type Inference + // + public int OutputTypeInference (ResolveContext ec, Expression e, TypeSpec t) + { + // If e is a lambda or anonymous method with inferred return type + AnonymousMethodExpression ame = e as AnonymousMethodExpression; + if (ame != null) { + TypeSpec rt = ame.InferReturnType (ec, this, t); + var invoke = Delegate.GetInvokeMethod (t); + + if (rt == null) { + AParametersCollection pd = invoke.Parameters; + return ame.Parameters.Count == pd.Count ? 1 : 0; + } + + TypeSpec rtype = invoke.ReturnType; + return LowerBoundInference (rt, rtype) + 1; + } + + // + // if E is a method group and T is a delegate type or expression tree type + // return type Tb with parameter types T1..Tk and return type Tb, and overload + // resolution of E with the types T1..Tk yields a single method with return type U, + // then a lower-bound inference is made from U for Tb. + // + if (e is MethodGroupExpr) { + if (!TypeManager.IsDelegateType (t)) { + if (!t.IsExpressionTreeType) + return 0; + + t = TypeManager.GetTypeArguments (t)[0]; + } + + var invoke = Delegate.GetInvokeMethod (t); + TypeSpec rtype = invoke.ReturnType; + + if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype)) + return 0; + + // LAMESPEC: Standard does not specify that all methodgroup arguments + // has to be fixed but it does not specify how to do recursive type inference + // either. We choose the simple option and infer return type only + // if all delegate generic arguments are fixed. + TypeSpec[] param_types = new TypeSpec [invoke.Parameters.Count]; + for (int i = 0; i < param_types.Length; ++i) { + var inflated = InflateGenericArgument (ec, invoke.Parameters.Types[i]); + if (inflated == null) + return 0; + + if (IsUnfixed (inflated) >= 0) + return 0; + + param_types[i] = inflated; + } + + MethodGroupExpr mg = (MethodGroupExpr) e; + Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, param_types, e.Location); + mg = mg.OverloadResolve (ec, ref args, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly); + if (mg == null) + return 0; + + return LowerBoundInference (mg.BestCandidateReturnType, rtype) + 1; + } + + // + // if e is an expression with type U, then + // a lower-bound inference is made from U for T + // + return LowerBoundInference (e.Type, t) * 2; + } + + void RemoveDependentTypes (List types, TypeSpec returnType) + { + int idx = IsUnfixed (returnType); + if (idx >= 0) { + types [idx] = null; + return; + } + + if (TypeManager.IsGenericType (returnType)) { + foreach (TypeSpec t in TypeManager.GetTypeArguments (returnType)) { + RemoveDependentTypes (types, t); + } + } + } + + public bool UnfixedVariableExists { + get { + foreach (TypeSpec ut in fixed_types) { + if (ut == null) + return true; + } + + return false; + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj new file mode 100644 index 0000000000..b371739189 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj @@ -0,0 +1,111 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56} + Library + Properties + gmcs + gmcs + v3.5 + 512 + + + true + full + false + ..\..\..\monodevelop\main\build\bin + TRACE;DEBUG;NET_2_0;MS_COMPATIBLE;FULL_AST;BOOTSTRAP_BASIC + prompt + 4 + false + + + pdbonly + true + TRACE;NET_2_0;MS_COMPATIBLE + prompt + TRACE;NET_2_0;MS_COMPATIBLE + prompt + 4 + ..\..\..\monodevelop\main\build\bin + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config new file mode 100644 index 0000000000..4b560e2f7a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources new file mode 100644 index 0000000000..03738c5032 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources @@ -0,0 +1,56 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc.cs +doc-bootstrap.cs +driver.cs +dynamic.cs +ecore.cs +enum.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +visit.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs +../tools/monop/outline.cs diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln new file mode 100644 index 0000000000..9977cd02f5 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gmcs", "gmcs.csproj", "{D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs new file mode 100644 index 0000000000..1231ec7060 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj new file mode 100644 index 0000000000..26a8030e8d --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj @@ -0,0 +1,29 @@ + + + + Exe + gmcs + v3.5 + gmcs.exe.sources + 65001 + ..\class\lib\basic\ + false + + + BOOTSTRAP_BASIC,NET_1_1,NET_2_0 + + + NET_1_1,NET_2_0 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs new file mode 100644 index 0000000000..137c5ccb38 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs @@ -0,0 +1,2096 @@ +// +// import.cs: System.Reflection conversions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009, 2010 Novell, Inc +// + +using System; +using System.Runtime.CompilerServices; +using System.Linq; +using System.Collections.Generic; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public abstract class MetadataImporter + { + // + // Dynamic types reader with additional logic to reconstruct a dynamic + // type using DynamicAttribute values + // + struct DynamicTypeReader + { + static readonly bool[] single_attribute = { true }; + + public int Position; + bool[] flags; + + // There is no common type for CustomAttributeData and we cannot + // use ICustomAttributeProvider + object provider; + + // + // A member provider which can be used to get CustomAttributeData + // + public DynamicTypeReader (object provider) + { + Position = 0; + flags = null; + this.provider = provider; + } + + // + // Returns true when object at local position has dynamic attribute flag + // + public bool IsDynamicObject (MetadataImporter importer) + { + if (provider != null) + ReadAttribute (importer); + + return flags != null && Position < flags.Length && flags[Position]; + } + + // + // Returns true when DynamicAttribute exists + // + public bool HasDynamicAttribute (MetadataImporter importer) + { + if (provider != null) + ReadAttribute (importer); + + return flags != null; + } + + void ReadAttribute (MetadataImporter importer) + { + IList cad; + if (provider is MemberInfo) { + cad = CustomAttributeData.GetCustomAttributes ((MemberInfo) provider); + } else if (provider is ParameterInfo) { + cad = CustomAttributeData.GetCustomAttributes ((ParameterInfo) provider); + } else { + provider = null; + return; + } + + if (cad.Count > 0) { + foreach (var ca in cad) { + var dt = ca.Constructor.DeclaringType; + if (dt.Name != "DynamicAttribute" && dt.Namespace != CompilerServicesNamespace) + continue; + + if (ca.ConstructorArguments.Count == 0) { + flags = single_attribute; + break; + } + + var arg_type = ca.ConstructorArguments[0].ArgumentType; + + if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) { + var carg = (IList) ca.ConstructorArguments[0].Value; + flags = new bool[carg.Count]; + for (int i = 0; i < flags.Length; ++i) { + if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean) + flags[i] = (bool) carg[i].Value; + } + + break; + } + } + } + + provider = null; + } + } + + protected readonly Dictionary import_cache; + protected readonly Dictionary compiled_types; + protected readonly Dictionary assembly_2_definition; + readonly ModuleContainer module; + + public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices"; + + protected MetadataImporter (ModuleContainer module) + { + this.module = module; + + import_cache = new Dictionary (1024, ReferenceEquality.Default); + compiled_types = new Dictionary (40, ReferenceEquality.Default); + assembly_2_definition = new Dictionary (ReferenceEquality.Default); + IgnorePrivateMembers = true; + } + + #region Properties + + public ICollection Assemblies { + get { + return assembly_2_definition.Values; + } + } + + public bool IgnorePrivateMembers { get; set; } + + #endregion + + public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec); + protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType); + protected abstract bool HasVolatileModifier (MetaType[] modifiers); + + public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) + { + Modifiers mod = 0; + var fa = fi.Attributes; + switch (fa & FieldAttributes.FieldAccessMask) { + case FieldAttributes.Public: + mod = Modifiers.PUBLIC; + break; + case FieldAttributes.Assembly: + mod = Modifiers.INTERNAL; + break; + case FieldAttributes.Family: + mod = Modifiers.PROTECTED; + break; + case FieldAttributes.FamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + // Ignore private fields (even for error reporting) to not require extra dependencies + if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) + return null; + + mod = Modifiers.PRIVATE; + break; + } + + TypeSpec field_type; + + try { + field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi)); + } catch (Exception e) { + // TODO: I should construct fake TypeSpec based on TypeRef signature + // but there is no way to do it with System.Reflection + throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'", + declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly); + } + + var definition = new ImportedMemberDefinition (fi, field_type, this); + + if ((fa & FieldAttributes.Literal) != 0) { + var c = Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null); + return new ConstSpec (declaringType, definition, field_type, fi, mod, c); + } + + if ((fa & FieldAttributes.InitOnly) != 0) { + if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi)); + if (dc != null) + return new ConstSpec (declaringType, definition, field_type, fi, mod, dc); + } + + mod |= Modifiers.READONLY; + } else { + var req_mod = fi.GetRequiredCustomModifiers (); + if (req_mod.Length > 0 && HasVolatileModifier (req_mod)) + mod |= Modifiers.VOLATILE; + } + + if ((fa & FieldAttributes.Static) != 0) { + mod |= Modifiers.STATIC; + } else { + // Fixed buffers cannot be static + if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested && + HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) { + + // TODO: Sanity check on field_type (only few types are allowed) + var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); + return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); + } + } + + return new FieldSpec (declaringType, definition, field_type, fi, mod); + } + + public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove) + { + add.IsAccessor = true; + remove.IsAccessor = true; + + if (add.Modifiers != remove.Modifiers) + throw new NotImplementedException ("Different accessor modifiers " + ei.Name); + + var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei)); + var definition = new ImportedMemberDefinition (ei, event_type, this); + return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove); + } + + TypeParameterSpec[] CreateGenericParameters (MetaType type, TypeSpec declaringType) + { + var tparams = type.GetGenericArguments (); + + int parent_owned_count; + if (type.IsNested) { + parent_owned_count = type.DeclaringType.GetGenericArguments ().Length; + + // + // System.Reflection duplicates parent type parameters for each + // nested type with slightly modified properties (eg. different owner) + // This just makes things more complicated (think of cloned constraints) + // therefore we remap any nested type owned by parent using `type_cache' + // to the single TypeParameterSpec + // + if (declaringType != null && parent_owned_count > 0) { + int read_count = 0; + while (read_count != parent_owned_count) { + var tparams_count = declaringType.Arity; + if (tparams_count != 0) { + var parent_tp = declaringType.MemberDefinition.TypeParameters; + read_count += tparams_count; + for (int i = 0; i < tparams_count; i++) { + import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]); + } + } + + declaringType = declaringType.DeclaringType; + } + } + } else { + parent_owned_count = 0; + } + + if (tparams.Length - parent_owned_count == 0) + return null; + + return CreateGenericParameters (parent_owned_count, tparams); + } + + TypeParameterSpec[] CreateGenericParameters (int first, MetaType[] tparams) + { + var tspec = new TypeParameterSpec[tparams.Length - first]; + for (int pos = first; pos < tparams.Length; ++pos) { + var type = tparams[pos]; + int index = pos - first; + + tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false); + } + + return tspec; + } + + TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype) + { + ++dtype.Position; + + var tspec = new TypeSpec [tparams.Length - first]; + for (int pos = first; pos < tparams.Length; ++pos) { + var type = tparams[pos]; + int index = pos - first; + + TypeSpec spec; + if (type.HasElementType) { + var element = type.GetElementType (); + ++dtype.Position; + spec = ImportType (element, dtype); + + if (!type.IsArray) { + throw new NotImplementedException ("Unknown element type " + type.ToString ()); + } + + spec = ArrayContainer.MakeType (module, spec, type.GetArrayRank ()); + } else { + spec = CreateType (type, dtype, true); + + // + // We treat nested generic types as inflated internally where + // reflection uses type definition + // + // class A { + // IFoo> foo; // A is definition in this case + // } + // + // TODO: Is full logic from CreateType needed here as well? + // + if (!IsMissingType (type) && type.IsGenericTypeDefinition) { + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + spec = spec.MakeGenericType (module, targs); + } + } + + ++dtype.Position; + tspec[index] = spec; + } + + return tspec; + } + + public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType) + { + Modifiers mod = ReadMethodModifiers (mb, declaringType); + TypeParameterSpec[] tparams; + + var parameters = CreateParameters (declaringType, mb.GetParameters (), mb); + + if (mb.IsGenericMethod) { + if (!mb.IsGenericMethodDefinition) + throw new NotSupportedException ("assert"); + + tparams = CreateGenericParameters (0, mb.GetGenericArguments ()); + } else { + tparams = null; + } + + MemberKind kind; + TypeSpec returnType; + if (mb.MemberType == MemberTypes.Constructor) { + kind = MemberKind.Constructor; + returnType = module.Compiler.BuiltinTypes.Void; + } else { + // + // Detect operators and destructors + // + string name = mb.Name; + kind = MemberKind.Method; + if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) { + if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) { + if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') { + var op_type = Operator.GetType (name); + if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) { + kind = MemberKind.Operator; + } + } + } else if (parameters.IsEmpty && name == Destructor.MetadataName) { + kind = MemberKind.Destructor; + if (declaringType.BuiltinType == BuiltinTypeSpec.Type.Object) { + mod &= ~Modifiers.OVERRIDE; + mod |= Modifiers.VIRTUAL; + } + } + } + + var mi = (MethodInfo) mb; + returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter)); + + // Cannot set to OVERRIDE without full hierarchy checks + // this flag indicates that the method could be override + // but further validation is needed + if ((mod & Modifiers.OVERRIDE) != 0) { + bool is_real_override = false; + if (kind == MemberKind.Method && declaringType.BaseType != null) { + var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null); + var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None); + + // + // For imported class method do additional validation to be sure that metadata + // override flag was correct + // + // Difference between protected internal and protected is ok + // + const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL; + if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) { + is_real_override = true; + } + } + + if (!is_real_override) { + mod &= ~Modifiers.OVERRIDE; + if ((mod & Modifiers.SEALED) != 0) + mod &= ~Modifiers.SEALED; + else + mod |= Modifiers.VIRTUAL; + } + } + } + + IMemberDefinition definition; + if (tparams != null) { + var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this); + foreach (var tp in gmd.TypeParameters) { + ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ()); + } + + definition = gmd; + } else { + definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this); + } + + MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod); + if (tparams != null) + ms.IsGeneric = true; + + return ms; + } + + // + // Imports System.Reflection parameters + // + AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method) + { + int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0; + + if (pi.Length == 0 && varargs == 0) + return ParametersCompiled.EmptyReadOnlyParameters; + + TypeSpec[] types = new TypeSpec[pi.Length + varargs]; + IParameterData[] par = new IParameterData[pi.Length + varargs]; + bool is_params = false; + for (int i = 0; i < pi.Length; i++) { + ParameterInfo p = pi[i]; + Parameter.Modifier mod = 0; + Expression default_value = null; + if (p.ParameterType.IsByRef) { + if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out) + mod = Parameter.Modifier.OUT; + else + mod = Parameter.Modifier.REF; + + // + // Strip reference wrapping + // + var el = p.ParameterType.GetElementType (); + types[i] = ImportType (el, new DynamicTypeReader (p)); // TODO: 1-based positio to be csc compatible + } else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod && + HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) { + mod = Parameter.Modifier.This; + types[i] = ImportType (p.ParameterType); + } else { + types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p)); + + if (i >= pi.Length - 2 && types[i] is ArrayContainer) { + if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) { + mod = Parameter.Modifier.PARAMS; + is_params = true; + } + } + + if (!is_params && p.IsOptional) { + object value = p.RawDefaultValue; + var ptype = types[i]; + if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) { + if (value == null) { + default_value = Constant.CreateConstant (ptype, null, Location.Null); + } else { + default_value = ImportParameterConstant (value); + + if (ptype.IsEnum) { + default_value = new EnumConstant ((Constant) default_value, ptype); + } + } + } else if (value == Missing.Value) { + default_value = EmptyExpression.MissingValue; + } else if (value == null) { + default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null); + } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + default_value = ImportParameterConstant (value); + } + } + } + + par[i] = new ParameterData (p.Name, mod, default_value); + } + + if (varargs != 0) { + par[par.Length - 1] = new ArglistParameter (Location.Null); + types[types.Length - 1] = InternalType.Arglist; + } + + return method != null ? + new ParametersImported (par, types, varargs != 0, is_params) : + new ParametersImported (par, types, is_params); + } + + // + // Returns null when the property is not valid C# property + // + public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set) + { + Modifiers mod = 0; + AParametersCollection param = null; + TypeSpec type = null; + if (get != null) { + mod = get.Modifiers; + param = get.Parameters; + type = get.ReturnType; + } + + bool is_valid_property = true; + if (set != null) { + if (set.ReturnType.Kind != MemberKind.Void) + is_valid_property = false; + + var set_param_count = set.Parameters.Count - 1; + + if (set_param_count < 0) { + set_param_count = 0; + is_valid_property = false; + } + + var set_type = set.Parameters.Types[set_param_count]; + + if (mod == 0) { + AParametersCollection set_based_param; + + if (set_param_count == 0) { + set_based_param = ParametersCompiled.EmptyReadOnlyParameters; + } else { + // + // Create indexer parameters based on setter method parameters (the last parameter has to be removed) + // + var data = new IParameterData[set_param_count]; + var types = new TypeSpec[set_param_count]; + Array.Copy (set.Parameters.FixedParameters, data, set_param_count); + Array.Copy (set.Parameters.Types, types, set_param_count); + set_based_param = new ParametersImported (data, types, set.Parameters.HasParams); + } + + mod = set.Modifiers; + param = set_based_param; + type = set_type; + } else { + if (set_param_count != get.Parameters.Count) + is_valid_property = false; + + if (get.ReturnType != set_type) + is_valid_property = false; + + // Possible custom accessor modifiers + if ((mod & Modifiers.AccessibilityMask) != (set.Modifiers & Modifiers.AccessibilityMask)) { + var get_acc = mod & Modifiers.AccessibilityMask; + if (get_acc != Modifiers.PUBLIC) { + var set_acc = set.Modifiers & Modifiers.AccessibilityMask; + // If the accessor modifiers are not same, do extra restriction checks + if (get_acc != set_acc) { + var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc); + var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc); + if (get_restr && set_restr) { + is_valid_property = false; // Neither is more restrictive + } + + if (get_restr) { + mod &= ~Modifiers.AccessibilityMask; + mod |= set_acc; + } + } + } + } + } + } + + PropertySpec spec = null; + if (!param.IsEmpty) { + var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember (); + if (index_name == null) { + is_valid_property = false; + } else { + if (get != null) { + if (get.IsStatic) + is_valid_property = false; + if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } + if (set != null) { + if (set.IsStatic) + is_valid_property = false; + if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } + } + + if (is_valid_property) + spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod); + } + + if (spec == null) + spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, type, this), type, pi, mod); + + if (!is_valid_property) { + spec.IsNotCSharpCompatible = true; + return spec; + } + + if (set != null) + spec.Set = set; + if (get != null) + spec.Get = get; + + return spec; + } + + public TypeSpec CreateType (MetaType type) + { + return CreateType (type, new DynamicTypeReader (), true); + } + + public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType) + { + return CreateType (type, declaringType, new DynamicTypeReader (type), false); + } + + TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType) + { + TypeSpec declaring_type; + if (type.IsNested && !type.IsGenericParameter) + declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true); + else + declaring_type = null; + + return CreateType (type, declaring_type, dtype, canImportBaseType); + } + + TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) + { + TypeSpec spec; + if (import_cache.TryGetValue (type, out spec)) { + if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) { + if (dtype.IsDynamicObject (this)) + return module.Compiler.BuiltinTypes.Dynamic; + + return spec; + } + + if (!spec.IsGeneric || type.IsGenericTypeDefinition) + return spec; + + if (!dtype.HasDynamicAttribute (this)) + return spec; + + // We've found same object in the cache but this one has a dynamic custom attribute + // and it's most likely dynamic version of same type IFoo agains IFoo + // Do type resolve process again in that case + + // TODO: Handle cases where they still unify + } + + if (IsMissingType (type)) { + spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC); + spec.MemberCache = MemberCache.Empty; + import_cache.Add (type, spec); + return spec; + } + + if (type.IsGenericType && !type.IsGenericTypeDefinition) { + var type_def = type.GetGenericTypeDefinition (); + + // Generic type definition can also be forwarded + if (compiled_types.TryGetValue (type_def, out spec)) + return spec; + + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + if (declaringType == null) { + // Simple case, no nesting + spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType); + spec = spec.MakeGenericType (module, targs); + } else { + // + // Nested type case, converting .NET types like + // A`1.B`1.C`1 to typespec like + // A.B.C + // + var nested_hierarchy = new List (); + while (declaringType.IsNested) { + nested_hierarchy.Add (declaringType); + declaringType = declaringType.DeclaringType; + } + + int targs_pos = 0; + if (declaringType.Arity > 0) { + spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ()); + targs_pos = spec.Arity; + } else { + spec = declaringType; + } + + for (int i = nested_hierarchy.Count; i != 0; --i) { + var t = nested_hierarchy [i - 1]; + spec = MemberCache.FindNestedType (spec, t.Name, t.Arity); + if (t.Arity > 0) { + spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ()); + targs_pos += t.Arity; + } + } + + string name = type.Name; + int index = name.IndexOf ('`'); + if (index > 0) + name = name.Substring (0, index); + + spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos); + if (spec == null) + return null; + + if (spec.Arity > 0) { + spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ()); + } + } + + // Don't add generic type with dynamic arguments, they can interfere with same type + // using object type arguments + if (!spec.HasDynamicElement) { + + // Add to reading cache to speed up reading + if (!import_cache.ContainsKey (type)) + import_cache.Add (type, spec); + } + + return spec; + } + + Modifiers mod; + MemberKind kind; + + var ma = type.Attributes; + switch (ma & TypeAttributes.VisibilityMask) { + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + mod = Modifiers.PUBLIC; + break; + case TypeAttributes.NestedPrivate: + mod = Modifiers.PRIVATE; + break; + case TypeAttributes.NestedFamily: + mod = Modifiers.PROTECTED; + break; + case TypeAttributes.NestedFamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + mod = Modifiers.INTERNAL; + break; + } + + if ((ma & TypeAttributes.Interface) != 0) { + kind = MemberKind.Interface; + } else if (type.IsGenericParameter) { + kind = MemberKind.TypeParameter; + } else { + var base_type = type.BaseType; + if (base_type == null || (ma & TypeAttributes.Abstract) != 0) { + kind = MemberKind.Class; + } else { + kind = DetermineKindFromBaseType (base_type); + if (kind == MemberKind.Struct || kind == MemberKind.Delegate) { + mod |= Modifiers.SEALED; + } + } + + if (kind == MemberKind.Class) { + if ((ma & TypeAttributes.Sealed) != 0) { + mod |= Modifiers.SEALED; + if ((ma & TypeAttributes.Abstract) != 0) + mod |= Modifiers.STATIC; + } else if ((ma & TypeAttributes.Abstract) != 0) { + mod |= Modifiers.ABSTRACT; + } + } + } + + var definition = new ImportedTypeDefinition (type, this); + TypeSpec pt; + + if (kind == MemberKind.Enum) { + const BindingFlags underlying_member = BindingFlags.DeclaredOnly | + BindingFlags.Instance | + BindingFlags.Public | BindingFlags.NonPublic; + + var type_members = type.GetFields (underlying_member); + foreach (var type_member in type_members) { + spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod); + break; + } + + if (spec == null) + kind = MemberKind.Class; + + } else if (kind == MemberKind.TypeParameter) { + spec = CreateTypeParameter (type, declaringType); + } else if (type.IsGenericTypeDefinition) { + definition.TypeParameters = CreateGenericParameters (type, declaringType); + } else if (compiled_types.TryGetValue (type, out pt)) { + // + // Same type was found in inside compiled types. It's + // either build-in type or forward referenced typed + // which point into just compiled assembly. + // + spec = pt; + BuiltinTypeSpec bts = pt as BuiltinTypeSpec; + if (bts != null) + bts.SetDefinition (definition, type, mod); + } + + if (spec == null) + spec = new TypeSpec (kind, declaringType, definition, type, mod); + + import_cache.Add (type, spec); + + // + // Two stage setup as the base type can be inflated declaring type or + // another nested type inside same declaring type which has not been + // loaded, therefore we can import a base type of nested types once + // the types have been imported + // + if (canImportBaseType) + ImportTypeBase (spec, type); + + return spec; + } + + public IAssemblyDefinition GetAssemblyDefinition (Assembly assembly) + { + IAssemblyDefinition found; + if (!assembly_2_definition.TryGetValue (assembly, out found)) { + + // This can happen in dynamic context only + var def = new ImportedAssemblyDefinition (assembly); + assembly_2_definition.Add (assembly, def); + def.ReadAttributes (); + found = def; + } + + return found; + } + + public void ImportTypeBase (MetaType type) + { + TypeSpec spec = import_cache[type]; + if (spec != null) + ImportTypeBase (spec, type); + } + + TypeParameterSpec CreateTypeParameter (MetaType type, TypeSpec declaringType) + { + Variance variance; + switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) { + case GenericParameterAttributes.Covariant: + variance = Variance.Covariant; + break; + case GenericParameterAttributes.Contravariant: + variance = Variance.Contravariant; + break; + default: + variance = Variance.None; + break; + } + + SpecialConstraint special = SpecialConstraint.None; + var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + + if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) { + special |= SpecialConstraint.Struct; + } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) { + special = SpecialConstraint.Constructor; + } + + if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) { + special |= SpecialConstraint.Class; + } + + TypeParameterSpec spec; + var def = new ImportedTypeParameterDefinition (type, this); + if (type.DeclaringMethod != null) { + spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type); + } else { + spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type); + } + + return spec; + } + + // + // Test for a custom attribute type match. Custom attributes are not really predefined globaly + // they can be assembly specific therefore we do check based on names only + // + public bool HasAttribute (IList attributesData, string attrName, string attrNamespace) + { + if (attributesData.Count == 0) + return false; + + foreach (var attr in attributesData) { + var dt = attr.Constructor.DeclaringType; + if (dt.Name == attrName && dt.Namespace == attrNamespace) + return true; + } + + return false; + } + + void ImportTypeBase (TypeSpec spec, MetaType type) + { + if (spec.Kind == MemberKind.Interface) + spec.BaseType = module.Compiler.BuiltinTypes.Object; + else if (type.BaseType != null) { + TypeSpec base_type; + if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType) + base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true); + else + base_type = CreateType (type.BaseType); + + spec.BaseType = base_type; + } + + MetaType[] ifaces; +#if STATIC + ifaces = type.__GetDeclaredInterfaces (); + if (ifaces.Length != 0) { + foreach (var iface in ifaces) { + var it = CreateType (iface); + if (it == null) + continue; + + spec.AddInterface (it); + + // Unfortunately not all languages expand inherited interfaces + var bifaces = it.Interfaces; + if (bifaces != null) { + foreach (var biface in bifaces) { + spec.AddInterface (biface); + } + } + } + } + + if (spec.BaseType != null) { + var bifaces = spec.BaseType.Interfaces; + if (bifaces != null) { + foreach (var iface in bifaces) + spec.AddInterface (iface); + } + } +#else + ifaces = type.GetInterfaces (); + + if (ifaces.Length > 0) { + foreach (var iface in ifaces) { + spec.AddInterface (CreateType (iface)); + } + } +#endif + + if (spec.MemberDefinition.TypeParametersCount > 0) { + foreach (var tp in spec.MemberDefinition.TypeParameters) { + ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ()); + } + } + + } + + protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes) + { + Namespace ns = targetNamespace; + string prev_namespace = null; + foreach (var t in types) { + if (t == null) + continue; + + // Be careful not to trigger full parent type loading + if (t.MemberType == MemberTypes.NestedType) + continue; + + if (t.Name[0] == '<') + continue; + + var it = CreateType (t, null, new DynamicTypeReader (t), true); + if (it == null) + continue; + + if (prev_namespace != t.Namespace) { + ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true); + prev_namespace = t.Namespace; + } + + ns.AddType (module, it); + + if (it.IsStatic && hasExtensionTypes && + HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) { + it.SetExtensionMethodContainer (); + } + } + } + + void ImportTypeParameterTypeConstraints (TypeParameterSpec spec, MetaType type) + { + var constraints = type.GetGenericParameterConstraints (); + List tparams = null; + foreach (var ct in constraints) { + if (ct.IsGenericParameter) { + if (tparams == null) + tparams = new List (); + + tparams.Add (CreateType (ct)); + continue; + } + + if (!IsMissingType (ct) && ct.IsClass) { + spec.BaseType = CreateType (ct); + continue; + } + + spec.AddInterface (CreateType (ct)); + } + + if (spec.BaseType == null) + spec.BaseType = module.Compiler.BuiltinTypes.Object; + + if (tparams != null) + spec.TypeArguments = tparams.ToArray (); + } + + Constant ImportParameterConstant (object value) + { + // + // Get type of underlying value as int constant can be used for object + // parameter type. This is not allowed in C# but other languages can do that + // + var types = module.Compiler.BuiltinTypes; + switch (System.Type.GetTypeCode (value.GetType ())) { + case TypeCode.Boolean: + return new BoolConstant (types, (bool) value, Location.Null); + case TypeCode.Byte: + return new ByteConstant (types, (byte) value, Location.Null); + case TypeCode.Char: + return new CharConstant (types, (char) value, Location.Null); + case TypeCode.Decimal: + return new DecimalConstant (types, (decimal) value, Location.Null); + case TypeCode.Double: + return new DoubleConstant (types, (double) value, Location.Null); + case TypeCode.Int16: + return new ShortConstant (types, (short) value, Location.Null); + case TypeCode.Int32: + return new IntConstant (types, (int) value, Location.Null); + case TypeCode.Int64: + return new LongConstant (types, (long) value, Location.Null); + case TypeCode.SByte: + return new SByteConstant (types, (sbyte) value, Location.Null); + case TypeCode.Single: + return new FloatConstant (types, (float) value, Location.Null); + case TypeCode.String: + return new StringConstant (types, (string) value, Location.Null); + case TypeCode.UInt16: + return new UShortConstant (types, (ushort) value, Location.Null); + case TypeCode.UInt32: + return new UIntConstant (types, (uint) value, Location.Null); + case TypeCode.UInt64: + return new ULongConstant (types, (ulong) value, Location.Null); + } + + throw new NotImplementedException (value.GetType ().ToString ()); + } + + public TypeSpec ImportType (MetaType type) + { + return ImportType (type, new DynamicTypeReader (type)); + } + + TypeSpec ImportType (MetaType type, DynamicTypeReader dtype) + { + if (type.HasElementType) { + var element = type.GetElementType (); + ++dtype.Position; + var spec = ImportType (element, dtype); + + if (type.IsArray) + return ArrayContainer.MakeType (module, spec, type.GetArrayRank ()); + if (type.IsByRef) + return ReferenceContainer.MakeType (module, spec); + if (type.IsPointer) + return PointerContainer.MakeType (module, spec); + + throw new NotImplementedException ("Unknown element type " + type.ToString ()); + } + + return CreateType (type, dtype, true); + } + + static bool IsMissingType (MetaType type) + { +#if STATIC + return type.__IsMissing; +#else + return false; +#endif + } + + // + // Decimal constants cannot be encoded in the constant blob, and thus are marked + // as IsInitOnly ('readonly' in C# parlance). We get its value from the + // DecimalConstantAttribute metadata. + // + Constant ReadDecimalConstant (IList attrs) + { + if (attrs.Count == 0) + return null; + + foreach (var ca in attrs) { + var dt = ca.Constructor.DeclaringType; + if (dt.Name != "DecimalConstantAttribute" || dt.Namespace != CompilerServicesNamespace) + continue; + + var value = new decimal ( + (int) (uint) ca.ConstructorArguments[4].Value, + (int) (uint) ca.ConstructorArguments[3].Value, + (int) (uint) ca.ConstructorArguments[2].Value, + (byte) ca.ConstructorArguments[1].Value != 0, + (byte) ca.ConstructorArguments[0].Value); + + return new DecimalConstant (module.Compiler.BuiltinTypes, value, Location.Null); + } + + return null; + } + + static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType) + { + Modifiers mod; + var ma = mb.Attributes; + switch (ma & MethodAttributes.MemberAccessMask) { + case MethodAttributes.Public: + mod = Modifiers.PUBLIC; + break; + case MethodAttributes.Assembly: + mod = Modifiers.INTERNAL; + break; + case MethodAttributes.Family: + mod = Modifiers.PROTECTED; + break; + case MethodAttributes.FamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + mod = Modifiers.PRIVATE; + break; + } + + if ((ma & MethodAttributes.Static) != 0) { + mod |= Modifiers.STATIC; + return mod; + } + if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) { + mod |= Modifiers.ABSTRACT; + return mod; + } + + // It can be sealed and override + if ((ma & MethodAttributes.Final) != 0) + mod |= Modifiers.SEALED; + + if ((ma & MethodAttributes.Virtual) != 0) { + // Not every member can be detected based on MethodAttribute, we + // set virtual or non-virtual only when we are certain. Further checks + // to really find out what `virtual' means for this member are done + // later + if ((ma & MethodAttributes.NewSlot) != 0) { + if ((mod & Modifiers.SEALED) != 0) { + mod &= ~Modifiers.SEALED; + } else { + mod |= Modifiers.VIRTUAL; + } + } else { + mod |= Modifiers.OVERRIDE; + } + } + + return mod; + } + } + + abstract class ImportedDefinition : IMemberDefinition + { + protected class AttributesBag + { + public static readonly AttributesBag Default = new AttributesBag (); + + public AttributeUsageAttribute AttributeUsage; + public ObsoleteAttribute Obsolete; + public string[] Conditionals; + public string DefaultIndexerName; + public bool? CLSAttributeValue; + public TypeSpec CoClass; + + public static AttributesBag Read (MemberInfo mi, MetadataImporter importer) + { + AttributesBag bag = null; + List conditionals = null; + + // It should not throw any loading exception + IList attrs = CustomAttributeData.GetCustomAttributes (mi); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + string name = dt.Name; + if (name == "ObsoleteAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + var args = a.ConstructorArguments; + + if (args.Count == 1) { + bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value); + } else if (args.Count == 2) { + bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value); + } else { + bag.Obsolete = new ObsoleteAttribute (); + } + + continue; + } + + if (name == "ConditionalAttribute") { + if (dt.Namespace != "System.Diagnostics") + continue; + + if (bag == null) + bag = new AttributesBag (); + + if (conditionals == null) + conditionals = new List (2); + + conditionals.Add ((string) a.ConstructorArguments[0].Value); + continue; + } + + if (name == "CLSCompliantAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.CLSAttributeValue = (bool) a.ConstructorArguments[0].Value; + continue; + } + + // Type only attributes + if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) { + if (name == "DefaultMemberAttribute") { + if (dt.Namespace != "System.Reflection") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value; + continue; + } + + if (name == "AttributeUsageAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value); + foreach (var named in a.NamedArguments) { + if (named.MemberInfo.Name == "AllowMultiple") + bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value; + else if (named.MemberInfo.Name == "Inherited") + bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value; + } + continue; + } + + // Interface only attribute + if (name == "CoClassAttribute") { + if (dt.Namespace != "System.Runtime.InteropServices") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value); + continue; + } + } + } + + if (bag == null) + return Default; + + if (conditionals != null) + bag.Conditionals = conditionals.ToArray (); + + return bag; + } + } + + protected readonly MemberInfo provider; + protected AttributesBag cattrs; + protected readonly MetadataImporter importer; + + public ImportedDefinition (MemberInfo provider, MetadataImporter importer) + { + this.provider = provider; + this.importer = importer; + } + + #region Properties + + public bool IsImported { + get { + return true; + } + } + + public virtual string Name { + get { + return provider.Name; + } + } + + #endregion + + public string[] ConditionalConditions () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.Conditionals; + } + + public ObsoleteAttribute GetAttributeObsolete () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.Obsolete; + } + + public bool? CLSAttributeValue { + get { + if (cattrs == null) + ReadAttributes (); + + return cattrs.CLSAttributeValue; + } + } + + protected void ReadAttributes () + { + cattrs = AttributesBag.Read (provider, importer); + } + + public void SetIsAssigned () + { + // Unused for imported members + } + + public void SetIsUsed () + { + // Unused for imported members + } + } + + public class ImportedModuleDefinition + { + readonly Module module; + bool cls_compliant; + + public ImportedModuleDefinition (Module module) + { + this.module = module; + } + + #region Properties + + public bool IsCLSCompliant { + get { + return cls_compliant; + } + } + + public string Name { + get { + return module.Name; + } + } + + #endregion + + public void ReadAttributes () + { + IList attrs = CustomAttributeData.GetCustomAttributes (module); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + if (dt.Name == "CLSCompliantAttribute") { + if (dt.Namespace != "System") + continue; + + cls_compliant = (bool) a.ConstructorArguments[0].Value; + continue; + } + } + } + + // + // Reads assembly attributes which where attached to a special type because + // module does have assembly manifest + // + public List ReadAssemblyAttributes () + { + var t = module.GetType (AssemblyAttributesPlaceholder.GetGeneratedName (Name)); + if (t == null) + return null; + + var field = t.GetField (AssemblyAttributesPlaceholder.AssemblyFieldName, BindingFlags.NonPublic | BindingFlags.Static); + if (field == null) + return null; + + // TODO: implement, the idea is to fabricate specil Attribute class and + // add it to OptAttributes before resolving the source code attributes + // Need to build module location as well for correct error reporting + + //var assembly_attributes = CustomAttributeData.GetCustomAttributes (field); + //var attrs = new List (assembly_attributes.Count); + //foreach (var a in assembly_attributes) + //{ + // var type = metaImporter.ImportType (a.Constructor.DeclaringType); + // var ctor = metaImporter.CreateMethod (a.Constructor, type); + + // foreach (var carg in a.ConstructorArguments) { + // carg.Value + // } + + // attrs.Add (new Attribute ("assembly", ctor, null, Location.Null, true)); + //} + + return null; + } + } + + public class ImportedAssemblyDefinition : IAssemblyDefinition + { + readonly Assembly assembly; + readonly AssemblyName aname; + bool cls_compliant; + bool contains_extension_methods; + + List internals_visible_to; + Dictionary internals_visible_to_cache; + + public ImportedAssemblyDefinition (Assembly assembly) + { + this.assembly = assembly; + this.aname = assembly.GetName (); + } + + #region Properties + + public Assembly Assembly { + get { + return assembly; + } + } + + public string FullName { + get { + return aname.FullName; + } + } + + public bool HasExtensionMethod { + get { + return contains_extension_methods; + } + } + + public bool HasStrongName { + get { + return aname.GetPublicKey ().Length != 0; + } + } + + public bool IsMissing { + get { +#if STATIC + return assembly.__IsMissing; +#else + return false; +#endif + } + } + + public bool IsCLSCompliant { + get { + return cls_compliant; + } + } + + public string Location { + get { + return assembly.Location; + } + } + + public string Name { + get { + return aname.Name; + } + } + + #endregion + + public byte[] GetPublicKeyToken () + { + return aname.GetPublicKeyToken (); + } + + public AssemblyName GetAssemblyVisibleToName (IAssemblyDefinition assembly) + { + return internals_visible_to_cache [assembly]; + } + + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) + { + if (internals_visible_to == null) + return false; + + AssemblyName is_visible = null; + if (internals_visible_to_cache == null) { + internals_visible_to_cache = new Dictionary (); + } else { + if (internals_visible_to_cache.TryGetValue (assembly, out is_visible)) + return is_visible != null; + } + + var token = assembly.GetPublicKeyToken (); + if (token != null && token.Length == 0) + token = null; + + foreach (var internals in internals_visible_to) { + if (internals.Name != assembly.Name) + continue; + + if (token == null && assembly is AssemblyDefinition) { + is_visible = internals; + break; + } + + if (!ArrayComparer.IsEqual (token, internals.GetPublicKeyToken ())) + continue; + + is_visible = internals; + break; + } + + internals_visible_to_cache.Add (assembly, is_visible); + return is_visible != null; + } + + public void ReadAttributes () + { +#if STATIC + if (assembly.__IsMissing) + return; +#endif + + IList attrs = CustomAttributeData.GetCustomAttributes (assembly); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + var name = dt.Name; + if (name == "CLSCompliantAttribute") { + if (dt.Namespace == "System") { + cls_compliant = (bool) a.ConstructorArguments[0].Value; + } + continue; + } + + if (name == "InternalsVisibleToAttribute") { + if (dt.Namespace != MetadataImporter.CompilerServicesNamespace) + continue; + + string s = a.ConstructorArguments[0].Value as string; + if (s == null) + continue; + + var an = new AssemblyName (s); + if (internals_visible_to == null) + internals_visible_to = new List (); + + internals_visible_to.Add (an); + continue; + } + + if (name == "ExtensionAttribute") { + if (dt.Namespace == MetadataImporter.CompilerServicesNamespace) + contains_extension_methods = true; + + continue; + } + } + } + + public override string ToString () + { + return FullName; + } + } + + class ImportedMemberDefinition : ImportedDefinition + { + readonly TypeSpec type; + + public ImportedMemberDefinition (MemberInfo member, TypeSpec type, MetadataImporter importer) + : base (member, importer) + { + this.type = type; + } + + #region Properties + + public TypeSpec MemberType { + get { + return type; + } + } + + #endregion + } + + class ImportedParameterMemberDefinition : ImportedMemberDefinition, IParametersMember + { + readonly AParametersCollection parameters; + + public ImportedParameterMemberDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + : base (provider, type, importer) + { + this.parameters = parameters; + } + + public ImportedParameterMemberDefinition (PropertyInfo provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + : base (provider, type, importer) + { + this.parameters = parameters; + } + + #region Properties + + public AParametersCollection Parameters { + get { + return parameters; + } + } + + #endregion + } + + class ImportedGenericMethodDefinition : ImportedParameterMemberDefinition, IGenericMethodDefinition + { + readonly TypeParameterSpec[] tparams; + + public ImportedGenericMethodDefinition (MethodInfo provider, TypeSpec type, AParametersCollection parameters, TypeParameterSpec[] tparams, MetadataImporter importer) + : base (provider, type, parameters, importer) + { + this.tparams = tparams; + } + + #region Properties + + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + } + + public int TypeParametersCount { + get { + return tparams.Length; + } + } + + #endregion + } + + class ImportedTypeDefinition : ImportedDefinition, ITypeDefinition + { + TypeParameterSpec[] tparams; + string name; + + public ImportedTypeDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) + { + } + + #region Properties + + public IAssemblyDefinition DeclaringAssembly { + get { + return importer.GetAssemblyDefinition (provider.Module.Assembly); + } + } + + public override string Name { + get { + if (name == null) { + name = base.Name; + if (tparams != null) { + int arity_start = name.IndexOf ('`'); + if (arity_start > 0) + name = name.Substring (0, arity_start); + } + } + + return name; + } + } + + public string Namespace { + get { + return ((MetaType) provider).Namespace; + } + } + + public int TypeParametersCount { + get { + return tparams == null ? 0 : tparams.Length; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + set { + tparams = value; + } + } + + #endregion + + public static void Error_MissingDependency (IMemberContext ctx, List types, Location loc) + { + // + // Report details about missing type and most likely cause of the problem. + // csc reports 1683, 1684 as warnings but we report them only when used + // or referenced from the user core in which case compilation error has to + // be reported because compiler cannot continue anyway + // + foreach (var t in types) { + string name = t.GetSignatureForError (); + + if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) { + ctx.Module.Compiler.Report.Error (1683, loc, + "Reference to type `{0}' claims it is defined in this assembly, but it is not defined in source or any added modules", + name); + } else if (t.MemberDefinition.DeclaringAssembly.IsMissing) { + ctx.Module.Compiler.Report.Error (12, loc, + "The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } else { + ctx.Module.Compiler.Report.Error (1684, loc, + "Reference to type `{0}' claims it is defined assembly `{1}', but it could not be found", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } + } + } + + public TypeSpec GetAttributeCoClass () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.CoClass; + } + + public string GetAttributeDefaultMember () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.DefaultIndexerName; + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.AttributeUsage; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + var a = importer.GetAssemblyDefinition (provider.Module.Assembly); + return a == assembly || a.IsFriendAssemblyTo (assembly); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + // + // Not interested in members of nested private types unless the importer needs them + // + if (declaringType.IsPrivate && importer.IgnorePrivateMembers) { + cache = MemberCache.Empty; + return; + } + + var loading_type = (MetaType) provider; + const BindingFlags all_members = BindingFlags.DeclaredOnly | + BindingFlags.Static | BindingFlags.Instance | + BindingFlags.Public | BindingFlags.NonPublic; + + const MethodAttributes explicit_impl = MethodAttributes.NewSlot | + MethodAttributes.Virtual | MethodAttributes.HideBySig | + MethodAttributes.Final; + + Dictionary possible_accessors = null; + List imported_events = null; + EventSpec event_spec; + MemberSpec imported; + MethodInfo m; + MemberInfo[] all; + try { + all = loading_type.GetMembers (all_members); + } catch (Exception e) { + throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'", + declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName); + } + + if (cache == null) { + cache = new MemberCache (all.Length); + + // + // Do the types first as they can be referenced by the members before + // they are found or inflated + // + foreach (var member in all) { + if (member.MemberType != MemberTypes.NestedType) + continue; + + var t = (MetaType) member; + + // Ignore compiler generated types, mostly lambda containers + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) + continue; + + imported = importer.CreateNestedType (t, declaringType); + cache.AddMemberImported (imported); + } + + foreach (var member in all) { + if (member.MemberType != MemberTypes.NestedType) + continue; + + var t = (MetaType) member; + + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) + continue; + + importer.ImportTypeBase (t); + } + } + + if (!onlyTypes) { + // + // The logic here requires methods to be returned first which seems to work for both Mono and .NET + // + foreach (var member in all) { + switch (member.MemberType) { + case MemberTypes.Constructor: + case MemberTypes.Method: + MethodBase mb = (MethodBase) member; + var attrs = mb.Attributes; + + if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { + if (importer.IgnorePrivateMembers) + continue; + + // Ignore explicitly implemented members + if ((attrs & explicit_impl) == explicit_impl) + continue; + + // Ignore compiler generated methods + if (importer.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace)) + continue; + } + + imported = importer.CreateMethod (mb, declaringType); + if (imported.Kind == MemberKind.Method && !imported.IsGeneric) { + if (possible_accessors == null) + possible_accessors = new Dictionary (ReferenceEquality.Default); + + // There are no metadata rules for accessors, we have to consider any method as possible candidate + possible_accessors.Add (mb, (MethodSpec) imported); + } + + break; + case MemberTypes.Property: + if (possible_accessors == null) + continue; + + var p = (PropertyInfo) member; + // + // Links possible accessors with property + // + MethodSpec get, set; + m = p.GetGetMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out get)) + get = null; + + m = p.GetSetMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out set)) + set = null; + + // No accessors registered (e.g. explicit implementation) + if (get == null && set == null) + continue; + + imported = importer.CreateProperty (p, declaringType, get, set); + if (imported == null) + continue; + + break; + case MemberTypes.Event: + if (possible_accessors == null) + continue; + + var e = (EventInfo) member; + // + // Links accessors with event + // + MethodSpec add, remove; + m = e.GetAddMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out add)) + add = null; + + m = e.GetRemoveMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out remove)) + remove = null; + + // Both accessors are required + if (add == null || remove == null) + continue; + + event_spec = importer.CreateEvent (e, declaringType, add, remove); + if (!importer.IgnorePrivateMembers) { + if (imported_events == null) + imported_events = new List (); + + imported_events.Add (event_spec); + } + + imported = event_spec; + break; + case MemberTypes.Field: + var fi = (FieldInfo) member; + + imported = importer.CreateField (fi, declaringType); + if (imported == null) + continue; + + // + // For dynamic binder event has to be fully restored to allow operations + // within the type container to work correctly + // + if (imported_events != null) { + // The backing event field should be private but it may not + int i; + for (i = 0; i < imported_events.Count; ++i) { + var ev = imported_events[i]; + if (ev.Name == fi.Name) { + ev.BackingField = (FieldSpec) imported; + imported_events.RemoveAt (i); + i = -1; + break; + } + } + + if (i < 0) + continue; + } + + break; + case MemberTypes.NestedType: + // Already in the cache from the first pass + continue; + default: + throw new NotImplementedException (member.ToString ()); + } + + cache.AddMemberImported (imported); + } + } + + if (declaringType.IsInterface && declaringType.Interfaces != null) { + foreach (var iface in declaringType.Interfaces) { + cache.AddInterface (iface); + } + } + } + } + + class ImportedTypeParameterDefinition : ImportedDefinition, ITypeDefinition + { + public ImportedTypeParameterDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) + { + } + + #region Properties + + public IAssemblyDefinition DeclaringAssembly { + get { + throw new NotImplementedException (); + } + } + + public string Namespace { + get { + return null; + } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return null; + } + } + + #endregion + + public TypeSpec GetAttributeCoClass () + { + return null; + } + + public string GetAttributeDefaultMember () + { + throw new NotSupportedException (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + throw new NotSupportedException (); + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + throw new NotImplementedException (); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotImplementedException (); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs new file mode 100644 index 0000000000..9a256de68c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs @@ -0,0 +1,1057 @@ +// +// iterators.cs: Support for implementing iterators +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +// TODO: +// Flow analysis for Yield. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public abstract class YieldStatement : ResumableStatement where T : StateMachineInitializer + { + protected Expression expr; + bool unwind_protect; + protected T machine_initializer; + int resume_pc; + + public Expression Expr { + get { return this.expr; } + } + + protected YieldStatement (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + var target = (YieldStatement) t; + target.expr = expr.Clone (clonectx); + } + + protected override void DoEmit (EmitContext ec) + { + machine_initializer.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + + public override bool Resolve (BlockContext bc) + { + expr = expr.Resolve (bc); + if (expr == null) + return false; + + machine_initializer = bc.CurrentAnonymousMethod as T; + + if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable) + unwind_protect = bc.CurrentBranching.AddResumePoint (this, loc, out resume_pc); + + return true; + } + } + + public class Yield : YieldStatement + { + public Yield (Expression expr, Location loc) + : base (expr, loc) + { + } + + public static bool CheckContext (ResolveContext ec, Location loc) + { + if (!ec.CurrentAnonymousMethod.IsIterator) { + ec.Report.Error (1621, loc, + "The yield statement cannot be used inside anonymous method blocks"); + return false; + } + + return true; + } + + public override bool Resolve (BlockContext bc) + { + if (!CheckContext (bc, loc)) + return false; + + if (!base.Resolve (bc)) + return false; + + var otype = bc.CurrentIterator.OriginalIteratorType; + if (expr.Type != otype) { + expr = Convert.ImplicitConversionRequired (bc, expr, otype, loc); + if (expr == null) + return false; + } + + return true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class YieldBreak : ExitStatement + { + Iterator iterator; + + public YieldBreak (Location l) + { + loc = l; + } + + public override void Error_FinallyClause (Report Report) + { + Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + protected override bool DoResolve (BlockContext ec) + { + iterator = ec.CurrentIterator; + return Yield.CheckContext (ec, loc); + } + + protected override void DoEmit (EmitContext ec) + { + iterator.EmitYieldBreak (ec, unwind_protect); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class StateMachine : AnonymousMethodStorey + { + public enum State + { + Running = -3, // Used only in CurrentPC, never stored into $PC + Uninitialized = -2, + After = -1, + Start = 0 + } + + Field disposing_field; + Field pc_field; + int local_name_idx; + StateMachineMethod method; + + protected StateMachine (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) + : base (block, parent, host, tparams, name) + { + } + + #region Properties + + public Field DisposingField { + get { + return disposing_field; + } + } + + public StateMachineMethod StateMachineMethod { + get { + return method; + } + } + + public Field PC { + get { + return pc_field; + } + } + + #endregion + + public void AddEntryMethod (StateMachineMethod method) + { + if (this.method != null) + throw new InternalErrorException (); + + this.method = method; + AddMethod (method); + } + + protected override bool DoDefineMembers () + { + pc_field = AddCompilerGeneratedField ("$PC", new TypeExpression (Compiler.BuiltinTypes.Int, Location)); + disposing_field = AddCompilerGeneratedField ("$disposing", new TypeExpression (Compiler.BuiltinTypes.Bool, Location)); + + return base.DoDefineMembers (); + } + + protected override string GetVariableMangledName (LocalVariable local_info) + { + return "<" + local_info.Name + ">__" + local_name_idx++.ToString (); + } + } + + class IteratorStorey : StateMachine + { + class GetEnumeratorMethod : StateMachineMethod + { + sealed class GetEnumeratorStatement : Statement + { + readonly IteratorStorey host; + readonly StateMachineMethod host_method; + + Expression new_storey; + + public GetEnumeratorStatement (IteratorStorey host, StateMachineMethod host_method) + { + this.host = host; + this.host_method = host_method; + loc = host_method.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + TypeExpression storey_type_expr = new TypeExpression (host.Definition, loc); + List init = null; + if (host.hoisted_this != null) { + init = new List (host.hoisted_params == null ? 1 : host.HoistedParameters.Count + 1); + HoistedThis ht = host.hoisted_this; + FieldExpr from = new FieldExpr (ht.Field, loc); + from.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + init.Add (new ElementInitializer (ht.Field.Name, from, loc)); + } + + if (host.hoisted_params != null) { + if (init == null) + init = new List (host.HoistedParameters.Count); + + for (int i = 0; i < host.hoisted_params.Count; ++i) { + HoistedParameter hp = host.hoisted_params [i]; + HoistedParameter hp_cp = host.hoisted_params_copy [i]; + + FieldExpr from = new FieldExpr (hp_cp.Field, loc); + from.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + + init.Add (new ElementInitializer (hp.Field.Name, from, loc)); + } + } + + if (init != null) { + new_storey = new NewInitialize (storey_type_expr, null, + new CollectionOrObjectInitializers (init, loc), loc); + } else { + new_storey = new New (storey_type_expr, null, loc); + } + + new_storey = new_storey.Resolve (ec); + if (new_storey != null) + new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc); + + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + Label label_init = ec.DefineLabel (); + + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldflda, host.PC.Spec); + ec.EmitInt ((int) State.Start); + ec.EmitInt ((int) State.Uninitialized); + + var m = ec.Module.PredefinedMembers.InterlockedCompareExchange.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + + ec.EmitInt ((int) State.Uninitialized); + ec.Emit (OpCodes.Bne_Un_S, label_init); + + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ret); + + ec.MarkLabel (label_init); + + new_storey.Emit (ec); + ec.Emit (OpCodes.Ret); + } + } + + public GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name) + : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name) + { + Block.AddStatement (new GetEnumeratorStatement (host, this)); + } + } + + class DisposeMethod : StateMachineMethod + { + sealed class DisposeMethodStatement : Statement + { + Iterator iterator; + + public DisposeMethodStatement (Iterator iterator) + { + this.iterator = iterator; + this.loc = iterator.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.CurrentAnonymousMethod = iterator; + iterator.EmitDispose (ec); + } + } + + public DisposeMethod (IteratorStorey host) + : base (host, null, new TypeExpression (host.Compiler.BuiltinTypes.Void, host.Location), Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("Dispose", host.Location)) + { + host.AddMethod (this); + + Block.AddStatement (new DisposeMethodStatement (host.Iterator)); + } + } + + // + // Uses Method as method info + // + class DynamicMethodGroupExpr : MethodGroupExpr + { + readonly Method method; + + public DynamicMethodGroupExpr (Method method, Location loc) + : base ((IList) null, null, loc) + { + this.method = method; + eclass = ExprClass.Unresolved; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Methods = new List (1) { method.Spec }; + type = method.Parent.Definition; + InstanceExpression = new CompilerGeneratedThis (type, Location); + return base.DoResolve (ec); + } + } + + class DynamicFieldExpr : FieldExpr + { + readonly Field field; + + public DynamicFieldExpr (Field field, Location loc) + : base (loc) + { + this.field = field; + } + + protected override Expression DoResolve (ResolveContext ec) + { + spec = field.Spec; + type = spec.MemberType; + InstanceExpression = new CompilerGeneratedThis (type, Location); + return base.DoResolve (ec); + } + } + + public readonly Iterator Iterator; + + List hoisted_params_copy; + + TypeExpr iterator_type_expr; + Field current_field; + + TypeExpr enumerator_type; + TypeExpr enumerable_type; + TypeArguments generic_args; + TypeExpr generic_enumerator_type; + TypeExpr generic_enumerable_type; + + public IteratorStorey (Iterator iterator) + : base (iterator.Container.ParametersBlock, iterator.Host, + iterator.OriginalMethod as MemberBase, iterator.GenericMethod == null ? null : iterator.GenericMethod.CurrentTypeParameters, "Iterator") + { + this.Iterator = iterator; + } + + public Field CurrentField { + get { return current_field; } + } + + public IList HoistedParameters { + get { return hoisted_params; } + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var mtype = Iterator.OriginalIteratorType; + if (Mutator != null) + mtype = Mutator.Mutate (mtype); + + iterator_type_expr = new TypeExpression (mtype, Location); + generic_args = new TypeArguments (iterator_type_expr); + + var list = new List (); + if (Iterator.IsEnumerable) { + enumerable_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerable, Location); + list.Add (enumerable_type); + + if (Module.PredefinedTypes.IEnumerableGeneric.Define ()) { + generic_enumerable_type = new GenericTypeExpr (Module.PredefinedTypes.IEnumerableGeneric.TypeSpec, generic_args, Location); + list.Add (generic_enumerable_type); + } + } + + enumerator_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerator, Location); + list.Add (enumerator_type); + + list.Add (new TypeExpression (Compiler.BuiltinTypes.IDisposable, Location)); + + var ienumerator_generic = Module.PredefinedTypes.IEnumeratorGeneric; + if (ienumerator_generic.Define ()) { + generic_enumerator_type = new GenericTypeExpr (ienumerator_generic.TypeSpec, generic_args, Location); + list.Add (generic_enumerator_type); + } + + type_bases = list; + + return base.ResolveBaseTypes (out base_class); + } + + protected override bool DoDefineMembers () + { + current_field = AddCompilerGeneratedField ("$current", iterator_type_expr); + + if (hoisted_params != null) { + // + // Iterators are independent, each GetEnumerator call has to + // create same enumerator therefore we have to keep original values + // around for re-initialization + // + // TODO: Do it for assigned/modified parameters only + // + hoisted_params_copy = new List (hoisted_params.Count); + foreach (HoistedParameter hp in hoisted_params) { + hoisted_params_copy.Add (new HoistedParameter (hp, "<$>" + hp.Field.Name)); + } + } + + if (generic_enumerator_type != null) + Define_Current (true); + + Define_Current (false); + new DisposeMethod (this); + Define_Reset (); + + if (Iterator.IsEnumerable) { + MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); + name = new MemberName (name, "Collections", Location); + name = new MemberName (name, "IEnumerable", Location); + name = new MemberName (name, "GetEnumerator", Location); + + if (generic_enumerator_type != null) { + Method get_enumerator = new StateMachineMethod (this, null, enumerator_type, 0, name); + + name = new MemberName (name.Left.Left, "Generic", Location); + name = new MemberName (name, "IEnumerable", generic_args, Location); + name = new MemberName (name, "GetEnumerator", Location); + Method gget_enumerator = new GetEnumeratorMethod (this, generic_enumerator_type, name); + + // + // Just call generic GetEnumerator implementation + // + get_enumerator.Block.AddStatement ( + new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), null), Location)); + + AddMethod (get_enumerator); + AddMethod (gget_enumerator); + } else { + AddMethod (new GetEnumeratorMethod (this, enumerator_type, name)); + } + } + + return base.DoDefineMembers (); + } + + void Define_Current (bool is_generic) + { + TypeExpr type; + + MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); + name = new MemberName (name, "Collections", Location); + + if (is_generic) { + name = new MemberName (name, "Generic", Location); + name = new MemberName (name, "IEnumerator", generic_args, Location); + type = iterator_type_expr; + } else { + name = new MemberName (name, "IEnumerator"); + type = new TypeExpression (Compiler.BuiltinTypes.Object, Location); + } + + name = new MemberName (name, "Current", Location); + + ToplevelBlock get_block = new ToplevelBlock (Compiler, Location); + get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location)); + + Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN, name, null); + current.Get = new Property.GetMethod (current, 0, null, Location); + current.Get.Block = get_block; + + AddProperty (current); + } + + void Define_Reset () + { + Method reset = new Method ( + this, null, new TypeExpression (Compiler.BuiltinTypes.Void, Location), + Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("Reset", Location), + ParametersCompiled.EmptyReadOnlyParameters, null); + AddMethod (reset); + + reset.Block = new ToplevelBlock (Compiler, Location); + + TypeSpec ex_type = Module.PredefinedTypes.NotSupportedException.Resolve (); + if (ex_type == null) + return; + + reset.Block.AddStatement (new Throw (new New (new TypeExpression (ex_type, Location), null, Location), Location)); + } + + protected override void EmitHoistedParameters (EmitContext ec, IList hoisted) + { + base.EmitHoistedParameters (ec, hoisted); + base.EmitHoistedParameters (ec, hoisted_params_copy); + } + } + + public class StateMachineMethod : Method + { + readonly StateMachineInitializer expr; + + public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType, Modifiers mod, MemberName name) + : base (host, null, returnType, mod | Modifiers.COMPILER_GENERATED, + name, ParametersCompiled.EmptyReadOnlyParameters, null) + { + this.expr = expr; + Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + } + + public override EmitContext CreateEmitContext (ILGenerator ig) + { + EmitContext ec = new EmitContext (this, ig, MemberType); + ec.CurrentAnonymousMethod = expr; + return ec; + } + } + + public abstract class StateMachineInitializer : AnonymousExpression + { + sealed class MoveNextBodyStatement : Statement + { + readonly StateMachineInitializer state_machine; + + public MoveNextBodyStatement (StateMachineInitializer stateMachine) + { + this.state_machine = stateMachine; + this.loc = stateMachine.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + protected override void DoEmit (EmitContext ec) + { + state_machine.EmitMoveNext (ec); + } + } + + public readonly TypeContainer Host; + protected StateMachine storey; + + // + // The state as we generate the machine + // + Label move_next_ok; + protected Label move_next_error; + protected LocalBuilder skip_finally, current_pc; + List resume_points; + + protected StateMachineInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType) + : base (block, returnType, block.StartLocation) + { + this.Host = host; + } + + public override AnonymousMethodStorey Storey { + get { + return storey; + } + } + + public int AddResumePoint (ResumableStatement stmt) + { + if (resume_points == null) + resume_points = new List (); + + resume_points.Add (stmt); + return resume_points.Count; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected virtual BlockContext CreateBlockContext (ResolveContext rc) + { + var ctx = new BlockContext (rc, block, ((BlockContext) rc).ReturnType); + ctx.CurrentAnonymousMethod = this; + return ctx; + } + + protected override Expression DoResolve (ResolveContext ec) + { + storey = (StateMachine) block.Parent.ParametersBlock.AnonymousMethodStorey; + + var ctx = CreateBlockContext (ec); + + ctx.StartFlowBranching (this, ec.CurrentBranching); + Block.Resolve (ctx); + + // + // Explicit return is required for Task state machine + // + var task_storey = storey as AsyncTaskStorey; + if (task_storey == null || (task_storey.ReturnType != null && !task_storey.ReturnType.IsGenericTask)) + ctx.CurrentBranching.CurrentUsageVector.Goto (); + + ctx.EndFlowBranching (); + + if (!ec.IsInProbingMode) { + var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc)); + move_next.Block.AddStatement (new MoveNextBodyStatement (this)); + storey.AddEntryMethod (move_next); + } + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + // + // Load Iterator storey instance + // + storey.Instance.Emit (ec); + } + + public void EmitDispose (EmitContext ec) + { + Label end = ec.DefineLabel (); + + Label[] labels = null; + int n_resume_points = resume_points == null ? 0 : resume_points.Count; + for (int i = 0; i < n_resume_points; ++i) { + ResumableStatement s = resume_points[i]; + Label ret = s.PrepareForDispose (ec, end); + if (ret.Equals (end) && labels == null) + continue; + if (labels == null) { + labels = new Label[resume_points.Count + 1]; + for (int j = 0; j <= i; ++j) + labels[j] = end; + } + + labels[i + 1] = ret; + } + + if (labels != null) { + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + ec.Emit (OpCodes.Stloc, current_pc); + } + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt (1); + ec.Emit (OpCodes.Stfld, storey.DisposingField.Spec); + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + if (labels != null) { + //SymbolWriter.StartIteratorDispatcher (ec.ig); + ec.Emit (OpCodes.Ldloc, current_pc); + ec.Emit (OpCodes.Switch, labels); + //SymbolWriter.EndIteratorDispatcher (ec.ig); + + foreach (ResumableStatement s in resume_points) + s.EmitForDispose (ec, current_pc, end, true); + } + + ec.MarkLabel (end); + } + + void EmitMoveNext_NoResumePoints (EmitContext ec, Block original_block) + { + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + // We only care if the PC is zero (start executing) or non-zero (don't do anything) + ec.Emit (OpCodes.Brtrue, move_next_error); + + SymbolWriter.StartIteratorBody (ec); + original_block.Emit (ec); + SymbolWriter.EndIteratorBody (ec); + + EmitMoveNextEpilogue (ec); + + ec.MarkLabel (move_next_error); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (0); + ec.Emit (OpCodes.Ret); + } + } + + void EmitMoveNext (EmitContext ec) + { + move_next_ok = ec.DefineLabel (); + move_next_error = ec.DefineLabel (); + + if (resume_points == null) { + EmitMoveNext_NoResumePoints (ec, block); + return; + } + + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + ec.Emit (OpCodes.Stloc, current_pc); + + // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + Label[] labels = new Label[1 + resume_points.Count]; + labels[0] = ec.DefineLabel (); + + bool need_skip_finally = false; + for (int i = 0; i < resume_points.Count; ++i) { + ResumableStatement s = resume_points[i]; + need_skip_finally |= s is ExceptionStatement; + labels[i + 1] = s.PrepareForEmit (ec); + } + + if (need_skip_finally) { + skip_finally = ec.GetTemporaryLocal (ec.BuiltinTypes.Bool); + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Stloc, skip_finally); + } + + SymbolWriter.StartIteratorDispatcher (ec); + ec.Emit (OpCodes.Ldloc, current_pc); + ec.Emit (OpCodes.Switch, labels); + + ec.Emit (OpCodes.Br, move_next_error); + SymbolWriter.EndIteratorDispatcher (ec); + + ec.MarkLabel (labels[0]); + + SymbolWriter.StartIteratorBody (ec); + block.Emit (ec); + SymbolWriter.EndIteratorBody (ec); + + SymbolWriter.StartIteratorDispatcher (ec); + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + EmitMoveNextEpilogue (ec); + + ec.MarkLabel (move_next_error); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (0); + ec.Emit (OpCodes.Ret); + } + + ec.MarkLabel (move_next_ok); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (1); + ec.Emit (OpCodes.Ret); + } + + SymbolWriter.EndIteratorDispatcher (ec); + } + + protected virtual void EmitMoveNextEpilogue (EmitContext ec) + { + } + + // + // Called back from YieldStatement + // + public virtual void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + // + // Guard against being disposed meantime + // + Label disposed = ec.DefineLabel (); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.DisposingField.Spec); + ec.Emit (OpCodes.Brtrue_S, disposed); + + // + // store resume program-counter + // + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt (resume_pc); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + ec.MarkLabel (disposed); + + // mark finally blocks as disabled + if (unwind_protect && skip_finally != null) { + ec.EmitInt (1); + ec.Emit (OpCodes.Stloc, skip_finally); + } + + // Return ok + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); + + ec.MarkLabel (resume_point); + } + } + + // + // Iterators are implemented as hidden anonymous block + // + public class Iterator : StateMachineInitializer + { + public readonly IMethodData OriginalMethod; + public readonly bool IsEnumerable; + public readonly TypeSpec OriginalIteratorType; + + public Iterator (ParametersBlock block, IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) + : base (block, host, host.Compiler.BuiltinTypes.Bool) + { + this.OriginalMethod = method; + this.OriginalIteratorType = iterator_type; + this.IsEnumerable = is_enumerable; + this.type = method.ReturnType; + } + + public LocalBuilder SkipFinally { + get { return skip_finally; } + } + + public LocalBuilder CurrentPC { + get { return current_pc; } + } + + public Block Container { + get { return OriginalMethod.Block; } + } + + public GenericMethod GenericMethod { + get { return OriginalMethod.GenericMethod; } + } + + public override string ContainerType { + get { return "iterator"; } + } + + public override bool IsIterator { + get { return true; } + } + + public void EmitYieldBreak (EmitContext ec, bool unwind_protect) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error); + } + + public override string GetSignatureForError () + { + return OriginalMethod.GetSignatureForError (); + } + + public override void Emit (EmitContext ec) + { + // + // Load Iterator storey instance + // + storey.Instance.Emit (ec); + + // + // Initialize iterator PC when it's unitialized + // + if (IsEnumerable) { + ec.Emit (OpCodes.Dup); + ec.EmitInt ((int)IteratorStorey.State.Uninitialized); + + var field = storey.PC.Spec; + if (storey.MemberName.IsGeneric) { + field = MemberCache.GetMember (Storey.Instance.Type, field); + } + + ec.Emit (OpCodes.Stfld, field); + } + } + + public override void EmitStatement (EmitContext ec) + { + throw new NotImplementedException (); + } + + public override void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + // Store the new value into current + var fe = new FieldExpr (((IteratorStorey) storey).CurrentField, loc); + fe.InstanceExpression = new CompilerGeneratedThis (storey.CurrentType, loc); + fe.EmitAssign (ec, expr, false, false); + + base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + + public static void CreateIterator (IMethodData method, TypeContainer parent, Modifiers modifiers) + { + bool is_enumerable; + TypeSpec iterator_type; + + TypeSpec ret = method.ReturnType; + if (ret == null) + return; + + if (!CheckType (ret, parent, out iterator_type, out is_enumerable)) { + parent.Compiler.Report.Error (1624, method.Location, + "The body of `{0}' cannot be an iterator block " + + "because `{1}' is not an iterator interface type", + method.GetSignatureForError (), + TypeManager.CSharpName (ret)); + return; + } + + ParametersCompiled parameters = method.ParameterInfo; + for (int i = 0; i < parameters.Count; i++) { + Parameter p = parameters [i]; + Parameter.Modifier mod = p.ModFlags; + if ((mod & Parameter.Modifier.ISBYREF) != 0) { + parent.Compiler.Report.Error (1623, p.Location, + "Iterators cannot have ref or out parameters"); + return; + } + + if (p is ArglistParameter) { + parent.Compiler.Report.Error (1636, method.Location, + "__arglist is not allowed in parameter list of iterators"); + return; + } + + if (parameters.Types [i].IsPointer) { + parent.Compiler.Report.Error (1637, p.Location, + "Iterators cannot have unsafe parameters or yield types"); + return; + } + } + + if ((modifiers & Modifiers.UNSAFE) != 0) { + parent.Compiler.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators"); + } + + method.Block.WrapIntoIterator (method, parent, iterator_type, is_enumerable); + } + + static bool CheckType (TypeSpec ret, TypeContainer parent, out TypeSpec original_iterator_type, out bool is_enumerable) + { + original_iterator_type = null; + is_enumerable = false; + + if (ret.BuiltinType == BuiltinTypeSpec.Type.IEnumerable) { + original_iterator_type = parent.Compiler.BuiltinTypes.Object; + is_enumerable = true; + return true; + } + if (ret.BuiltinType == BuiltinTypeSpec.Type.IEnumerator) { + original_iterator_type = parent.Compiler.BuiltinTypes.Object; + is_enumerable = false; + return true; + } + + InflatedTypeSpec inflated = ret as InflatedTypeSpec; + if (inflated == null) + return false; + + var member_definition = inflated.MemberDefinition; + PredefinedType ptype = parent.Module.PredefinedTypes.IEnumerableGeneric; + + if (ptype.Define () && ptype.TypeSpec.MemberDefinition == member_definition) { + original_iterator_type = inflated.TypeArguments[0]; + is_enumerable = true; + return true; + } + + ptype = parent.Module.PredefinedTypes.IEnumeratorGeneric; + if (ptype.Define () && ptype.TypeSpec.MemberDefinition == member_definition) { + original_iterator_type = inflated.TypeArguments[0]; + is_enumerable = false; + return true; + } + + return false; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs new file mode 100644 index 0000000000..3cad50ce49 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs @@ -0,0 +1,229 @@ +// +// lambda.cs: support for lambda expressions +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2007-2008 Novell, Inc +// + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + public class LambdaExpression : AnonymousMethodExpression + { + // + // The parameters can either be: + // A list of Parameters (explicitly typed parameters) + // An ImplicitLambdaParameter + // + public LambdaExpression (bool isAsync, Location loc) + : base (isAsync, loc) + { + } + + public LambdaExpression (Location loc) + : this (false, loc) + { + } + + protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) + { + if (ec.IsInProbingMode) + return this; + + BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { + CurrentAnonymousMethod = ec.CurrentAnonymousMethod + }; + + Expression args = Parameters.CreateExpressionTree (bc, loc); + Expression expr = Block.CreateExpressionTree (ec); + if (expr == null) + return null; + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (expr)); + arguments.Add (new Argument (args)); + return CreateExpressionFactoryCall (ec, "Lambda", + new TypeArguments (new TypeExpression (delegate_type, loc)), + arguments); + } + + public override bool HasExplicitParameters { + get { + return Parameters.Count > 0 && !(Parameters.FixedParameters [0] is ImplicitLambdaParameter); + } + } + + protected override ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegateType) + { + if (!delegateType.IsDelegate) + return null; + + AParametersCollection d_params = Delegate.GetParameters (delegateType); + + if (HasExplicitParameters) { + if (!VerifyExplicitParameters (ec, delegateType, d_params)) + return null; + + return Parameters; + } + + // + // If L has an implicitly typed parameter list we make implicit parameters explicit + // Set each parameter of L is given the type of the corresponding parameter in D + // + if (!VerifyParameterCompatibility (ec, delegateType, d_params, ec.IsInProbingMode)) + return null; + + TypeSpec [] ptypes = new TypeSpec [Parameters.Count]; + for (int i = 0; i < d_params.Count; i++) { + // D has no ref or out parameters + if ((d_params.FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) != 0) + return null; + + TypeSpec d_param = d_params.Types [i]; + + // + // When type inference context exists try to apply inferred type arguments + // + if (tic != null) { + d_param = tic.InflateGenericArgument (ec, d_param); + } + + ptypes [i] = d_param; + ImplicitLambdaParameter ilp = (ImplicitLambdaParameter) Parameters.FixedParameters [i]; + ilp.SetParameterType (d_param); + ilp.Resolve (null, i); + } + + Parameters.Types = ptypes; + return Parameters; + } + + protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ParametersBlock b) + { + return new LambdaMethod (p, b, returnType, delegateType, loc); + } + + protected override bool DoResolveParameters (ResolveContext rc) + { + // + // Only explicit parameters can be resolved at this point + // + if (HasExplicitParameters) { + return Parameters.Resolve (rc); + } + + return true; + } + + public override string GetSignatureForError () + { + return "lambda expression"; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class LambdaMethod : AnonymousMethodBody + { + public LambdaMethod (ParametersCompiled parameters, + ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, + Location loc) + : base (parameters, block, return_type, delegate_type, loc) + { + } + + #region Properties + + public override string ContainerType { + get { + return "lambda expression"; + } + } + + #endregion + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // TODO: nothing ?? + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType); + Expression args = parameters.CreateExpressionTree (bc, loc); + Expression expr = Block.CreateExpressionTree (ec); + if (expr == null) + return null; + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (expr)); + arguments.Add (new Argument (args)); + return CreateExpressionFactoryCall (ec, "Lambda", + new TypeArguments (new TypeExpression (type, loc)), + arguments); + } + } + + // + // This is a return statement that is prepended lambda expression bodies that happen + // to be expressions. Depending on the return type of the delegate this will behave + // as either { expr (); return (); } or { return expr (); } + // + public class ContextualReturn : Return + { + ExpressionStatement statement; + + public ContextualReturn (Expression expr) + : base (expr, expr.Location) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return Expr.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + if (statement != null) { + statement.EmitStatement (ec); + ec.Emit (OpCodes.Ret); + return; + } + + base.Emit (ec); + } + + protected override bool DoResolve (BlockContext ec) + { + // + // When delegate returns void, only expression statements can be used + // + if (ec.ReturnType.Kind == MemberKind.Void) { + Expr = Expr.Resolve (ec); + if (Expr == null) + return false; + + statement = Expr as ExpressionStatement; + if (statement == null) + Expr.Error_InvalidExpressionStatement (ec); + + return true; + } + + return base.DoResolve (ec); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo new file mode 100644 index 0000000000..e3a8a184cd --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo @@ -0,0 +1,24 @@ +Tasks for completing Lambda support: + +* Port the grammar to mcs + +* Everywhere where we use Arguments, we need to clone them. + +* We need a "CloneContext" that would keep track of mappings between +the old blocks and the new blocks, so that expression that keep +pointers to blocks can get the proper block on cloning, something like: + + CloneTo (CloneContext cc, Expression t) + { + MyClass target = (MyClass) t; + target.Block = cc.RemapBlock (Block); + } + +* Generics section support. + +* Fix the bug in the modified l1.cs that introduces two rets instead + of a single one. + +* Complete CloneTo for Statements. + +* Write an extensive test suite to exercise CloneTo \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs new file mode 100644 index 0000000000..070b6df10c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs @@ -0,0 +1,892 @@ +// +// linq.cs: support for query expressions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2007-2008 Novell, Inc +// + +using System; +using System.Collections.Generic; + +namespace Mono.CSharp.Linq +{ + public class QueryExpression : AQueryClause + { + public QueryExpression (AQueryClause start) + : base (null, null, start.Location) + { + this.next = start; + } + + public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parentParameter) + { + return next.BuildQueryClause (ec, lSide, parentParameter); + } + + protected override Expression DoResolve (ResolveContext ec) + { + int counter = QueryBlock.TransparentParameter.Counter; + + Expression e = BuildQueryClause (ec, null, null); + if (e != null) + e = e.Resolve (ec); + + // + // Reset counter in probing mode to ensure that all transparent + // identifier anonymous types are created only once + // + if (ec.IsInProbingMode) + QueryBlock.TransparentParameter.Counter = counter; + + return e; + } + + protected override string MethodName { + get { throw new NotSupportedException (); } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class AQueryClause : ShimExpression + { + protected class QueryExpressionAccess : MemberAccess + { + public QueryExpressionAccess (Expression expr, string methodName, Location loc) + : base (expr, methodName, loc) + { + } + + public QueryExpressionAccess (Expression expr, string methodName, TypeArguments typeArguments, Location loc) + : base (expr, methodName, typeArguments, loc) + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + ec.Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " + + "Are you missing `System.Linq' using directive or `System.Core.dll' assembly reference?", + name); + } + } + + protected class QueryExpressionInvocation : Invocation, OverloadResolver.IErrorHandler + { + public QueryExpressionInvocation (QueryExpressionAccess expr, Arguments arguments) + : base (expr, arguments) + { + } + + protected override MethodGroupExpr DoResolveOverload (ResolveContext ec) + { + MethodGroupExpr rmg = mg.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.None); + return rmg; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + ec.Report.SymbolRelatedToPreviousError (best); + ec.Report.SymbolRelatedToPreviousError (ambiguous); + ec.Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'", + best.Name, mg.InstanceExpression.GetSignatureForError ()); + return true; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + return false; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + var ms = (MethodSpec) best; + TypeSpec source_type = ms.Parameters.ExtensionMethodType; + if (source_type != null) { + Argument a = arguments[0]; + + if (TypeManager.IsGenericType (source_type) && InflatedTypeSpec.ContainsTypeParameter (source_type)) { + TypeInferenceContext tic = new TypeInferenceContext (source_type.TypeArguments); + tic.OutputTypeInference (rc, a.Expr, source_type); + if (tic.FixAllTypes (rc)) { + source_type = source_type.GetDefinition ().MakeGenericType (rc, tic.InferredTypeArguments); + } + } + + if (!Convert.ImplicitConversionExists (rc, a.Expr, source_type)) { + rc.Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found", + best.Name, TypeManager.CSharpName (a.Type)); + return true; + } + } + + if (best.Name == "SelectMany") { + rc.Report.Error (1943, loc, + "An expression type is incorrect in a subsequent `from' clause in a query expression with source type `{0}'", + arguments[0].GetSignatureForError ()); + } else { + rc.Report.Error (1942, loc, + "An expression type in `{0}' clause is incorrect. Type inference failed in the call to `{1}'", + best.Name.ToLowerInvariant (), best.Name); + } + + return true; + } + + #endregion + } + + public AQueryClause next; + public QueryBlock block; + + protected AQueryClause (QueryBlock block, Expression expr, Location loc) + : base (expr) + { + this.block = block; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + base.CloneTo (clonectx, target); + + AQueryClause t = (AQueryClause) target; + + if (block != null) + t.block = (QueryBlock) clonectx.LookupBlock (block); + + if (next != null) + t.next = (AQueryClause) next.Clone (clonectx); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return expr.Resolve (ec); + } + + public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter) + { + Arguments args = null; + CreateArguments (ec, parameter, ref args); + lSide = CreateQueryExpression (lSide, args); + if (next != null) { + parameter = CreateChildrenParameters (parameter); + + Select s = next as Select; + if (s == null || s.IsRequired (parameter)) + return next.BuildQueryClause (ec, lSide, parameter); + + // Skip transparent select clause if any clause follows + if (next.next != null) + return next.next.BuildQueryClause (ec, lSide, parameter); + } + + return lSide; + } + + protected virtual Parameter CreateChildrenParameters (Parameter parameter) + { + // Have to clone the parameter for any children use, it carries block sensitive data + return parameter.Clone (); + } + + protected virtual void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + args = new Arguments (2); + + LambdaExpression selector = new LambdaExpression (loc); + + block.SetParameter (parameter); + selector.Block = block; + selector.Block.AddStatement (new ContextualReturn (expr)); + + args.Add (new Argument (selector)); + } + + protected Invocation CreateQueryExpression (Expression lSide, Arguments arguments) + { + return new QueryExpressionInvocation ( + new QueryExpressionAccess (lSide, MethodName, loc), arguments); + } + + protected abstract string MethodName { get; } + + public AQueryClause Next { + set { + next = value; + } + } + + public AQueryClause Tail { + get { + return next == null ? this : next.Tail; + } + } + } + + // + // A query clause with an identifier (range variable) + // + public abstract class ARangeVariableQueryClause : AQueryClause + { + sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter + { + public RangeAnonymousTypeParameter (Expression initializer, RangeVariable parameter) + : base (initializer, parameter.Name, parameter.Location) + { + } + + protected override void Error_InvalidInitializer (ResolveContext ec, string initializer) + { + ec.Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'", + Name, initializer); + } + } + + class RangeParameterReference : ParameterReference + { + Parameter parameter; + + public RangeParameterReference (Parameter p) + : base (null, p.Location) + { + this.parameter = p; + } + + protected override Expression DoResolve (ResolveContext ec) + { + pi = ec.CurrentBlock.ParametersBlock.GetParameterInfo (parameter); + return base.DoResolve (ec); + } + } + + protected RangeVariable identifier; + + public RangeVariable IntoVariable { + get { + return identifier; + } + } + + protected ARangeVariableQueryClause (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, expr, loc) + { + this.identifier = identifier; + } + + public FullNamedExpression IdentifierType { get; set; } + + protected Invocation CreateCastExpression (Expression lSide) + { + return new QueryExpressionInvocation ( + new QueryExpressionAccess (lSide, "Cast", new TypeArguments (IdentifierType), loc), null); + } + + protected override Parameter CreateChildrenParameters (Parameter parameter) + { + return new QueryBlock.TransparentParameter (parameter.Clone (), GetIntoVariable ()); + } + + protected static Expression CreateRangeVariableType (ResolveContext rc, Parameter parameter, RangeVariable name, Expression init) + { + var args = new List (2); + + // + // The first argument is the reference to the parameter + // + args.Add (new AnonymousTypeParameter (new RangeParameterReference (parameter), parameter.Name, parameter.Location)); + + // + // The second argument is the linq expression + // + args.Add (new RangeAnonymousTypeParameter (init, name)); + + // + // Create unique anonymous type + // + return new NewAnonymousType (args, rc.MemberContext.CurrentMemberDefinition.Parent, name.Location); + } + + protected virtual RangeVariable GetIntoVariable () + { + return identifier; + } + } + + public sealed class RangeVariable : INamedBlockVariable + { + Block block; + + public RangeVariable (string name, Location loc) + { + Name = name; + Location = loc; + } + + #region Properties + + public Block Block { + get { + return block; + } + set { + block = value; + } + } + + public bool IsDeclared { + get { + return true; + } + } + + public Location Location { get; private set; } + + public string Name { get; private set; } + + #endregion + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + // + // We know the variable name is somewhere in the scope. This generates + // an access expression from current block + // + var pb = rc.CurrentBlock.ParametersBlock; + while (true) { + if (pb is QueryBlock) { + for (int i = pb.Parameters.Count - 1; i >= 0; --i) { + var p = pb.Parameters[i]; + if (p.Name == Name) + return pb.GetParameterReference (i, loc); + + Expression expr = null; + var tp = p as QueryBlock.TransparentParameter; + while (tp != null) { + if (expr == null) + expr = pb.GetParameterReference (i, loc); + else + expr = new TransparentMemberAccess (expr, tp.Name); + + if (tp.Identifier == Name) + return new TransparentMemberAccess (expr, Name); + + if (tp.Parent.Name == Name) + return new TransparentMemberAccess (expr, Name); + + tp = tp.Parent as QueryBlock.TransparentParameter; + } + } + } + + if (pb == block) + return null; + + pb = pb.Parent.ParametersBlock; + } + } + } + + public class QueryStartClause : ARangeVariableQueryClause + { + public QueryStartClause (QueryBlock block, Expression expr, RangeVariable identifier, Location loc) + : base (block, identifier, expr, loc) + { + block.AddRangeVariable (identifier); + } + + public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter) + { +/* + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (expr.Type == InternalType.Dynamic || expr.Type == TypeManager.void_type) { + ec.Report.Error (1979, expr.Location, + "Query expression with a source or join sequence of type `{0}' is not allowed", + TypeManager.CSharpName (expr.Type)); + return null; + } +*/ + + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + if (parameter == null) + lSide = expr; + + return next.BuildQueryClause (ec, lSide, new ImplicitLambdaParameter (identifier.Name, identifier.Location)); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = BuildQueryClause (ec, null, null); + return e.Resolve (ec); + } + + protected override string MethodName { + get { throw new NotSupportedException (); } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + + public class GroupBy : AQueryClause + { + Expression element_selector; + QueryBlock element_block; + + public Expression ElementSelector { + get { return this.element_selector; } + } + + public GroupBy (QueryBlock block, Expression elementSelector, QueryBlock elementBlock, Expression keySelector, Location loc) + : base (block, keySelector, loc) + { + // + // Optimizes clauses like `group A by A' + // + if (!elementSelector.Equals (keySelector)) { + this.element_selector = elementSelector; + this.element_block = elementBlock; + } + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + base.CreateArguments (ec, parameter, ref args); + + if (element_selector != null) { + LambdaExpression lambda = new LambdaExpression (element_selector.Location); + + element_block.SetParameter (parameter.Clone ()); + lambda.Block = element_block; + lambda.Block.AddStatement (new ContextualReturn (element_selector)); + args.Add (new Argument (lambda)); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + GroupBy t = (GroupBy) target; + if (element_selector != null) { + t.element_selector = element_selector.Clone (clonectx); + t.element_block = (QueryBlock) element_block.Clone (clonectx); + } + + base.CloneTo (clonectx, t); + } + + protected override string MethodName { + get { return "GroupBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Join : SelectMany + { + QueryBlock inner_selector, outer_selector; + + public RangeVariable JoinVariable { + get { return this.GetIntoVariable (); } + } + + public QueryBlock InnerSelector { + get { + return inner_selector; + } + } + + public QueryBlock OuterSelector { + get { + return outer_selector; + } + } + + public Join (QueryBlock block, RangeVariable lt, Expression inner, QueryBlock outerSelector, QueryBlock innerSelector, Location loc) + : base (block, lt, inner, loc) + { + this.outer_selector = outerSelector; + this.inner_selector = innerSelector; + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + args = new Arguments (4); + + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + args.Add (new Argument (expr)); + + outer_selector.SetParameter (parameter.Clone ()); + var lambda = new LambdaExpression (outer_selector.StartLocation); + lambda.Block = outer_selector; + args.Add (new Argument (lambda)); + + inner_selector.SetParameter (new ImplicitLambdaParameter (identifier.Name, identifier.Location)); + lambda = new LambdaExpression (inner_selector.StartLocation); + lambda.Block = inner_selector; + args.Add (new Argument (lambda)); + + base.CreateArguments (ec, parameter, ref args); + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + Join t = (Join) target; + t.inner_selector = (QueryBlock) inner_selector.Clone (clonectx); + t.outer_selector = (QueryBlock) outer_selector.Clone (clonectx); + base.CloneTo (clonectx, t); + } + + protected override string MethodName { + get { return "Join"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class GroupJoin : Join + { + readonly RangeVariable into; + + public GroupJoin (QueryBlock block, RangeVariable lt, Expression inner, + QueryBlock outerSelector, QueryBlock innerSelector, RangeVariable into, Location loc) + : base (block, lt, inner, outerSelector, innerSelector, loc) + { + this.into = into; + } + + protected override RangeVariable GetIntoVariable () + { + return into; + } + + protected override string MethodName { + get { return "GroupJoin"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Let : ARangeVariableQueryClause + { + public Let (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, identifier, expr, loc) + { + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + expr = CreateRangeVariableType (ec, parameter, identifier, expr); + base.CreateArguments (ec, parameter, ref args); + } + + protected override string MethodName { + get { return "Select"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Select : AQueryClause + { + public Select (QueryBlock block, Expression expr, Location loc) + : base (block, expr, loc) + { + } + + // + // For queries like `from a orderby a select a' + // the projection is transparent and select clause can be safely removed + // + public bool IsRequired (Parameter parameter) + { + SimpleName sn = expr as SimpleName; + if (sn == null) + return true; + + return sn.Name != parameter.Name; + } + + protected override string MethodName { + get { return "Select"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public class SelectMany : ARangeVariableQueryClause + { + public SelectMany (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, identifier, expr, loc) + { + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + if (args == null) { + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + base.CreateArguments (ec, parameter.Clone (), ref args); + } + + Expression result_selector_expr; + QueryBlock result_block; + + var target = GetIntoVariable (); + var target_param = new ImplicitLambdaParameter (target.Name, target.Location); + + // + // When select follows use it as a result selector + // + if (next is Select) { + result_selector_expr = next.Expr; + + result_block = next.block; + result_block.SetParameters (parameter, target_param); + + next = next.next; + } else { + result_selector_expr = CreateRangeVariableType (ec, parameter, target, new SimpleName (target.Name, target.Location)); + + result_block = new QueryBlock (block.Parent, block.StartLocation); + result_block.SetParameters (parameter, target_param); + } + + LambdaExpression result_selector = new LambdaExpression (Location); + result_selector.Block = result_block; + result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr)); + + args.Add (new Argument (result_selector)); + } + + protected override string MethodName { + get { return "SelectMany"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Where : AQueryClause + { + public Where (QueryBlock block, Expression expr, Location loc) + : base (block, expr, loc) + { + } + + protected override string MethodName { + get { return "Where"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class OrderByAscending : AQueryClause + { + public OrderByAscending (QueryBlock block, Expression expr) + : base (block, expr, expr.Location) + { + } + + protected override string MethodName { + get { return "OrderBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class OrderByDescending : AQueryClause + { + public OrderByDescending (QueryBlock block, Expression expr) + : base (block, expr, expr.Location) + { + } + + protected override string MethodName { + get { return "OrderByDescending"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ThenByAscending : OrderByAscending + { + public ThenByAscending (QueryBlock block, Expression expr) + : base (block, expr) + { + } + + protected override string MethodName { + get { return "ThenBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ThenByDescending : OrderByDescending + { + public ThenByDescending (QueryBlock block, Expression expr) + : base (block, expr) + { + } + + protected override string MethodName { + get { return "ThenByDescending"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Implicit query block + // + public class QueryBlock : ParametersBlock + { + // + // Transparent parameters are used to package up the intermediate results + // and pass them onto next clause + // + public sealed class TransparentParameter : ImplicitLambdaParameter + { + public static int Counter; + const string ParameterNamePrefix = "<>__TranspIdent"; + + public readonly Parameter Parent; + public readonly string Identifier; + + public TransparentParameter (Parameter parent, RangeVariable identifier) + : base (ParameterNamePrefix + Counter++, identifier.Location) + { + Parent = parent; + Identifier = identifier.Name; + } + + public static void Reset () + { + Counter = 0; + } + } + + public QueryBlock (Block parent, Location start) + : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start) + { + flags |= Flags.CompilerGenerated; + } + + public void AddRangeVariable (RangeVariable variable) + { + variable.Block = this; + AddLocalName (variable.Name, variable); + } + + public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable, string reason) + { + TopBlock.Report.Error (1931, variable.Location, + "A range variable `{0}' conflicts with a previous declaration of `{0}'", + name); + } + + public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable) + { + TopBlock.Report.Error (1930, variable.Location, + "A range variable `{0}' has already been declared in this scope", + name); + } + + public override void Error_AlreadyDeclaredTypeParameter (string name, Location loc) + { + TopBlock.Report.Error (1948, loc, + "A range variable `{0}' conflicts with a method type parameter", + name); + } + + public void SetParameter (Parameter parameter) + { + base.parameters = new ParametersCompiled (parameter); + base.parameter_info = new ParameterInfo[] { + new ParameterInfo (this, 0) + }; + } + + public void SetParameters (Parameter first, Parameter second) + { + base.parameters = new ParametersCompiled (first, second); + base.parameter_info = new ParameterInfo[] { + new ParameterInfo (this, 0), + new ParameterInfo (this, 1) + }; + } + } + + sealed class TransparentMemberAccess : MemberAccess + { + public TransparentMemberAccess (Expression expr, string name) + : base (expr, name) + { + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + rc.Report.Error (1947, loc, + "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value", + Name); + + return null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs new file mode 100644 index 0000000000..b2efb35c1a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs @@ -0,0 +1,282 @@ +// +// literal.cs: Literal representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. +// +// +// Notice that during parsing we create objects of type Literal, but the +// types are not loaded (thats why the Resolve method has to assign the +// type at that point). +// +// Literals differ from the constants in that we know we encountered them +// as a literal in the source code (and some extra rules apply there) and +// they have to be resolved (since during parsing we have not loaded the +// types yet) while constants are created only after types have been loaded +// and are fully resolved when born. +// + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public interface ILiteralConstant + { +#if FULL_AST + char[] ParsedValue { get; set; } +#endif + } + + // + // The null literal + // + // Note: C# specification null-literal is NullLiteral of NullType type + // + public class NullLiteral : NullConstant + { + // + // Default type of null is an object + // + public NullLiteral (Location loc) + : base (InternalType.NullLiteral, loc) + { + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec t, bool expl) + { + if (t.IsGenericParameter) { + ec.Report.Error(403, loc, + "Cannot convert null to the type parameter `{0}' because it could be a value " + + "type. Consider using `default ({0})' instead", t.Name); + return; + } + + if (TypeSpec.IsValueType (t)) { + ec.Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type", + TypeManager.CSharpName(t)); + return; + } + + base.Error_ValueCannotBeConverted (ec, loc, t, expl); + } + + public override string GetValueAsLiteral () + { + return "null"; + } + + public override bool IsLiteral { + get { return true; } + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return System.Linq.Expressions.Expression.Constant (null); + } + } + + public class BoolLiteral : BoolConstant, ILiteralConstant + { + public BoolLiteral (BuiltinTypes types, bool val, Location loc) + : base (types, val, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class CharLiteral : CharConstant, ILiteralConstant + { + public CharLiteral (BuiltinTypes types, char c, Location loc) + : base (types, c, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class IntLiteral : IntConstant, ILiteralConstant + { + public IntLiteral (BuiltinTypes types, int l, Location loc) + : base (types, l, loc) + { + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + // + // The 0 literal can be converted to an enum value + // + if (Value == 0 && TypeManager.IsEnumType (type)) { + Constant c = ConvertImplicitly (EnumSpec.GetUnderlyingType (type)); + if (c == null) + return null; + + return new EnumConstant (c, type); + } + + return base.ConvertImplicitly (type); + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class UIntLiteral : UIntConstant, ILiteralConstant + { + public UIntLiteral (BuiltinTypes types, uint l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class LongLiteral : LongConstant, ILiteralConstant + { + public LongLiteral (BuiltinTypes types, long l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class ULongLiteral : ULongConstant, ILiteralConstant + { + public ULongLiteral (BuiltinTypes types, ulong l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class FloatLiteral : FloatConstant, ILiteralConstant + { + public FloatLiteral (BuiltinTypes types, float f, Location loc) + : base (types, f, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class DoubleLiteral : DoubleConstant, ILiteralConstant + { + public DoubleLiteral (BuiltinTypes types, double d, Location loc) + : base (types, d, loc) + { + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + if (target.BuiltinType == BuiltinTypeSpec.Type.Float) { + Error_664 (ec, loc, "float", "f"); + return; + } + + if (target.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + Error_664 (ec, loc, "decimal", "m"); + return; + } + + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + + static void Error_664 (ResolveContext ec, Location loc, string type, string suffix) + { + ec.Report.Error (664, loc, + "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type", + type, suffix); + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class DecimalLiteral : DecimalConstant, ILiteralConstant + { + public DecimalLiteral (BuiltinTypes types, decimal d, Location loc) + : base (types, d, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class StringLiteral : StringConstant, ILiteralConstant + { + public StringLiteral (BuiltinTypes types, string s, Location loc) + : base (types, s, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs new file mode 100644 index 0000000000..fd3fe3aaa3 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs @@ -0,0 +1,912 @@ +// +// location.cs: Keeps track of the location of source code entity +// +// Author: +// Miguel de Icaza +// Atsushi Enomoto +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001 Ximian, Inc. +// Copyright 2005 Novell, Inc. +// + +using System; +using System.IO; +using System.Collections.Generic; +using Mono.CompilerServices.SymbolWriter; +using System.Diagnostics; +using System.Linq; + +namespace Mono.CSharp { + /// + /// This is one single source file. + /// + /// + /// This is intentionally a class and not a struct since we need + /// to pass this by reference. + /// + public class SourceFile : ISourceFile, IEquatable + { + public readonly string Name; + public readonly string FullPathName; + public readonly int Index; + public bool AutoGenerated; + + SourceFileEntry file; + byte[] guid, checksum; + + public SourceFile (string name, string path, int index) + { + this.Index = index; + this.Name = name; + this.FullPathName = path; + } + + public SourceFileEntry SourceFileEntry { + get { return file; } + } + + SourceFileEntry ISourceFile.Entry { + get { return file; } + } + + public void SetChecksum (byte[] guid, byte[] checksum) + { + this.guid = guid; + this.checksum = checksum; + } + + public virtual void DefineSymbolInfo (MonoSymbolWriter symwriter) + { + if (guid != null) + file = symwriter.DefineDocument (FullPathName, guid, checksum); + else { + file = symwriter.DefineDocument (FullPathName); + if (AutoGenerated) + file.SetAutoGenerated (); + } + } + + public bool Equals (SourceFile other) + { + return FullPathName == other.FullPathName; + } + + public override string ToString () + { + return String.Format ("SourceFile ({0}:{1}:{2}:{3})", + Name, FullPathName, Index, SourceFileEntry); + } + } + + public class CompilationSourceFile : SourceFile, ICompileUnit + { + CompileUnitEntry comp_unit; + Dictionary include_files; + Dictionary conditionals; + NamespaceContainer ns_container; + + public CompilationSourceFile (string name, string fullPathName, int index) + : base (name, fullPathName, index) + { + } + + CompileUnitEntry ICompileUnit.Entry { + get { return comp_unit; } + } + + public CompileUnitEntry CompileUnitEntry { + get { return comp_unit; } + } + + public NamespaceContainer NamespaceContainer { + get { + return ns_container; + } + set { + ns_container = value; + } + } + + public void AddIncludeFile (SourceFile file) + { + if (file == this) + return; + + if (include_files == null) + include_files = new Dictionary (); + + if (!include_files.ContainsKey (file.FullPathName)) + include_files.Add (file.FullPathName, file); + } + + public void AddDefine (string value) + { + if (conditionals == null) + conditionals = new Dictionary (2); + + conditionals [value] = true; + } + + public void AddUndefine (string value) + { + if (conditionals == null) + conditionals = new Dictionary (2); + + conditionals [value] = false; + } + + public override void DefineSymbolInfo (MonoSymbolWriter symwriter) + { + base.DefineSymbolInfo (symwriter); + + comp_unit = symwriter.DefineCompilationUnit (SourceFileEntry); + + if (include_files != null) { + foreach (SourceFile include in include_files.Values) { + include.DefineSymbolInfo (symwriter); + comp_unit.AddFile (include.SourceFileEntry); + } + } + } + + public bool IsConditionalDefined (CompilerContext ctx, string value) + { + if (conditionals != null) { + bool res; + if (conditionals.TryGetValue (value, out res)) + return res; + + // When conditional was undefined + if (conditionals.ContainsKey (value)) + return false; + } + + return ctx.Settings.IsConditionalSymbolDefined (value); + } + } + + /// + /// Keeps track of the location in the program + /// + /// + /// + /// This uses a compact representation and a couple of auxiliary + /// structures to keep track of tokens to (file,line and column) + /// mappings. The usage of the bits is: + /// + /// - 16 bits for "checkpoint" which is a mixed concept of + /// file and "line segment" + /// - 8 bits for line delta (offset) from the line segment + /// - 8 bits for column number. + /// + /// http://lists.ximian.com/pipermail/mono-devel-list/2004-December/009508.html + /// + public struct Location : IEquatable + { + struct Checkpoint { + public readonly int LineOffset; + public readonly int CompilationUnit; + public readonly int File; + + public Checkpoint (int compile_unit, int file, int line) + { + File = file; + CompilationUnit = compile_unit; + LineOffset = line - (int) (line % (1 << line_delta_bits)); + } + } + +#if FULL_AST + long token; + + const int column_bits = 24; + const int line_delta_bits = 24; +#else + int token; + + const int column_bits = 8; + const int line_delta_bits = 8; +#endif + const int checkpoint_bits = 16; + + // -2 because the last one is used for hidden + const int max_column = (1 << column_bits) - 2; + const int column_mask = (1 << column_bits) - 1; + + static List source_list; + static int current_source; + static int current_compile_unit; + static Checkpoint [] checkpoints; + static int checkpoint_index; + + public readonly static Location Null = new Location (-1); + public static bool InEmacs; + + static Location () + { + Reset (); + } + + public static void Reset () + { + source_list = new List (); + current_source = 0; + current_compile_unit = 0; + checkpoint_index = 0; + } + + public static SourceFile AddFile (string name, string fullName) + { + var source = new SourceFile (name, fullName, source_list.Count + 1); + source_list.Add (source); + return source; + } + + // + // After adding all source files we want to compile with AddFile(), this method + // must be called to `reserve' an appropriate number of bits in the token for the + // source file. We reserve some extra space for files we encounter via #line + // directives while parsing. + // + static public void Initialize (List files) + { +#if NET_4_0 + source_list.AddRange (files); +#else + source_list.AddRange (files.ToArray ()); +#endif + + checkpoints = new Checkpoint [source_list.Count * 2]; + if (checkpoints.Length > 0) + checkpoints [0] = new Checkpoint (0, 0, 0); + } + + static public void Push (CompilationSourceFile compile_unit, SourceFile file) + { + current_source = file != null ? file.Index : -1; + current_compile_unit = compile_unit != null ? compile_unit.Index : -1; + // File is always pushed before being changed. + } + + public Location (int row) + : this (row, 0) + { + } + + public Location (int row, int column) + { + if (row <= 0) + token = 0; + else { + if (column > max_column) + column = max_column; + else if (column < 0) + column = max_column + 1; + + long target = -1; + long delta = 0; + + // FIXME: This value is certainly wrong but what was the intension + int max = checkpoint_index < 10 ? + checkpoint_index : 10; + for (int i = 0; i < max; i++) { + int offset = checkpoints [checkpoint_index - i].LineOffset; + delta = row - offset; + if (delta >= 0 && + delta < (1 << line_delta_bits) && + checkpoints [checkpoint_index - i].File == current_source) { + target = checkpoint_index - i; + break; + } + } + if (target == -1) { + AddCheckpoint (current_compile_unit, current_source, row); + target = checkpoint_index; + delta = row % (1 << line_delta_bits); + } + + long l = column + + (delta << column_bits) + + (target << (line_delta_bits + column_bits)); +#if FULL_AST + token = l; +#else + token = l > 0xFFFFFFFF ? 0 : (int) l; +#endif + } + } + + public static Location operator - (Location loc, int columns) + { + return new Location (loc.Row, loc.Column - columns); + } + + static void AddCheckpoint (int compile_unit, int file, int row) + { + if (checkpoints.Length == ++checkpoint_index) { + Array.Resize (ref checkpoints, checkpoint_index * 2); + } + checkpoints [checkpoint_index] = new Checkpoint (compile_unit, file, row); + } + + string FormatLocation (string fileName) + { + if (column_bits == 0 || InEmacs) + return fileName + "(" + Row.ToString () + "):"; + + return fileName + "(" + Row.ToString () + "," + Column.ToString () + + (Column == max_column ? "+):" : "):"); + } + + public override string ToString () + { + return FormatLocation (Name); + } + + public string ToStringFullName () + { + return FormatLocation (NameFullPath); + } + + /// + /// Whether the Location is Null + /// + public bool IsNull { + get { return token == 0; } + } + + public string Name { + get { + int index = File; + if (token == 0 || index == 0) + return "Internal"; + if (source_list == null || index - 1 >= source_list.Count) + return "unknown_file"; + + SourceFile file = source_list [index - 1]; + return file.Name; + } + } + + public string NameFullPath { + get { + int index = File; + if (token == 0 || index == 0) + return "Internal"; + + return source_list[index - 1].FullPathName; + } + } + + int CheckpointIndex { + get { + const int checkpoint_mask = (1 << checkpoint_bits) - 1; + return ((int) (token >> (line_delta_bits + column_bits))) & checkpoint_mask; + } + } + + public int Row { + get { + if (token == 0) + return 1; + + int offset = checkpoints[CheckpointIndex].LineOffset; + + const int line_delta_mask = (1 << column_bits) - 1; + return offset + (((int)(token >> column_bits)) & line_delta_mask); + } + } + + public int Column { + get { + if (token == 0) + return 1; + int col = (int) (token & column_mask); + return col > max_column ? 1 : col; + } + } + + public bool Hidden { + get { + return (int) (token & column_mask) == max_column + 1; + } + } + + public int CompilationUnitIndex { + get { + if (token == 0) + return 0; +if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex)); + return checkpoints [CheckpointIndex].CompilationUnit; + } + } + + public int File { + get { + if (token == 0) + return 0; +if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex)); + return checkpoints [CheckpointIndex].File; + } + } + + // The ISymbolDocumentWriter interface is used by the symbol writer to + // describe a single source file - for each source file there's exactly + // one corresponding ISymbolDocumentWriter instance. + // + // This class has an internal hash table mapping source document names + // to such ISymbolDocumentWriter instances - so there's exactly one + // instance per document. + // + // This property returns the ISymbolDocumentWriter instance which belongs + // to the location's source file. + // + // If we don't have a symbol writer, this property is always null. + public SourceFile SourceFile { + get { + int index = File; + if (index == 0) + return null; + return (SourceFile) source_list [index - 1]; + } + } + + public CompilationSourceFile CompilationUnit { + get { + int index = CompilationUnitIndex; + if (index == 0) + return null; + return (CompilationSourceFile) source_list [index - 1]; + } + } + + #region IEquatable Members + + public bool Equals (Location other) + { + return this.token == other.token; + } + + #endregion + } + + public class SpecialsBag + { + public enum CommentType + { + Single, + Multi, + Documentation + } + + public class Comment + { + public readonly CommentType CommentType; + public readonly bool StartsLine; + public readonly int Line; + public readonly int Col; + public readonly int EndLine; + public readonly int EndCol; + public readonly string Content; + + public Comment (CommentType commentType, bool startsLine, int line, int col, int endLine, int endCol, string content) + { + this.CommentType = commentType; + this.StartsLine = startsLine; + this.Line = line; + this.Col = col; + this.EndLine = endLine; + this.EndCol = endCol; + this.Content = content; + } + + public override string ToString () + { + return string.Format ("[Comment: CommentType={0}, Line={1}, Col={2}, EndLine={3}, EndCol={4}, Content={5}]", CommentType, Line, Col, EndLine, EndCol, Content); + } + } + + public class PreProcessorDirective + { + public readonly int Line; + public readonly int Col; + public readonly int EndLine; + public readonly int EndCol; + + public readonly Tokenizer.PreprocessorDirective Cmd; + public readonly string Arg; + + public PreProcessorDirective (int line, int col, int endLine, int endCol, Tokenizer.PreprocessorDirective cmd, string arg) + { + this.Line = line; + this.Col = col; + this.EndLine = endLine; + this.EndCol = endCol; + this.Cmd = cmd; + this.Arg = arg; + } + + public override string ToString () + { + return string.Format ("[PreProcessorDirective: Line={0}, Col={1}, EndLine={2}, EndCol={3}, Cmd={4}, Arg={5}]", Line, Col, EndLine, EndCol, Cmd, Arg); + } + } + + public readonly List Specials = new List (); + + CommentType curComment; + bool startsLine; + int startLine, startCol; + System.Text.StringBuilder contentBuilder = new System.Text.StringBuilder (); + + [Conditional ("FULL_AST")] + public void StartComment (CommentType type, bool startsLine, int startLine, int startCol) + { + curComment = type; + this.startsLine = startsLine; + this.startLine = startLine; + this.startCol = startCol; + contentBuilder.Length = 0; + } + + [Conditional ("FULL_AST")] + public void PushCommentChar (int ch) + { + if (ch < 0) + return; + contentBuilder.Append ((char)ch); + } + [Conditional ("FULL_AST")] + public void PushCommentString (string str) + { + contentBuilder.Append (str); + } + + [Conditional ("FULL_AST")] + public void EndComment (int endLine, int endColumn) + { + Specials.Add (new Comment (curComment, startsLine, startLine, startCol, endLine, endColumn, contentBuilder.ToString ())); + } + + [Conditional ("FULL_AST")] + public void AddPreProcessorDirective (int startLine, int startCol, int endLine, int endColumn, Tokenizer.PreprocessorDirective cmd, string arg) + { + Specials.Add (new PreProcessorDirective (startLine, startCol, endLine, endColumn, cmd, arg)); + } + } + + // + // A bag of additional locations to support full ast tree + // + public class LocationsBag + { + public class MemberLocations + { + public IList> Modifiers { get; internal set; } + List locations; + + public MemberLocations (IList> mods, IEnumerable locs) + { + Modifiers = mods; + locations = locs != null ? new List (locs) : null; + } + + #region Properties + + public Location this [int index] { + get { + return locations [index]; + } + } + + public int Count { + get { + return locations != null ? locations.Count : 0; + } + } + + #endregion + + public void AddLocations (params Location[] additional) + + { + + AddLocations ((IEnumerable)additional); + + } + public void AddLocations (IEnumerable additional) + { + if (additional == null) + return; + if (locations == null) { + locations = new List(additional); + } else { + locations.AddRange (additional); + } + } + } + + public MemberCore LastMember { + get; + private set; + } + + Dictionary> simple_locs = new Dictionary> (ReferenceEquality.Default); + Dictionary member_locs = new Dictionary (ReferenceEquality.Default); + + [Conditional ("FULL_AST")] + public void AddLocation (object element, params Location[] locations) + { + AddLocation (element, (IEnumerable)locations); + } + + [Conditional ("FULL_AST")] + public void AddLocation (object element, IEnumerable locations) + { + if (element == null || locations == null) + return; + simple_locs.Add (element, new List (locations)); + } + + [Conditional ("FULL_AST")] + public void AddStatement (object element, params Location[] locations) + { + if (element == null) + return; + if (locations.Length == 0) + throw new ArgumentException ("Statement is missing semicolon location"); + simple_locs.Add (element, new List(locations)); + } + + [Conditional ("FULL_AST")] + public void AddMember (MemberCore member, IList> modLocations, params Location[] locations) + { + LastMember = member; + if (member == null) + return; + + MemberLocations existing; + if (member_locs.TryGetValue (member, out existing)) { + existing.Modifiers = modLocations; + existing.AddLocations (locations); + return; + } + member_locs.Add (member, new MemberLocations (modLocations, locations)); + } + [Conditional ("FULL_AST")] + public void AddMember (MemberCore member, IList> modLocations, IEnumerable locations) + { + LastMember = member; + if (member == null) + return; + + MemberLocations existing; + if (member_locs.TryGetValue (member, out existing)) { + existing.Modifiers = modLocations; + existing.AddLocations (locations); + return; + } + member_locs.Add (member, new MemberLocations (modLocations, locations)); + } + + [Conditional ("FULL_AST")] + public void AppendTo (object existing, params Location[] locations) + { + AppendTo (existing, (IEnumerable)locations); + + } + + [Conditional ("FULL_AST")] + public void AppendTo (object existing, IEnumerable locations) + { + if (existing == null) + return; + List locs; + if (simple_locs.TryGetValue (existing, out locs)) { + simple_locs [existing].AddRange (locations); + return; + } + AddLocation (existing, locations); + } + + [Conditional ("FULL_AST")] + public void AppendToMember (MemberCore existing, params Location[] locations) + { + AppendToMember (existing, (IEnumerable)locations); + + } + + [Conditional ("FULL_AST")] + public void AppendToMember (MemberCore existing, IEnumerable locations) + { + if (existing == null) + return; + MemberLocations member; + if (member_locs.TryGetValue (existing, out member)) { + member.AddLocations (locations); + return; + } + member_locs.Add (existing, new MemberLocations (null, locations)); + } + + public List GetLocations (object element) + { + if (element == null) + return null; + List found; + simple_locs.TryGetValue (element, out found); + return found; + } + + public MemberLocations GetMemberLocation (MemberCore element) + { + MemberLocations found; + member_locs.TryGetValue (element, out found); + return found; + } + } + + public class UsingsBag + { + public class Namespace { + public Location NamespaceLocation { get; set; } + public MemberName Name { get; set; } + + public Location OpenBrace { get; set; } + public Location CloseBrace { get; set; } + public Location OptSemicolon { get; set; } + + public List usings = new List (); + public List members = new List (); + + public Namespace () + { + // in case of missing close brace, set it to the highest value. + CloseBrace = new Location (int.MaxValue, int.MaxValue); + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class AliasUsing + { + public readonly Location UsingLocation; + public readonly Tokenizer.LocatedToken Identifier; + public readonly Location AssignLocation; + public readonly MemberName Nspace; + public readonly Location SemicolonLocation; + + public AliasUsing (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation) + { + this.UsingLocation = usingLocation; + this.Identifier = identifier; + this.AssignLocation = assignLocation; + this.Nspace = nspace; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class Using + { + public readonly Location UsingLocation; + public readonly MemberName NSpace; + public readonly Location SemicolonLocation; + + public Using (Location usingLocation, MemberName nSpace, Location semicolonLocation) + { + this.UsingLocation = usingLocation; + this.NSpace = nSpace; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class ExternAlias + { + public readonly Location ExternLocation; + public readonly Location AliasLocation; + public readonly Tokenizer.LocatedToken Identifier; + public readonly Location SemicolonLocation; + + public ExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation) + { + this.ExternLocation = externLocation; + this.AliasLocation = aliasLocation; + this.Identifier = identifier; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public Namespace Global { + get; + set; + } + Stack curNamespace = new Stack (); + + public UsingsBag () + { + Global = new Namespace (); + Global.OpenBrace = new Location (1, 1); + Global.CloseBrace = new Location (int.MaxValue, int.MaxValue); + curNamespace.Push (Global); + } + + [Conditional ("FULL_AST")] + public void AddUsingAlias (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new AliasUsing (usingLocation, identifier, assignLocation, nspace, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void AddUsing (Location usingLocation, MemberName nspace, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new Using (usingLocation, nspace, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void AddExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new ExternAlias (externLocation, aliasLocation, identifier, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void DeclareNamespace (Location namespaceLocation, MemberName nspace) + { + var newNamespace = new Namespace () { NamespaceLocation = namespaceLocation, Name = nspace }; + curNamespace.Peek ().members.Add (newNamespace); + curNamespace.Push (newNamespace); + } + + int typeLevel = 0; + [Conditional ("FULL_AST")] + public void PushTypeDeclaration (object type) + { + if (typeLevel == 0) + curNamespace.Peek ().members.Add (type); + typeLevel++; + } + + [Conditional ("FULL_AST")] + public void PopTypeDeclaration () + { + typeLevel--; + } + + [Conditional ("FULL_AST")] + public void EndNamespace (Location optSemicolon) + { + curNamespace.Peek ().OptSemicolon = optSemicolon; + curNamespace.Pop (); + } + + [Conditional ("FULL_AST")] + public void OpenNamespace (Location bracketLocation) + { + curNamespace.Peek ().OpenBrace = bracketLocation; + } + + [Conditional ("FULL_AST")] + public void CloseNamespace (Location bracketLocation) + { + curNamespace.Peek ().CloseBrace = bracketLocation; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs new file mode 100644 index 0000000000..a01100c25f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs @@ -0,0 +1,1409 @@ +// +// membercache.cs: A container for all member lookups +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2010 Novell, Inc +// +// + +using System; +using System.Collections.Generic; + +namespace Mono.CSharp { + + [Flags] + public enum MemberKind + { + Constructor = 1, + Event = 1 << 1, + Field = 1 << 2, + Method = 1 << 3, + Property = 1 << 4, + Indexer = 1 << 5, + Operator = 1 << 6, + Destructor = 1 << 7, + + Class = 1 << 11, + Struct = 1 << 12, + Delegate = 1 << 13, + Enum = 1 << 14, + Interface = 1 << 15, + TypeParameter = 1 << 16, + + ArrayType = 1 << 19, + PointerType = 1 << 20, + InternalCompilerType = 1 << 21, + MissingType = 1 << 22, + Void = 1 << 23, + + NestedMask = Class | Struct | Delegate | Enum | Interface, + GenericMask = Method | Class | Struct | Delegate | Interface, + MaskType = Constructor | Event | Field | Method | Property | Indexer | Operator | Destructor | NestedMask + } + + [Flags] + public enum BindingRestriction + { + None = 0, + + // Inspect only queried type members + DeclaredOnly = 1 << 1, + + // Exclude static + InstanceOnly = 1 << 2, + + NoAccessors = 1 << 3, + + // Member has to be override + OverrideOnly = 1 << 4 + } + + public struct MemberFilter : IEquatable + { + public readonly string Name; + public readonly MemberKind Kind; + public readonly AParametersCollection Parameters; + public readonly TypeSpec MemberType; + public readonly int Arity; // -1 to ignore the check + + private MemberFilter (string name, MemberKind kind) + { + Name = name; + Kind = kind; + Parameters = null; + MemberType = null; + Arity = -1; + } + + public MemberFilter (MethodSpec m) + { + Name = m.Name; + Kind = MemberKind.Method; + Parameters = m.Parameters; + MemberType = m.ReturnType; + Arity = m.Arity; + } + + public MemberFilter (string name, int arity, MemberKind kind, AParametersCollection param, TypeSpec type) + { + Name = name; + Kind = kind; + Parameters = param; + MemberType = type; + this.Arity = arity; + } + + public static MemberFilter Constructor (AParametersCollection param) + { + return new MemberFilter (Mono.CSharp.Constructor.ConstructorName, 0, MemberKind.Constructor, param, null); + } + + public static MemberFilter Property (string name, TypeSpec type) + { + return new MemberFilter (name, 0, MemberKind.Property, null, type); + } + + public static MemberFilter Field (string name, TypeSpec type) + { + return new MemberFilter (name, 0, MemberKind.Field, null, type); + } + + public static MemberFilter Method (string name, int arity, AParametersCollection param, TypeSpec type) + { + return new MemberFilter (name, arity, MemberKind.Method, param, type); + } + + #region IEquatable Members + + public bool Equals (MemberSpec other) + { + // Is the member of the correct type ? + // TODO: Isn't this redundant ? + if ((other.Kind & Kind & MemberKind.MaskType) == 0) + return false; + + // Check arity when not disabled + if (Arity >= 0 && Arity != other.Arity) + return false; + + if (Parameters != null) { + if (other is IParametersMember) { + var other_param = ((IParametersMember) other).Parameters; + if (!TypeSpecComparer.Override.IsEqual (Parameters, other_param)) + return false; + } else { + return false; + } + } + + if (MemberType != null) { + if (other is IInterfaceMemberSpec) { + var other_type = ((IInterfaceMemberSpec) other).MemberType; + if (!TypeSpecComparer.Override.IsEqual (other_type, MemberType)) + return false; + } else { + return false; + } + } + + return true; + } + + #endregion + } + + // + // The MemberCache is the main members container used by compiler. It contains + // all members imported or defined during compilation using on demand filling + // process. Inflated containers are also using MemberCache to make inflated + // members look like normal definition. + // + // All of the methods are performance and memory sensitive as the MemberCache + // is the underlying engine of all member based operations. + // + public class MemberCache + { + [Flags] + enum StateFlags + { + HasConversionOperator = 1 << 1, + HasUserOperator = 1 << 2 + } + + readonly Dictionary> member_hash; + Dictionary locase_members; + IList missing_abstract; + StateFlags state; // TODO: Move to TypeSpec or ITypeDefinition + + public static readonly string IndexerNameAlias = ""; + + public static readonly MemberCache Empty = new MemberCache (0); + + public MemberCache () + : this (16) + { + } + + public MemberCache (int capacity) + { + member_hash = new Dictionary> (capacity); + } + + public MemberCache (MemberCache cache) + : this (cache.member_hash.Count) + { + this.state = cache.state; + } + + // + // Creates a new MemberCache for the given `container'. + // + public MemberCache (TypeContainer container) + : this () // TODO: Optimize the size + { + } + + // + // For cases where we need to union cache members + // + public void AddBaseType (TypeSpec baseType) + { + var cache = baseType.MemberCache; + + IList list; + foreach (var entry in cache.member_hash) { + if (!member_hash.TryGetValue (entry.Key, out list)) { + if (entry.Value.Count == 1) { + list = entry.Value; + } else { + list = new List (entry.Value); + } + + member_hash.Add (entry.Key, list); + continue; + } + + foreach (var ce in entry.Value) { + if (list.Contains (ce)) + continue; + + if (list is MemberSpec[]) { + list = new List () { list [0] }; + member_hash[entry.Key] = list; + } + + list.Add (ce); + } + } + } + + // + // Member-cache does not contain base members but it does + // contain all base interface members, so the Lookup code + // can use simple inheritance rules. + // + public void AddInterface (TypeSpec iface) + { + var cache = iface.MemberCache; + + IList list; + foreach (var entry in cache.member_hash) { + if (!member_hash.TryGetValue (entry.Key, out list)) { + if (entry.Value.Count == 1) { + list = entry.Value; + } else { + list = new List (entry.Value); + } + + member_hash.Add (entry.Key, list); + continue; + } + + foreach (var ce in entry.Value) { + if (list.Contains (ce)) + continue; + + if (AddInterfaceMember (ce, ref list)) + member_hash[entry.Key] = list; + } + } + + // Add also all base interfaces + if (iface.Interfaces != null) { + foreach (var base_iface in iface.Interfaces) + AddInterface (base_iface); + } + } + + public void AddMember (InterfaceMemberBase imb, string exlicitName, MemberSpec ms) + { + // Explicit names cannot be looked-up but can be used for + // collision checking (no name mangling needed) + if (imb.IsExplicitImpl) + AddMember (exlicitName, ms, false); + else + AddMember (ms); + } + + // + // Add non-explicit member to member cache + // + public void AddMember (MemberSpec ms) + { + AddMember (GetLookupName (ms), ms, false); + } + + void AddMember (string name, MemberSpec member, bool removeHiddenMembers) + { + if (member.Kind == MemberKind.Operator) { + var dt = member.DeclaringType; + switch (dt.BuiltinType) { + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + // Some core types have user operators but they cannot be used as normal + // user operators as they are predefined and therefore having different + // rules (e.g. binary operators) by not setting the flag we hide them for + // user conversions + // TODO: Should I do this for all core types ? + break; + default: + if (name == Operator.GetMetadataName (Operator.OpType.Implicit) || name == Operator.GetMetadataName (Operator.OpType.Explicit)) { + state |= StateFlags.HasConversionOperator; + } else { + state |= StateFlags.HasUserOperator; + } + + break; + } + } + + IList list; + if (!member_hash.TryGetValue (name, out list)) { + member_hash.Add (name, new MemberSpec[] { member }); + return; + } + + if (removeHiddenMembers && member.DeclaringType.IsInterface) { + if (AddInterfaceMember (member, ref list)) + member_hash[name] = list; + } else { + if (list.Count == 1) { + list = new List () { list[0] }; + member_hash[name] = list; + } + + list.Add (member); + } + } + + public void AddMemberImported (MemberSpec ms) + { + AddMember (GetLookupName (ms), ms, true); + } + + // + // Ignores any base interface member which can be hidden + // by this interface + // + static bool AddInterfaceMember (MemberSpec member, ref IList existing) + { + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters; + + // + // interface IA : IB { int Prop { set; } } + // interface IB { bool Prop { get; } } + // + // IB.Prop is never accessible from IA interface + // + for (int i = 0; i < existing.Count; ++i) { + var entry = existing[i]; + + if (entry.Arity != member.Arity) + continue; + + if (entry is IParametersMember) { + var entry_param = ((IParametersMember) entry).Parameters; + if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param)) + continue; + } + + if (member.DeclaringType.ImplementsInterface (entry.DeclaringType, false)) { + if (existing.Count == 1) { + existing = new MemberSpec[] { member }; + return true; + } + + existing.RemoveAt (i--); + continue; + } + + if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor) || + entry.DeclaringType.ImplementsInterface (member.DeclaringType, false)) + return false; + } + + if (existing.Count == 1) { + existing = new List () { existing[0], member }; + return true; + } + + existing.Add (member); + return false; + } + + public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions) + { + do { + IList applicable; + if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) { + // Start from the end because interface members are in reverse order + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable [i]; + + if ((restrictions & BindingRestriction.InstanceOnly) != 0 && entry.IsStatic) + continue; + + if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor) + continue; + + if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0) + continue; + + if (!filter.Equals (entry)) + continue; + + if ((restrictions & BindingRestriction.DeclaredOnly) != 0 && container.IsInterface && entry.DeclaringType != container) + continue; + + return entry; + } + } + + if ((restrictions & BindingRestriction.DeclaredOnly) != 0) + break; + + container = container.BaseType; + } while (container != null); + + return null; + } + + // + // A special method to work with member lookup only. It returns a list of all members named @name + // starting from @container. It's very performance sensitive + // + public static IList FindMembers (TypeSpec container, string name, bool declaredOnly) + { + IList applicable; + + do { + if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnly) + return applicable; + + container = container.BaseType; + } while (container != null); + + return null; + } + + // + // Finds the nested type in container + // + public static TypeSpec FindNestedType (TypeSpec container, string name, int arity) + { + IList applicable; + TypeSpec best_match = null; + do { + // TODO: Don't know how to handle this yet + // When resolving base type of nested type, parent type must have + // base type resolved to scan full hierarchy correctly + // Similarly MemberCacheTypes will inflate BaseType and Interfaces + // based on type definition + var tc = container.MemberDefinition as TypeContainer; + if (tc != null) + tc.DefineType (); + + if (container.MemberCacheTypes.member_hash.TryGetValue (name, out applicable)) { + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable[i]; + if ((entry.Kind & MemberKind.NestedMask) == 0) + continue; + + var ts = (TypeSpec) entry; + if (arity == ts.Arity) + return ts; + + if (arity < 0) { + if (best_match == null) { + best_match = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (ts.Arity + arity)) { + best_match = ts; + } + } + } + } + + container = container.BaseType; + } while (container != null); + + return best_match; + } + + // + // Looks for extension methods with defined name and extension type + // + public List FindExtensionMethods (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity) + { + IList entries; + if (!member_hash.TryGetValue (name, out entries)) + return null; + + List candidates = null; + foreach (var entry in entries) { + if (entry.Kind != MemberKind.Method || (arity > 0 && entry.Arity != arity)) + continue; + + var ms = (MethodSpec) entry; + if (!ms.IsExtensionMethod) + continue; + + if (!ms.IsAccessible (invocationContext)) + continue; + + // + // Extension methods cannot be nested hence checking parent is enough + // + if ((ms.DeclaringType.Modifiers & Modifiers.INTERNAL) != 0 && !ms.DeclaringType.MemberDefinition.IsInternalAsPublic (invocationContext.Module.DeclaringAssembly)) + continue; + + if (candidates == null) + candidates = new List (); + candidates.Add (ms); + } + + return candidates; + } + + // + // Returns base members of @member member if no exact match is found @bestCandidate returns + // the best match + // + public static MemberSpec FindBaseMember (MemberCore member, out MemberSpec bestCandidate, ref bool overrides) + { + bestCandidate = null; + var container = member.Parent.PartialContainer.Definition; + if (!container.IsInterface) { + container = container.BaseType; + + // It can happen for a user definition of System.Object + if (container == null) + return null; + } + + string name = GetLookupName (member); + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : null; + + var mkind = GetMemberCoreKind (member); + bool member_with_accessors = mkind == MemberKind.Indexer || mkind == MemberKind.Property; + + IList applicable; + MemberSpec ambig_candidate = null; + + do { + if (container.MemberCache.member_hash.TryGetValue (name, out applicable)) { + for (int i = 0; i < applicable.Count; ++i) { + var entry = applicable [i]; + + if ((entry.Modifiers & Modifiers.PRIVATE) != 0) + continue; + + if ((entry.Modifiers & Modifiers.AccessibilityMask) == Modifiers.INTERNAL && + !entry.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly)) + continue; + + // + // Isn't the member of same kind ? + // + if ((entry.Kind & ~MemberKind.Destructor & mkind & MemberKind.MaskType) == 0) { + // Destructors are ignored as they cannot be overridden by user + if ((entry.Kind & MemberKind.Destructor) != 0) + continue; + + // A method with different arity does not hide base member + if (mkind != MemberKind.Method && member.MemberName.Arity != entry.Arity) + continue; + + bestCandidate = entry; + return null; + } + + // + // Same kind of different arity is valid + // + if (member.MemberName.Arity != entry.Arity) { + continue; + } + + if ((entry.Kind & mkind & (MemberKind.Method | MemberKind.Indexer)) != 0) { + if (entry.IsAccessor != member is AbstractPropertyEventMethod) + continue; + + var pm = entry as IParametersMember; + if (!TypeSpecComparer.Override.IsEqual (pm.Parameters, member_param)) + continue; + } + + // + // Skip override for member with accessors. It may not fully implement the base member + // but keep flag we found an implementation in case the base member is abstract + // + if (member_with_accessors && ((entry.Modifiers & (Modifiers.OVERRIDE | Modifiers.SEALED)) == Modifiers.OVERRIDE)) { + // + // Set candidate to override implementation to flag we found an implementation + // + overrides = true; + continue; + } + + // + // For members with parameters we can encounter an ambiguous candidates (they match exactly) + // because generic type parameters could be inflated into same types + // + if (ambig_candidate == null && (entry.Kind & mkind & (MemberKind.Method | MemberKind.Indexer)) != 0) { + bestCandidate = null; + ambig_candidate = entry; + continue; + } + + bestCandidate = ambig_candidate; + return entry; + } + } + + if (container.IsInterface || ambig_candidate != null) + break; + + container = container.BaseType; + } while (container != null); + + return ambig_candidate; + } + + // + // Returns inflated version of MemberSpec, it works similarly to + // SRE TypeBuilder.GetMethod + // + public static T GetMember (TypeSpec container, T spec) where T : MemberSpec + { + IList applicable; + if (container.MemberCache.member_hash.TryGetValue (GetLookupName (spec), out applicable)) { + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable[i]; + if (entry.MemberDefinition == spec.MemberDefinition) + return (T) entry; + } + } + + throw new InternalErrorException ("Missing member `{0}' on inflated type `{1}'", + spec.GetSignatureForError (), container.GetSignatureForError ()); + } + + static MemberKind GetMemberCoreKind (MemberCore member) + { + if (member is FieldBase) + return MemberKind.Field; + if (member is Indexer) + return MemberKind.Indexer; + if (member is Class) + return MemberKind.Class; + if (member is Struct) + return MemberKind.Struct; + if (member is Destructor) + return MemberKind.Destructor; + if (member is Method) + return MemberKind.Method; + if (member is Property) + return MemberKind.Property; + if (member is EventField) + return MemberKind.Event; + if (member is Interface) + return MemberKind.Interface; + if (member is EventProperty) + return MemberKind.Event; + if (member is Delegate) + return MemberKind.Delegate; + if (member is Enum) + return MemberKind.Enum; + + throw new NotImplementedException (member.GetType ().ToString ()); + } + + public static IList GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name) + { + var matches = new List (); + foreach (var entry in container.MemberCache.member_hash) { + foreach (var name_entry in entry.Value) { + if (name_entry.IsAccessor) + continue; + + if ((name_entry.Kind & (MemberKind.Constructor | MemberKind.Destructor | MemberKind.Operator)) != 0) + continue; + + if (!name_entry.IsAccessible (ctx)) + continue; + + if (name == null || name_entry.Name.StartsWith (name)) { + matches.Add (name_entry); + } + } + } + + return matches; + } + + // + // Returns members of @iface only, base members are ignored + // + public static List GetInterfaceMethods (TypeSpec iface) + { + // + // MemberCache flatten interfaces, therefore in cases like this one + // + // interface IA : IB {} + // interface IB { void Foo () } + // + // we would return Foo inside IA which is not expected in this case + // + var methods = new List (); + foreach (var entry in iface.MemberCache.member_hash.Values) { + foreach (var name_entry in entry) { + if (iface == name_entry.DeclaringType) { + if (name_entry.Kind == MemberKind.Method) { + methods.Add ((MethodSpec) name_entry); + } + } + } + } + + return methods; + } + + // + // Returns all not implememted abstract members inside abstract type + // NOTE: Returned list is shared and must not be modified + // + public static IList GetNotImplementedAbstractMethods (TypeSpec type) + { + if (type.MemberCache.missing_abstract != null) + return type.MemberCache.missing_abstract; + + var abstract_methods = new List (); + List hierarchy = null; + + // + // Stage 1: top-to-bottom scan for abstract members + // + var abstract_type = type; + while (true) { + foreach (var entry in abstract_type.MemberCache.member_hash) { + foreach (var name_entry in entry.Value) { + if ((name_entry.Modifiers & Modifiers.ABSTRACT) == 0) + continue; + + if (name_entry.Kind != MemberKind.Method) + continue; + + abstract_methods.Add ((MethodSpec) name_entry); + } + } + + var base_type = abstract_type.BaseType; + if (!base_type.IsAbstract) + break; + + if (hierarchy == null) + hierarchy = new List (); + + hierarchy.Add (abstract_type); + abstract_type = base_type; + } + + int not_implemented_count = abstract_methods.Count; + if (not_implemented_count == 0 || hierarchy == null) { + type.MemberCache.missing_abstract = abstract_methods; + return type.MemberCache.missing_abstract; + } + + // + // Stage 2: Remove already implemented methods + // + foreach (var type_up in hierarchy) { + var members = type_up.MemberCache.member_hash; + if (members.Count == 0) + continue; + + for (int i = 0; i < abstract_methods.Count; ++i) { + var candidate = abstract_methods [i]; + if (candidate == null) + continue; + + IList applicable; + if (!members.TryGetValue (candidate.Name, out applicable)) + continue; + + var filter = new MemberFilter (candidate); + foreach (var item in applicable) { + if ((item.Modifiers & (Modifiers.OVERRIDE | Modifiers.VIRTUAL)) == 0) + continue; + + if (filter.Equals (item)) { + --not_implemented_count; + abstract_methods [i] = null; + break; + } + } + } + } + + if (not_implemented_count == abstract_methods.Count) { + type.MemberCache.missing_abstract = abstract_methods; + return type.MemberCache.missing_abstract; + } + + var not_implemented = new MethodSpec[not_implemented_count]; + int counter = 0; + foreach (var m in abstract_methods) { + if (m == null) + continue; + + not_implemented[counter++] = m; + } + + type.MemberCache.missing_abstract = not_implemented; + return type.MemberCache.missing_abstract; + } + + static string GetLookupName (MemberSpec ms) + { + if (ms.Kind == MemberKind.Indexer) + return IndexerNameAlias; + + if (ms.Kind == MemberKind.Constructor) { + if (ms.IsStatic) + return Constructor.TypeConstructorName; + + return Constructor.ConstructorName; + } + + return ms.Name; + } + + static string GetLookupName (MemberCore mc) + { + if (mc is Indexer) + return IndexerNameAlias; + + if (mc is Constructor) + return Constructor.ConstructorName; + + return mc.MemberName.Name; + } + + // + // Returns all operators declared on container and its base types (until declaredOnly is used) + // + public static IList GetUserOperator (TypeSpec container, Operator.OpType op, bool declaredOnly) + { + IList found = null; + + IList applicable; + do { + var mc = container.MemberCache; + + if (((op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) && (mc.state & StateFlags.HasConversionOperator) != 0) || + (mc.state & StateFlags.HasUserOperator) != 0) { + + if (mc.member_hash.TryGetValue (Operator.GetMetadataName (op), out applicable)) { + int i; + for (i = 0; i < applicable.Count; ++i) { + if (applicable[i].Kind != MemberKind.Operator) { + break; + } + } + + // + // Handles very rare case where a method with same name as operator (op_xxxx) exists + // and we have to resize the applicable list + // + if (i != applicable.Count) { + for (i = 0; i < applicable.Count; ++i) { + if (applicable[i].Kind != MemberKind.Operator) { + continue; + } + + if (found == null) { + found = new List (); + found.Add (applicable[i]); + } else { + var prev = found as List; + if (prev == null) { + prev = new List (found.Count + 1); + prev.AddRange (found); + } + + prev.Add (applicable[i]); + } + } + } else { + if (found == null) { + found = applicable; + } else { + var merged = found as List; + if (merged == null) { + merged = new List (found.Count + applicable.Count); + merged.AddRange (found); + found = merged; + } + + merged.AddRange (applicable); + } + } + } + } + + // BaseType call can be expensive + if (declaredOnly) + break; + + container = container.BaseType; + } while (container != null); + + return found; + } + + // + // Inflates all member cache nested types + // + public void InflateTypes (MemberCache inflated_cache, TypeParameterInflator inflator) + { + foreach (var item in member_hash) { + IList inflated_members = null; + for (int i = 0; i < item.Value.Count; ++i ) { + var member = item.Value[i]; + + // FIXME: When inflating members refering nested types before they are inflated + if (member == null) + continue; + + if ((member.Kind & MemberKind.NestedMask) != 0 && + (member.Modifiers & Modifiers.COMPILER_GENERATED) == 0) { + if (inflated_members == null) { + inflated_members = new MemberSpec[item.Value.Count]; + inflated_cache.member_hash.Add (item.Key, inflated_members); + } + + inflated_members [i] = member.InflateMember (inflator); + } + } + } + } + + // + // Inflates all open type members, requires InflateTypes to be called before + // + public void InflateMembers (MemberCache cacheToInflate, TypeSpec inflatedType, TypeParameterInflator inflator) + { + var inflated_member_hash = cacheToInflate.member_hash; + Dictionary accessor_relation = null; + List accessor_members = null; + + // Copy member specific flags when all members were added + cacheToInflate.state = state; + + foreach (var item in member_hash) { + var members = item.Value; + IList inflated_members = null; + for (int i = 0; i < members.Count; ++i ) { + var member = members[i]; + + // + // All nested types have been inflated earlier except for + // compiler types which are created later and could miss InflateTypes + // + if ((member.Kind & MemberKind.NestedMask) != 0 && + (member.Modifiers & Modifiers.COMPILER_GENERATED) == 0) { + if (inflated_members == null) + inflated_members = inflated_member_hash[item.Key]; + + continue; + } + + // + // Clone the container first + // + if (inflated_members == null) { + inflated_members = new MemberSpec [item.Value.Count]; + inflated_member_hash.Add (item.Key, inflated_members); + } + + var local_inflator = inflator; + + if (member.DeclaringType != inflatedType) { + // + // Don't inflate top-level non-generic interface members + // merged into generic interface + // + if (!member.DeclaringType.IsGeneric && !member.DeclaringType.IsNested) { + inflated_members [i] = member; + continue; + } + + // + // Needed when inflating flatten interfaces. It inflates + // container type only, type parameters are already done + // + // Handles cases like: + // + // interface I {} + // interface I : I {} + // + // class C: I {} + // + var inflated_parent = inflator.Inflate (member.DeclaringType); + if (inflated_parent != inflator.TypeInstance) + local_inflator = new TypeParameterInflator (inflator, inflated_parent); + } + + // + // Inflate every member, its parent is now different + // + var inflated = member.InflateMember (local_inflator); + inflated_members [i] = inflated; + + if (member is PropertySpec || member is EventSpec) { + if (accessor_members == null) + accessor_members = new List (); + + accessor_members.Add (inflated); + continue; + } + + if (member.IsAccessor) { + if (accessor_relation == null) + accessor_relation = new Dictionary (); + accessor_relation.Add (member, (MethodSpec) inflated); + } + } + } + + if (accessor_members != null) { + foreach (var member in accessor_members) { + var prop = member as PropertySpec; + if (prop != null) { + if (prop.Get != null) + prop.Get = accessor_relation[prop.Get]; + if (prop.Set != null) + prop.Set = accessor_relation[prop.Set]; + + continue; + } + + var ev = (EventSpec) member; + ev.AccessorAdd = accessor_relation[ev.AccessorAdd]; + ev.AccessorRemove = accessor_relation[ev.AccessorRemove]; + } + } + } + + // + // Removes hidden base members of an interface. For compiled interfaces we cannot + // do name filtering during Add (as we do for import) because we need all base + // names to be valid during type definition. + // Add replaces hidden base member with current one which means any name collision + // (CS0108) of non-first name would be unnoticed because the name was replaced + // with the one from compiled type + // + public void RemoveHiddenMembers (TypeSpec container) + { + foreach (var entry in member_hash) { + var values = entry.Value; + + int container_members_start_at = 0; + while (values[container_members_start_at].DeclaringType != container && ++container_members_start_at < entry.Value.Count); + + if (container_members_start_at == 0 || container_members_start_at == values.Count) + continue; + + for (int i = 0; i < container_members_start_at; ++i) { + var member = values[i]; + + if (!container.ImplementsInterface (member.DeclaringType, false)) + continue; + + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters; + + for (int ii = container_members_start_at; ii < values.Count; ++ii) { + var container_entry = values[ii]; + + if (container_entry.Arity != member.Arity) + continue; + + if (container_entry is IParametersMember) { + if (!TypeSpecComparer.Override.IsEqual (((IParametersMember) container_entry).Parameters, member_param)) + continue; + } + + values.RemoveAt (i); + --container_members_start_at; + --ii; + --i; + } + } + } + } + + // + // Checks all appropriate container members for CLS compliance + // + public void VerifyClsCompliance (TypeSpec container, Report report) + { + if (locase_members != null) + return; + + if (container.BaseType == null) { + locase_members = new Dictionary (member_hash.Count); // StringComparer.OrdinalIgnoreCase); + } else { + container.BaseType.MemberCache.VerifyClsCompliance (container.BaseType, report); + locase_members = new Dictionary (container.BaseType.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase); + } + + var is_imported_type = container.MemberDefinition.IsImported; + foreach (var entry in container.MemberCache.member_hash) { + for (int i = 0; i < entry.Value.Count; ++i ) { + var name_entry = entry.Value[i]; + if ((name_entry.Modifiers & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + continue; + + if ((name_entry.Modifiers & (Modifiers.OVERRIDE | Modifiers.COMPILER_GENERATED)) != 0) + continue; + + if ((name_entry.Kind & MemberKind.MaskType) == 0) + continue; + + if (name_entry.MemberDefinition.CLSAttributeValue == false) + continue; + + IParametersMember p_a = name_entry as IParametersMember; + if (p_a != null && !name_entry.IsAccessor) { + if (!is_imported_type) { + var p_a_pd = p_a.Parameters; + for (int ii = i + 1; ii < entry.Value.Count; ++ii) { + var checked_entry = entry.Value[ii]; + IParametersMember p_b = checked_entry as IParametersMember; + if (p_b == null) + continue; + + if (p_a_pd.Count != p_b.Parameters.Count) + continue; + + if (checked_entry.IsAccessor) + continue; + + var res = ParametersCompiled.IsSameClsSignature (p_a.Parameters, p_b.Parameters); + if (res != 0) { + var last = GetLaterDefinedMember (checked_entry, name_entry); + if (last == checked_entry.MemberDefinition) { + report.SymbolRelatedToPreviousError (name_entry); + } else { + report.SymbolRelatedToPreviousError (checked_entry); + } + + if ((res & 1) != 0) { + report.Warning (3006, 1, last.Location, + "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", + name_entry.GetSignatureForError ()); + } + + if ((res & 2) != 0) { + report.Warning (3007, 1, last.Location, + "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", + name_entry.GetSignatureForError ()); + } + } + } + } + } + + if (i > 0 || name_entry.Kind == MemberKind.Constructor || name_entry.Kind == MemberKind.Indexer) + continue; + + var name_entry_locase = name_entry.Name.ToLowerInvariant (); + + MemberSpec[] found; + if (!locase_members.TryGetValue (name_entry_locase, out found)) { + found = new MemberSpec[] { name_entry }; + locase_members.Add (name_entry_locase, found); + } else { + bool same_names_only = true; + foreach (var f in found) { + if (f.Name == name_entry.Name) + continue; + +// if (f.IsAccessor && name_entry.IsAccessor) +// continue; + + same_names_only = false; + if (!is_imported_type) { + var last = GetLaterDefinedMember (f, name_entry); + if (last == f.MemberDefinition) { + report.SymbolRelatedToPreviousError (name_entry); + } else { + report.SymbolRelatedToPreviousError (f); + } + + report.Warning (3005, 1, last.Location, + "Identifier `{0}' differing only in case is not CLS-compliant", last.GetSignatureForError ()); + } + } + + if (!same_names_only) { + Array.Resize (ref found, found.Length + 1); + found[found.Length - 1] = name_entry; + locase_members[name_entry_locase] = found; + } + } + } + } + } + + // + // Local report helper to issue correctly ordered members stored in hashtable + // + static MemberCore GetLaterDefinedMember (MemberSpec a, MemberSpec b) + { + var mc_a = a.MemberDefinition as MemberCore; + var mc_b = b.MemberDefinition as MemberCore; + if (mc_a == null) + return mc_b; + + if (mc_b == null) + return mc_a; + + if (mc_a.Location.File != mc_a.Location.File) + return mc_b; + + return mc_b.Location.Row > mc_a.Location.Row ? mc_b : mc_a; + } + + public bool CheckExistingMembersOverloads (MemberCore member, AParametersCollection parameters) + { + var name = GetLookupName (member); + var imb = member as InterfaceMemberBase; + if (imb != null && imb.IsExplicitImpl) { + name = imb.GetFullName (name); + } + + return CheckExistingMembersOverloads (member, name, parameters); + } + + public bool CheckExistingMembersOverloads (MemberCore member, string name, AParametersCollection parameters) + { + IList entries; + if (!member_hash.TryGetValue (name, out entries)) + return false; + + var Report = member.Compiler.Report; + + int method_param_count = parameters.Count; + for (int i = entries.Count - 1; i >= 0; --i) { + var ce = entries[i]; + var pm = ce as IParametersMember; + var pd = pm == null ? ParametersCompiled.EmptyReadOnlyParameters : pm.Parameters; + if (pd.Count != method_param_count) + continue; + + if (ce.Arity != member.MemberName.Arity) + continue; + + // Ignore merged interface members + if (member.Parent.PartialContainer != ce.DeclaringType.MemberDefinition) + continue; + + var p_types = pd.Types; + if (method_param_count > 0) { + int ii = method_param_count - 1; + TypeSpec type_a, type_b; + do { + type_a = parameters.Types [ii]; + type_b = p_types [ii]; + + if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) != + (parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF)) + break; + + } while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0); + + if (ii >= 0) + continue; + + // + // Operators can differ in return type only + // + if (member is Operator && ce.Kind == MemberKind.Operator && ((MethodSpec) ce).ReturnType != ((Operator) member).ReturnType) + continue; + + // + // Report difference in parameter modifiers only + // + if (pd != null && member is MethodCore) { + ii = method_param_count; + while (ii-- != 0 && parameters.FixedParameters[ii].ModFlags == pd.FixedParameters[ii].ModFlags && + parameters.ExtensionMethodType == pd.ExtensionMethodType) ; + + if (ii >= 0) { + var mc = ce as MethodSpec; + member.Compiler.Report.SymbolRelatedToPreviousError (ce); + if ((member.ModFlags & Modifiers.PARTIAL) != 0 && (mc.Modifiers & Modifiers.PARTIAL) != 0) { + if (parameters.HasParams || pd.HasParams) { + Report.Error (758, member.Location, + "A partial method declaration and partial method implementation cannot differ on use of `params' modifier"); + } else { + Report.Error (755, member.Location, + "A partial method declaration and partial method implementation must be both an extension method or neither"); + } + } else if (member is Constructor) { + Report.Error (851, member.Location, + "Overloaded contructor `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } else { + Report.Error (663, member.Location, + "Overloaded method `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } + return false; + } + } + } + + if ((ce.Kind & MemberKind.Method) != 0) { + Method method_a = member as Method; + Method method_b = ce.MemberDefinition as Method; + if (method_a != null && method_b != null && (method_a.ModFlags & method_b.ModFlags & Modifiers.PARTIAL) != 0) { + const Modifiers partial_modifiers = Modifiers.STATIC | Modifiers.UNSAFE; + if (method_a.IsPartialDefinition == method_b.IsPartialImplementation) { + if ((method_a.ModFlags & partial_modifiers) == (method_b.ModFlags & partial_modifiers) || + method_a.Parent.IsUnsafe && method_b.Parent.IsUnsafe) { + if (method_a.IsPartialImplementation) { + method_a.SetPartialDefinition (method_b); + if (entries.Count == 1) + member_hash.Remove (name); + else + entries.RemoveAt (i); + } else { + method_b.SetPartialDefinition (method_a); + method_a.caching_flags |= MemberCore.Flags.PartialDefinitionExists; + } + continue; + } + + if (method_a.IsStatic != method_b.IsStatic) { + Report.SymbolRelatedToPreviousError (ce); + Report.Error (763, member.Location, + "A partial method declaration and partial method implementation must be both `static' or neither"); + } + + Report.SymbolRelatedToPreviousError (ce); + Report.Error (764, member.Location, + "A partial method declaration and partial method implementation must be both `unsafe' or neither"); + return false; + } + + Report.SymbolRelatedToPreviousError (ce); + if (method_a.IsPartialDefinition) { + Report.Error (756, member.Location, "A partial method `{0}' declaration is already defined", + member.GetSignatureForError ()); + } + + Report.Error (757, member.Location, "A partial method `{0}' implementation is already defined", + member.GetSignatureForError ()); + return false; + } + + Report.SymbolRelatedToPreviousError (ce); + + bool is_reserved_a = member is AbstractPropertyEventMethod || member is Operator; + bool is_reserved_b = ((MethodSpec) ce).IsReservedMethod; + + if (is_reserved_a || is_reserved_b) { + Report.Error (82, member.Location, "A member `{0}' is already reserved", + is_reserved_a ? + ce.GetSignatureForError () : + member.GetSignatureForError ()); + return false; + } + } else { + Report.SymbolRelatedToPreviousError (ce); + } + + if (member is Operator && ce.Kind == MemberKind.Operator) { + Report.Error (557, member.Location, "Duplicate user-defined conversion in type `{0}'", + member.Parent.GetSignatureForError ()); + return false; + } + + Report.Error (111, member.Location, + "A member `{0}' is already defined. Rename this member or use different parameter types", + member.GetSignatureForError ()); + return false; + } + + return true; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs index c43ab18efd..75998515ac 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs @@ -11,10 +11,2337 @@ // Copyright 2004-2008 Novell, Inc // -// This newNRefactory version does not include a parser, so I included only the required parts of mcs - that is, only the Operator.OpType stuff. +using System; +using System.Collections.Generic; +using System.Security; +using System.Security.Permissions; +using System.Text; +using System.Linq; + +#if NET_2_1 +using XmlElement = System.Object; +#else +using System.Xml; +#endif + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using SecurityType = System.Collections.Generic.List; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +using Mono.CompilerServices.SymbolWriter; namespace Mono.CSharp { - static class Operator { + + public abstract class MethodCore : InterfaceMemberBase, IParametersMember + { + protected ParametersCompiled parameters; + protected ToplevelBlock block; + protected MethodSpec spec; + + public MethodCore (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs, ParametersCompiled parameters) + : base (parent, generic, type, mod, allowed_mod, name, attrs) + { + this.parameters = parameters; + } + + public override Variance ExpectedMemberTypeVariance { + get { + return Variance.Covariant; + } + } + + // + // Returns the System.Type array for the parameters of this method + // + public TypeSpec [] ParameterTypes { + get { + return parameters.Types; + } + } + + public ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + AParametersCollection IParametersMember.Parameters { + get { return parameters; } + } + + public ToplevelBlock Block { + get { + return block; + } + + set { + block = value; + } + } + + public CallingConventions CallingConventions { + get { + CallingConventions cc = parameters.CallingConvention; + if (!IsInterface) + if ((ModFlags & Modifiers.STATIC) == 0) + cc |= CallingConventions.HasThis; + + // FIXME: How is `ExplicitThis' used in C#? + + return cc; + } + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + bool res = base.CheckOverrideAgainstBase (base_member); + + // + // Check that the permissions are not being changed + // + if (!CheckAccessModifiers (this, base_member)) { + Error_CannotChangeAccessModifiers (this, base_member); + res = false; + } + + return res; + } + + protected override bool CheckBase () + { + // Check whether arguments were correct. + if (!DefineParameters (parameters)) + return false; + + return base.CheckBase (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader + { + get { return "M:"; } + } + + public override void Emit () + { + if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + parameters.CheckConstraints (this); + } + + base.Emit (); + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is MethodCore) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + if (overload is AbstractPropertyEventMethod) + return true; + + return base.EnableOverloadChecks (overload); + } + + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (MemberName.Arity > 0) + s += "``" + MemberName.Arity.ToString (); + + return s + parameters.GetSignatureForDocumentation (); + } + + public MethodSpec Spec { + get { return spec; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (parameters.HasArglist) { + Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant"); + } + + if (member_type != null && !member_type.IsCLSCompliant ()) { + Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + + parameters.VerifyClsCompliance (this); + return true; + } + } + + public interface IGenericMethodDefinition : IMemberDefinition + { + TypeParameterSpec[] TypeParameters { get; } + int TypeParametersCount { get; } + +// MethodInfo MakeGenericMethod (TypeSpec[] targs); + } + + public sealed class MethodSpec : MemberSpec, IParametersMember + { + MethodBase metaInfo, inflatedMetaInfo; + AParametersCollection parameters; + TypeSpec returnType; + + TypeSpec[] targs; + TypeParameterSpec[] constraints; + + public MethodSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition details, TypeSpec returnType, + MethodBase info, AParametersCollection parameters, Modifiers modifiers) + : base (kind, declaringType, details, modifiers) + { + this.metaInfo = info; + this.parameters = parameters; + this.returnType = returnType; + } + + #region Properties + + public override int Arity { + get { + return IsGeneric ? GenericDefinition.TypeParametersCount : 0; + } + } + + public TypeParameterSpec[] Constraints { + get { + if (constraints == null && IsGeneric) + constraints = GenericDefinition.TypeParameters; + + return constraints; + } + } + + public bool IsConstructor { + get { + return Kind == MemberKind.Constructor; + } + } + + public IGenericMethodDefinition GenericDefinition { + get { + return (IGenericMethodDefinition) definition; + } + } + + public bool IsExtensionMethod { + get { + return IsStatic && parameters.HasExtensionMethodType; + } + } + + public bool IsSealed { + get { + return (Modifiers & Modifiers.SEALED) != 0; + } + } + + // When is virtual or abstract + public bool IsVirtual { + get { + return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0; + } + } + + public bool IsReservedMethod { + get { + return Kind == MemberKind.Operator || IsAccessor; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return returnType; + } + } + + public AParametersCollection Parameters { + get { + return parameters; + } + } + + public TypeSpec ReturnType { + get { + return returnType; + } + } + + public TypeSpec[] TypeArguments { + get { + return targs; + } + } + + #endregion + + public MethodSpec GetGenericMethodDefinition () + { + if (!IsGeneric && !DeclaringType.IsGeneric) + return this; + + return MemberCache.GetMember (declaringType, this); + } + + public MethodBase GetMetaInfo () + { + // + // inflatedMetaInfo is extra field needed for cases where we + // inflate method but another nested type can later inflate + // again (the cache would be build with inflated metaInfo) and + // TypeBuilder can work with method definitions only + // + if (inflatedMetaInfo == null) { + if ((state & StateFlags.PendingMetaInflate) != 0) { + var dt_meta = DeclaringType.GetMetaInfo (); + + if (DeclaringType.IsTypeBuilder) { + if (IsConstructor) + inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) metaInfo); + else + inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) metaInfo); + } else { +#if STATIC + // it should not be reached + throw new NotImplementedException (); +#else + inflatedMetaInfo = MethodInfo.GetMethodFromHandle (metaInfo.MethodHandle, dt_meta.TypeHandle); +#endif + } + + state &= ~StateFlags.PendingMetaInflate; + } else { + inflatedMetaInfo = metaInfo; + } + } + + if ((state & StateFlags.PendingMakeMethod) != 0) { + var sre_targs = new MetaType[targs.Length]; + for (int i = 0; i < sre_targs.Length; ++i) + sre_targs[i] = targs[i].GetMetaInfo (); + + inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs); + state &= ~StateFlags.PendingMakeMethod; + } + + return inflatedMetaInfo; + } + + public override string GetSignatureForDocumentation () + { + string name; + switch (Kind) { + case MemberKind.Constructor: + name = "#ctor"; + break; + case MemberKind.Method: + if (Arity > 0) + name = Name + "``" + Arity.ToString (); + else + name = Name; + + break; + default: + name = Name; + break; + } + + name = DeclaringType.GetSignatureForDocumentation () + "." + name + parameters.GetSignatureForDocumentation (); + if (Kind == MemberKind.Operator) { + var op = Operator.GetType (Name).Value; + if (op == Operator.OpType.Explicit || op == Operator.OpType.Implicit) { + name += "~" + ReturnType.GetSignatureForDocumentation (); + } + } + + return name; + } + + public override string GetSignatureForError () + { + string name; + if (IsConstructor) { + name = DeclaringType.GetSignatureForError () + "." + DeclaringType.Name; + } else if (Kind == MemberKind.Operator) { + var op = Operator.GetType (Name).Value; + if (op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) { + name = DeclaringType.GetSignatureForError () + "." + Operator.GetName (op) + " operator " + returnType.GetSignatureForError (); + } else { + name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op); + } + } else if (IsAccessor) { + int split = Name.IndexOf ('_'); + name = Name.Substring (split + 1); + var postfix = Name.Substring (0, split); + if (split == 3) { + var pc = parameters.Count; + if (pc > 0 && postfix == "get") { + name = "this" + parameters.GetSignatureForError ("[", "]", pc); + } else if (pc > 1 && postfix == "set") { + name = "this" + parameters.GetSignatureForError ("[", "]", pc - 1); + } + } + + return DeclaringType.GetSignatureForError () + "." + name + "." + postfix; + } else { + name = base.GetSignatureForError (); + if (targs != null) + name += "<" + TypeManager.CSharpName (targs) + ">"; + else if (IsGeneric) + name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">"; + } + + return name + parameters.GetSignatureForError (); + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var ms = (MethodSpec) base.InflateMember (inflator); + ms.inflatedMetaInfo = null; + ms.returnType = inflator.Inflate (returnType); + ms.parameters = parameters.Inflate (inflator); + if (IsGeneric) + ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints); + + return ms; + } + + public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs) + { + if (targs == null) + throw new ArgumentNullException (); +// TODO MemberCache +// if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance)) +// return ginstance; + + //if (generic_intances == null) + // generic_intances = new Dictionary (TypeSpecArrayComparer.Default); + + var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs); + + var inflated = (MethodSpec) MemberwiseClone (); + inflated.declaringType = inflator.TypeInstance; + inflated.returnType = inflator.Inflate (returnType); + inflated.parameters = parameters.Inflate (inflator); + inflated.targs = targs; + inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters); + inflated.state |= StateFlags.PendingMakeMethod; + + // if (inflated.parent == null) + // inflated.parent = parent; + + //generic_intances.Add (targs, inflated); + return inflated; + } + + public MethodSpec Mutate (TypeParameterMutator mutator) + { + var targs = TypeArguments; + if (targs != null) + targs = mutator.Mutate (targs); + + var decl = DeclaringType; + if (DeclaringType.IsGenericOrParentIsGeneric) { + decl = mutator.Mutate (decl); + } + + if (targs == TypeArguments && decl == DeclaringType) + return this; + + var ms = (MethodSpec) MemberwiseClone (); + if (decl != DeclaringType) { + ms.inflatedMetaInfo = null; + ms.declaringType = decl; + ms.state |= StateFlags.PendingMetaInflate; + } + + if (targs != null) { + ms.targs = targs; + ms.state |= StateFlags.PendingMakeMethod; + } + + return ms; + } + + public override List ResolveMissingDependencies () + { + var missing = returnType.ResolveMissingDependencies (); + foreach (var pt in parameters.Types) { + var m = pt.GetMissingDependencies (); + if (m == null) + continue; + + if (missing == null) + missing = new List (); + + missing.AddRange (m); + } + + return missing; + } + + public void SetMetaInfo (MethodInfo info) + { + if (this.metaInfo != null) + throw new InternalErrorException ("MetaInfo reset"); + + this.metaInfo = info; + } + } + + public abstract class MethodOrOperator : MethodCore, IMethodData + { + public MethodBuilder MethodBuilder; + ReturnParameter return_attributes; + SecurityType declarative_security; + protected MethodData MethodData; + + static readonly string[] attribute_targets = new string [] { "method", "return" }; + + protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod, + Modifiers allowed_mod, MemberName name, + Attributes attrs, ParametersCompiled parameters) + : base (parent, generic, type, mod, allowed_mod, name, + attrs, parameters) + { + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); + } + + if (a.Type == pa.DllImport) { + const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC; + if ((ModFlags & extern_static) != extern_static) { + Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'"); + } + is_external_implementation = true; + } + + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (MethodBuilder != null) + MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + protected override bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + } + + public virtual EmitContext CreateEmitContext (ILGenerator ig) + { + return new EmitContext (this, ig, MemberType); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!CheckBase ()) + return false; + + MemberKind kind; + if (this is Operator) + kind = MemberKind.Operator; + else if (this is Destructor) + kind = MemberKind.Destructor; + else + kind = MemberKind.Method; + + if (IsPartialDefinition) { + caching_flags &= ~Flags.Excluded_Undetected; + caching_flags |= Flags.Excluded; + + // Add to member cache only when a partial method implementation has not been found yet + if ((caching_flags & Flags.PartialDefinitionExists) == 0) { +// MethodBase mb = new PartialMethodDefinitionInfo (this); + + spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, null, parameters, ModFlags); + if (MemberName.Arity > 0) { + spec.IsGeneric = true; + + // TODO: Have to move DefineMethod after Define (ideally to Emit) + throw new NotImplementedException ("Generic partial methods"); + } + + Parent.MemberCache.AddMember (spec); + } + + return true; + } + + MethodData = new MethodData ( + this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method); + + if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report)) + return false; + + MethodBuilder = MethodData.MethodBuilder; + + spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, MethodBuilder, parameters, ModFlags); + if (MemberName.Arity > 0) + spec.IsGeneric = true; + + Parent.MemberCache.AddMember (this, MethodBuilder.Name, spec); + + return true; + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + CheckAbstractAndExtern (block != null); + + if ((ModFlags & Modifiers.PARTIAL) != 0) { + for (int i = 0; i < parameters.Count; ++i) { + IParameterData p = parameters.FixedParameters [i]; + if (p.ModFlags == Parameter.Modifier.OUT) { + Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier", + GetSignatureForError ()); + } + + if (p.HasDefaultValue && IsPartialImplementation) + ((Parameter) p).Warning_UselessOptionalParameter (Report); + } + } + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + if (MemberType.IsStatic) { + Error_StaticReturnType (); + } + } + + public override void Emit () + { + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder); + if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder); + + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); + } + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + MethodBuilder.__AddDeclarativeSecurity (de); +#else + MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + if (type_expr != null) + ConstraintChecker.Check (this, member_type, type_expr.Location); + + base.Emit (); + + if (MethodData != null) + MethodData.Emit (Parent); + + Block = null; + MethodData = null; + } + + protected void Error_ConditionalAttributeIsNotValid () + { + Report.Error (577, Location, + "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation", + GetSignatureForError ()); + } + + public bool IsPartialDefinition { + get { + return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null; + } + } + + public bool IsPartialImplementation { + get { + return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #region IMethodData Members + + bool IMethodData.IsAccessor { + get { + return false; + } + } + + public TypeSpec ReturnType { + get { + return MemberType; + } + } + + public MemberName MethodName { + get { + return MemberName; + } + } + + /// + /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded). + /// + public override string[] ConditionalConditions () + { + if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0) + return null; + + if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0) + return new string [0]; + + caching_flags &= ~Flags.Excluded_Undetected; + string[] conditions; + + if (base_method == null) { + if (OptAttributes == null) + return null; + + Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional); + if (attrs == null) + return null; + + conditions = new string[attrs.Length]; + for (int i = 0; i < conditions.Length; ++i) + conditions[i] = attrs[i].GetConditionalAttributeValue (); + } else { + conditions = base_method.MemberDefinition.ConditionalConditions(); + } + + if (conditions != null) + caching_flags |= Flags.Excluded; + + return conditions; + } + + GenericMethod IMethodData.GenericMethod { + get { + return GenericMethod; + } + } + + public virtual void EmitExtraSymbolInfo (SourceMethod source) + { } + + #endregion + + } + + public class SourceMethod : IMethodDef + { + MethodBase method; + SourceMethodBuilder builder; + + protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file) + { + this.method = method; + + builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this); + } + + public string Name { + get { return method.Name; } + } + + public int Token { + get { + MethodToken token; + var mb = method as MethodBuilder; + if (mb != null) + token = mb.GetToken (); + else + token = ((ConstructorBuilder) method).GetToken (); +#if STATIC + if (token.IsPseudoToken) + return ((ModuleBuilder) method.Module).ResolvePseudoToken (token.Token); +#endif + return token.Token; + } + } + + public void CloseMethod () + { + SymbolWriter.CloseMethod (); + } + + public void SetRealMethodName (string name) + { + if (builder != null) + builder.SetRealMethodName (name); + } + + public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block) + { + if (!SymbolWriter.HasSymbolWriter) + return null; + if (block == null) + return null; + + Location start_loc = block.StartLocation; + if (start_loc.IsNull) + return null; + + ICompileUnit compile_unit = start_loc.CompilationUnit; + if (compile_unit == null) + return null; + + return new SourceMethod (parent, method, compile_unit); + } + } + + public class Method : MethodOrOperator, IGenericMethodDefinition + { + Method partialMethodImplementation; + + public Method (DeclSpace parent, GenericMethod generic, + FullNamedExpression return_type, Modifiers mod, + MemberName name, ParametersCompiled parameters, Attributes attrs) + : base (parent, generic, return_type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct | Modifiers.ASYNC : + AllowedModifiersClass | Modifiers.ASYNC, + name, attrs, parameters) + { + } + + protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod, + MemberName name, ParametersCompiled parameters, Attributes attrs) + : base (parent, null, return_type, mod, amod, name, attrs, parameters) + { + } + + #region Properties + + public override TypeParameter[] CurrentTypeParameters { + get { + if (GenericMethod != null) + return GenericMethod.CurrentTypeParameters; + + return null; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + // TODO: Cache this + return CurrentTypeParameters.Select (l => l.Type).ToArray (); + } + } + + public int TypeParametersCount { + get { + return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Length; + } + } + +#endregion + + public override string GetSignatureForError() + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + void Error_DuplicateEntryPoint (Method b) + { + Report.Error (17, b.Location, + "Program `{0}' has more than one entry point defined: `{1}'", + b.Module.Builder.ScopeName, b.GetSignatureForError ()); + } + + bool IsEntryPoint () + { + if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int) + return false; + + if (parameters.IsEmpty) + return true; + + if (parameters.Count > 1) + return false; + + var ac = parameters.Types [0] as ArrayContainer; + return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String && + (parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE; + } + + public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter t = TypeParameter.FindTypeParameter (tp, name); + if (t != null) + return new TypeParameterExpr (t, loc); + } + } + + return base.LookupNamespaceOrType (name, arity, mode, loc); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + if (IsExplicitImpl) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ()); + return; + } + + if (ReturnType.Kind != MemberKind.Void) { + Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ()); + return; + } + + if (IsInterface) { + Report.Error (582, Location, "Conditional not valid on interface members"); + return; + } + + if (MethodData.implementing != null) { + Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType); + Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'", + GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing)); + return; + } + + for (int i = 0; i < parameters.Count; ++i) { + if (parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) { + Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ()); + return; + } + } + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected virtual void DefineTypeParameters () + { + var tparams = CurrentTypeParameters; + + TypeParameterSpec[] base_tparams = null; + TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes; + TypeSpec[] base_targs = TypeSpec.EmptyTypes; + if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) { + if (base_method != null) { + base_tparams = base_method.GenericDefinition.TypeParameters; + + if (base_method.DeclaringType.IsGeneric) { + base_decl_tparams = base_method.DeclaringType.MemberDefinition.TypeParameters; + + var base_type_parent = CurrentType; + while (base_type_parent.BaseType != base_method.DeclaringType) { + base_type_parent = base_type_parent.BaseType; + } + + base_targs = base_type_parent.BaseType.TypeArguments; + } + + if (base_method.IsGeneric) { + ObsoleteAttribute oa; + foreach (var base_tp in base_tparams) { + oa = base_tp.BaseType.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report); + } + + if (base_tp.InterfacesDefined != null) { + foreach (var iface in base_tp.InterfacesDefined) { + oa = iface.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report); + } + } + } + } + + if (base_decl_tparams.Length != 0) { + base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray (); + base_targs = base_targs.Concat (tparams.Select (l => l.Type)).ToArray (); + } else { + base_decl_tparams = base_tparams; + base_targs = tparams.Select (l => l.Type).ToArray (); + } + } + } else if (MethodData.implementing != null) { + base_tparams = MethodData.implementing.GenericDefinition.TypeParameters; + if (MethodData.implementing.DeclaringType.IsGeneric) { + base_decl_tparams = MethodData.implementing.DeclaringType.MemberDefinition.TypeParameters; + foreach (var iface in Parent.CurrentType.Interfaces) { + if (iface == MethodData.implementing.DeclaringType) { + base_targs = iface.TypeArguments; + break; + } + } + } + } + } + + for (int i = 0; i < tparams.Length; ++i) { + var tp = tparams[i]; + + if (!tp.ResolveConstraints (this)) + continue; + + // + // Copy base constraints for override/explicit methods + // + if (base_tparams != null) { + var base_tparam = base_tparams[i]; + var local_tparam = tp.Type; + local_tparam.SpecialConstraint = base_tparam.SpecialConstraint; + + var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs); + base_tparam.InflateConstraints (inflator, local_tparam); + + // + // Check all type argument constraints for possible collision + // introduced by inflating inherited constraints in this context + // + // Conflict example: + // + // class A { virtual void Foo () where U : class, T {} } + // class B : A { override void Foo {} } + // + var local_tparam_targs = local_tparam.TypeArguments; + if (local_tparam_targs != null) { + for (int ii = 0; ii < local_tparam_targs.Length; ++ii) { + var ta = local_tparam_targs [ii]; + if (!ta.IsClass && !ta.IsStruct) + continue; + + if (Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location)) { + local_tparam.ChangeTypeArgumentToBaseType (ii); + } + } + } + + continue; + } + + if (MethodData != null && MethodData.implementing != null) { + var base_tp = MethodData.implementing.Constraints[i]; + if (!tp.Type.HasSameConstraintsImplementation (base_tp)) { + Report.SymbolRelatedToPreviousError (MethodData.implementing); + Report.Error (425, Location, + "The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead", + tp.GetSignatureForError (), GetSignatureForError (), base_tp.GetSignatureForError (), MethodData.implementing.GetSignatureForError ()); + } + } + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + // + // Creates the type + // + public override bool Define () + { + if (!base.Define ()) + return false; + + if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) { + Report.Warning (465, 1, Location, + "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?"); + } + + if (partialMethodImplementation != null && IsPartialDefinition) + MethodBuilder = partialMethodImplementation.MethodBuilder; + + if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) { + Error1599 (Location, ReturnType, Report); + return false; + } + + if (CurrentTypeParameters == null) { + if (base_method != null) { + if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && Name == "Equals") + Parent.PartialContainer.Mark_HasEquals (); + else if (parameters.IsEmpty && Name == "GetHashCode") + Parent.PartialContainer.Mark_HasGetHashCode (); + } + + } else { + DefineTypeParameters (); + } + + if (block != null) { + if (block.IsIterator) { + // + // Current method is turned into automatically generated + // wrapper which creates an instance of iterator + // + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + ModFlags |= Modifiers.DEBUGGER_HIDDEN; + } + + if ((ModFlags & Modifiers.ASYNC) != 0) { + AsyncInitializer.Create (block, parameters, Parent.PartialContainer, ReturnType, Location); + } + } + + if ((ModFlags & Modifiers.STATIC) == 0) + return true; + + if (parameters.HasExtensionMethodType) { + if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) { + if (!Parent.IsTopLevel) + Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class", + GetSignatureForError ()); + + PredefinedAttribute pa = Module.PredefinedAttributes.Extension; + if (!pa.IsDefined) { + Report.Error (1110, Location, + "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter", + GetSignatureForError ()); + } + + ModFlags |= Modifiers.METHOD_EXTENSION; + Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION; + Spec.DeclaringType.SetExtensionMethodContainer (); + Parent.Module.HasExtensionMethod = true; + } else { + Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class", + GetSignatureForError ()); + } + } + + // + // This is used to track the Entry Point, + // + var settings = Compiler.Settings; + if (settings.NeedsEntryPoint && Name == "Main" && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) { + if (IsEntryPoint ()) { + if (Parent.DeclaringAssembly.EntryPoint == null) { + if (Parent.IsGeneric || MemberName.IsGeneric) { + Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type", + GetSignatureForError ()); + } else { + SetIsUsed (); + Parent.DeclaringAssembly.EntryPoint = this; + } + } else { + Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint); + Error_DuplicateEntryPoint (this); + } + } else { + Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point", + GetSignatureForError ()); + } + } + + return true; + } + + // + // Emits the code + // + public override void Emit () + { + try { + if (IsPartialDefinition) { + // + // Use partial method implementation builder for partial method declaration attributes + // + if (partialMethodImplementation != null) { + MethodBuilder = partialMethodImplementation.MethodBuilder; + } + + return; + } + + if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) { + Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration", + GetSignatureForError ()); + } + + if (CurrentTypeParameters != null) { + for (int i = 0; i < CurrentTypeParameters.Length; ++i) { + var tp = CurrentTypeParameters [i]; + tp.CheckGenericConstraints (false); + tp.Emit (); + } + } + + base.Emit (); + + if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0) + Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder); + } catch { + Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}", + Location, MethodBuilder); + throw; + } + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + // TODO: It can be deleted when members will be defined in correct order + if (overload is Operator) + return overload.EnableOverloadChecks (this); + + if (overload is Indexer) + return false; + + return base.EnableOverloadChecks (overload); + } + + public static void Error1599 (Location loc, TypeSpec t, Report Report) + { + Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t)); + } + + protected override bool ResolveMemberType () + { + if (GenericMethod != null) { + MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags); + if (!GenericMethod.Define (this)) + return false; + } + + return base.ResolveMemberType (); + } + + public void SetPartialDefinition (Method methodDefinition) + { + caching_flags |= Flags.PartialDefinitionExists; + methodDefinition.partialMethodImplementation = this; + + // Ensure we are always using method declaration parameters + for (int i = 0; i < methodDefinition.parameters.Count; ++i ) { + parameters [i].Name = methodDefinition.parameters [i].Name; + parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue; + } + + if (methodDefinition.attributes == null) + return; + + if (attributes == null) { + attributes = methodDefinition.attributes; + } else { + attributes.Attrs.AddRange (methodDefinition.attributes.Attrs); + } + } + } + + public abstract class ConstructorInitializer : ExpressionStatement + { + Arguments argument_list; + MethodSpec base_ctor; + + public ConstructorInitializer (Arguments argument_list, Location loc) + { + this.argument_list = argument_list; + this.loc = loc; + } + + public Arguments Arguments { + get { + return argument_list; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + + // FIXME: Hack + var caller_builder = (Constructor) ec.MemberContext; + + // + // Spec mandates that constructor initializer will not have `this' access + // + using (ec.Set (ResolveContext.Options.BaseInitializer)) { + if (argument_list != null) { + bool dynamic; + argument_list.Resolve (ec, out dynamic); + + if (dynamic) { + ec.Report.Error (1975, loc, + "The constructor call cannot be dynamically dispatched within constructor initializer"); + + return null; + } + } + + type = ec.CurrentType; + if (this is ConstructorBaseInitializer) { + if (ec.CurrentType.BaseType == null) + return this; + + type = ec.CurrentType.BaseType; + if (ec.CurrentType.IsStruct) { + ec.Report.Error (522, loc, + "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); + return this; + } + } else { + // + // It is legal to have "this" initializers that take no arguments + // in structs, they are just no-ops. + // + // struct D { public D (int a) : this () {} + // + if (ec.CurrentType.IsStruct && argument_list == null) + return this; + } + + base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); + } + + // TODO MemberCache: Does it work for inflated types ? + if (base_ctor == caller_builder.Spec){ + ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", + caller_builder.GetSignatureForError ()); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + // It can be null for static initializers + if (base_ctor == null) + return; + + ec.Mark (loc); + + Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + } + } + + public class ConstructorBaseInitializer : ConstructorInitializer { + public ConstructorBaseInitializer (Arguments argument_list, Location l) : + base (argument_list, l) + { + } + } + + class GeneratedBaseInitializer: ConstructorBaseInitializer { + public GeneratedBaseInitializer (Location loc): + base (null, loc) + { + } + } + + public class ConstructorThisInitializer : ConstructorInitializer { + public ConstructorThisInitializer (Arguments argument_list, Location l) : + base (argument_list, l) + { + } + } + + public class Constructor : MethodCore, IMethodData { + public ConstructorBuilder ConstructorBuilder; + public ConstructorInitializer Initializer; + SecurityType declarative_security; + bool has_compliant_args; + + // + // Modifiers allowed for a constructor. + // + public const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.STATIC | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.PRIVATE; + + static readonly string[] attribute_targets = new string [] { "method" }; + + public static readonly string ConstructorName = ".ctor"; + public static readonly string TypeConstructorName = ".cctor"; + + // + // The spec claims that static is not permitted, but + // my very own code has static constructors. + // + public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, + ConstructorInitializer init, Location loc) + : base (parent, null, null, mod, AllowedModifiers, + new MemberName (name, loc), attrs, args) + { + Initializer = init; + } + + public bool HasCompliantArgs { + get { return has_compliant_args; } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Constructor; + } + } + + bool IMethodData.IsAccessor { + get { + return false; + } + } + + // + // Returns true if this is a default constructor + // + public bool IsDefault () + { + if ((ModFlags & Modifiers.STATIC) != 0) + return parameters.IsEmpty; + + return parameters.IsEmpty && + (Initializer is ConstructorBaseInitializer) && + (Initializer.Arguments == null); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); + } + + ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + protected override bool CheckBase () + { + if ((ModFlags & Modifiers.STATIC) != 0) { + if (!parameters.IsEmpty) { + Report.Error (132, Location, "`{0}': The static constructor must be parameterless", + GetSignatureForError ()); + return false; + } + + // the rest can be ignored + return true; + } + + // Check whether arguments were correct. + if (!DefineParameters (parameters)) + return false; + + if ((caching_flags & Flags.MethodOverloadsExist) != 0) + Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + + if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) { + Report.Error (568, Location, + "Structs cannot contain explicit parameterless constructors"); + return false; + } + + CheckProtectedModifier (); + + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + // + // Creates the ConstructorBuilder + // + public override bool Define () + { + if (ConstructorBuilder != null) + return true; + + var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName; + + if ((ModFlags & Modifiers.STATIC) != 0) { + ca |= MethodAttributes.Static | MethodAttributes.Private; + } else { + ca |= ModifiersExtensions.MethodAttr (ModFlags); + } + + if (!CheckAbstractAndExtern (block != null)) + return false; + + // Check if arguments were correct. + if (!CheckBase ()) + return false; + + ConstructorBuilder = Parent.TypeBuilder.DefineConstructor ( + ca, CallingConventions, + parameters.GetMetaInfo ()); + + spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, ConstructorBuilder, parameters, ModFlags); + + Parent.MemberCache.AddMember (spec); + + // It's here only to report an error + if (block != null && block.IsIterator) { + member_type = Compiler.BuiltinTypes.Void; + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + } + + return true; + } + + // + // Emits the code + // + public override void Emit () + { + if (Parent.PartialContainer.IsComImport) { + if (!IsDefault ()) { + Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor", + Parent.GetSignatureForError ()); + } + + // Set as internal implementation and reset block data + // to ensure no IL is generated + ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall); + block = null; + } + + if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder); + + if (OptAttributes != null) + OptAttributes.Emit (); + + base.Emit (); + parameters.ApplyAttributes (this, ConstructorBuilder); + + // + // If we use a "this (...)" constructor initializer, then + // do not emit field initializers, they are initialized in the other constructor + // + bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) || + !(Initializer is ConstructorThisInitializer); + + BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void); + bc.Set (ResolveContext.Options.ConstructorScope); + + if (emit_field_initializers) + Parent.PartialContainer.ResolveFieldInitializers (bc); + + if (block != null) { + // If this is a non-static `struct' constructor and doesn't have any + // initializer, it must initialize all of the struct's fields. + if ((Parent.PartialContainer.Kind == MemberKind.Struct) && + ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null)) + block.AddThisVariable (bc, Parent, Location); + + if (block != null && (ModFlags & Modifiers.STATIC) == 0){ + if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null) + Initializer = new GeneratedBaseInitializer (Location); + + if (Initializer != null) { + block.AddScopeStatement (new StatementExpression (Initializer)); + } + } + } + + SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block); + + if (block != null) { + if (block.Resolve (null, bc, this)) { + EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType); + ec.With (EmitContext.Options.ConstructorScope, true); + + if (!ec.HasReturnLabel && bc.HasReturnLabel) { + ec.ReturnLabel = bc.ReturnLabel; + ec.HasReturnLabel = true; + } + + block.Emit (ec); + } + } + + if (source != null) + source.CloseMethod (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + ConstructorBuilder.__AddDeclarativeSecurity (de); +#else + ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + block = null; + } + + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + // Is never override + bestCandidate = null; + return null; + } + + public override string GetSignatureForDocumentation () + { + return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation (); + } + + public override string GetSignatureForError() + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) { + return false; + } + + if (!parameters.IsEmpty && Parent.Definition.IsAttribute) { + foreach (TypeSpec param in parameters.Types) { + if (param.IsArray) { + return true; + } + } + } + + has_compliant_args = true; + return true; + } + + #region IMethodData Members + + public MemberName MethodName { + get { + return MemberName; + } + } + + public TypeSpec ReturnType { + get { + return MemberType; + } + } + + public EmitContext CreateEmitContext (ILGenerator ig) + { + throw new NotImplementedException (); + } + + public bool IsExcluded() + { + return false; + } + + GenericMethod IMethodData.GenericMethod { + get { + return null; + } + } + + void IMethodData.EmitExtraSymbolInfo (SourceMethod source) + { } + + #endregion + } + + /// + /// Interface for MethodData class. Holds links to parent members to avoid member duplication. + /// + public interface IMethodData : IMemberContext + { + CallingConventions CallingConventions { get; } + Location Location { get; } + MemberName MethodName { get; } + TypeSpec ReturnType { get; } + GenericMethod GenericMethod { get; } + ParametersCompiled ParameterInfo { get; } + MethodSpec Spec { get; } + bool IsAccessor { get; } + + Attributes OptAttributes { get; } + ToplevelBlock Block { get; set; } + + EmitContext CreateEmitContext (ILGenerator ig); + void EmitExtraSymbolInfo (SourceMethod source); + } + + // + // Encapsulates most of the Method's state + // + public class MethodData + { +#if !STATIC + static FieldInfo methodbuilder_attrs_field; +#endif + + public readonly IMethodData method; + + public readonly GenericMethod GenericMethod; + + // + // Are we implementing an interface ? + // + public MethodSpec implementing; + + // + // Protected data. + // + protected InterfaceMemberBase member; + protected Modifiers modifiers; + protected MethodAttributes flags; + protected TypeSpec declaring_type; + protected MethodSpec parent_method; + + MethodBuilder builder; + public MethodBuilder MethodBuilder { + get { + return builder; + } + } + + public TypeSpec DeclaringType { + get { + return declaring_type; + } + } + + public MethodData (InterfaceMemberBase member, + Modifiers modifiers, MethodAttributes flags, IMethodData method) + { + this.member = member; + this.modifiers = modifiers; + this.flags = flags; + + this.method = method; + } + + public MethodData (InterfaceMemberBase member, + Modifiers modifiers, MethodAttributes flags, + IMethodData method, MethodBuilder builder, + GenericMethod generic, MethodSpec parent_method) + : this (member, modifiers, flags, method) + { + this.builder = builder; + this.GenericMethod = generic; + this.parent_method = parent_method; + } + + public bool Define (DeclSpace parent, string method_full_name, Report Report) + { + TypeContainer container = parent.PartialContainer; + + PendingImplementation pending = container.PendingImplementations; + MethodSpec ambig_iface_method; + if (pending != null) { + implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method); + + if (member.InterfaceType != null) { + if (implementing == null) { + if (member is PropertyBase) { + Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", + method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), + member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); + + } else { + Report.Error (539, method.Location, + "`{0}.{1}' in explicit interface declaration is not a member of interface", + TypeManager.CSharpName (member.InterfaceType), member.ShortName); + } + return false; + } + if (implementing.IsAccessor && !method.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", + member.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); + return false; + } + } else { + if (implementing != null) { + if (!method.IsAccessor) { + if (implementing.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", + method.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); + } + } else if (implementing.DeclaringType.IsInterface) { + if (!implementing.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", + method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); + } else { + PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod; + if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", + method.GetSignatureForError (), implementing.GetSignatureForError ()); + } + } + } + } + } + } else { + ambig_iface_method = null; + } + + // + // For implicit implementations, make sure we are public, for + // explicit implementations, make sure we are private. + // + if (implementing != null){ + // + // Setting null inside this block will trigger a more + // verbose error reporting for missing interface implementations + // + // The "candidate" function has been flagged already + // but it wont get cleared + // + if (member.IsExplicitImpl){ + if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", + method.GetSignatureForError ()); + } + + if (ambig_iface_method != null) { + Report.SymbolRelatedToPreviousError (ambig_iface_method); + Report.SymbolRelatedToPreviousError (implementing); + Report.Warning (473, 2, method.Location, + "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead", + method.GetSignatureForError ()); + } + + } else { + if (implementing.DeclaringType.IsInterface) { + // + // If this is an interface method implementation, + // check for public accessibility + // + if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) + { + implementing = null; + } + } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){ + // We may never be private. + implementing = null; + + } else if ((modifiers & Modifiers.OVERRIDE) == 0){ + // + // We may be protected if we're overriding something. + // + implementing = null; + } + } + + // + // Static is not allowed + // + if ((modifiers & Modifiers.STATIC) != 0){ + implementing = null; + } + } + + // + // If implementing is still valid, set flags + // + if (implementing != null){ + // + // When implementing interface methods, set NewSlot + // unless, we are overwriting a method. + // + if (implementing.DeclaringType.IsInterface){ + if ((modifiers & Modifiers.OVERRIDE) == 0) + flags |= MethodAttributes.NewSlot; + } + + flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig; + + // Set Final unless we're virtual, abstract or already overriding a method. + if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0) + flags |= MethodAttributes.Final; + + // + // clear the pending implementation flag (requires explicit methods to be defined first) + // + parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName, + member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method); + + // + // Update indexer accessor name to match implementing abstract accessor + // + if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor) + method_full_name = implementing.MemberDefinition.Name; + } + + DefineMethodBuilder (container, method_full_name, method.ParameterInfo); + + if (builder == null) + return false; + +// if (container.CurrentType != null) +// declaring_type = container.CurrentType; +// else + declaring_type = container.Definition; + + if (implementing != null && member.IsExplicitImpl) { + container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ()); + } + + return true; + } + + + /// + /// Create the MethodBuilder for the method + /// + void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param) + { + var return_type = method.ReturnType.GetMetaInfo (); + var p_types = param.GetMetaInfo (); + + if (builder == null) { + builder = container.TypeBuilder.DefineMethod ( + method_name, flags, method.CallingConventions, + return_type, p_types); + return; + } + + // + // Generic method has been already defined to resolve method parameters + // correctly when they use type parameters + // + builder.SetParameters (p_types); + builder.SetReturnType (return_type); + if (builder.Attributes != flags) { +#if STATIC + builder.__SetAttributes (flags); +#else + try { + if (methodbuilder_attrs_field == null) + methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance); + methodbuilder_attrs_field.SetValue (builder, flags); + } catch { + container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes"); + } +#endif + } + } + + // + // Emits the code + // + public void Emit (DeclSpace parent) + { + if (GenericMethod != null) + GenericMethod.EmitAttributes (); + + var mc = (IMemberContext) method; + + method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); + + SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block); + + ToplevelBlock block = method.Block; + if (block != null) { + BlockContext bc = new BlockContext (mc, block, method.ReturnType); + if (block.Resolve (null, bc, method)) { + EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ()); + if (!ec.HasReturnLabel && bc.HasReturnLabel) { + ec.ReturnLabel = bc.ReturnLabel; + ec.HasReturnLabel = true; + } + + block.Emit (ec); + } + } + + if (source != null) { + method.EmitExtraSymbolInfo (source); + source.CloseMethod (); + } + } + } + + public class Destructor : MethodOrOperator + { + const Modifiers AllowedModifiers = + Modifiers.UNSAFE | + Modifiers.EXTERN; + + static readonly string[] attribute_targets = new string [] { "method" }; + + public static readonly string MetadataName = "Finalize"; + + public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l) + : base (parent, null, null, mod, AllowedModifiers, + new MemberName (MetadataName, l), attrs, parameters) + { + ModFlags &= ~Modifiers.PRIVATE; + ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + protected override bool CheckBase () + { + // Don't check base, destructors have special syntax + return true; + } + + public override void Emit() + { + var base_type = Parent.PartialContainer.BaseType; + if (base_type != null && Block != null) { + var base_dtor = MemberCache.FindMember (base_type, + new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec; + + if (base_dtor == null) + throw new NotImplementedException (); + + MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location); + method_expr.InstanceExpression = new BaseThis (base_type, Location); + + var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation); + var finaly_block = new ExplicitBlock (block, Location, Location); + + // + // 0-size arguments to avoid CS0250 error + // TODO: Should use AddScopeStatement or something else which emits correct + // debugger scope + // + finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); + + var tf = new TryFinally (try_block, finaly_block, Location); + block.WrapIntoDestructor (tf, try_block); + } + + base.Emit (); + } + + public override string GetSignatureForError () + { + return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()"; + } + + protected override bool ResolveMemberType () + { + member_type = Compiler.BuiltinTypes.Void; + return true; + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + // Ooouh Martin, templates are missing here. + // When it will be possible move here a lot of child code and template method type. + public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData { + protected MethodData method_data; + protected ToplevelBlock block; + protected SecurityType declarative_security; + + protected readonly string prefix; + + ReturnParameter return_attributes; + + public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc) + : base (member.Parent, SetupName (prefix, member, loc), attrs) + { + this.prefix = prefix; + } + + static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc) + { + return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc); + } + + public void UpdateName (InterfaceMemberBase member) + { + SetMemberName (SetupName (prefix, member, Location)); + } + + #region IMethodData Members + + public ToplevelBlock Block { + get { + return block; + } + + set { + block = value; + } + } + + public CallingConventions CallingConventions { + get { + return CallingConventions.Standard; + } + } + + public EmitContext CreateEmitContext (ILGenerator ig) + { + return new EmitContext (this, ig, ReturnType); + } + + public bool IsAccessor { + get { + return true; + } + } + + public bool IsExcluded () + { + return false; + } + + GenericMethod IMethodData.GenericMethod { + get { + return null; + } + } + + public MemberName MethodName { + get { + return MemberName; + } + } + + public TypeSpec[] ParameterTypes { + get { + return ParameterInfo.Types; + } + } + + public abstract ParametersCompiled ParameterInfo { get ; } + public abstract TypeSpec ReturnType { get; } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) { + Report.Error (1667, a.Location, + "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only", + TypeManager.CSharpName (a.Type), a.GetValidTargets ()); + return; + } + + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Target == AttributeTargets.Method) { + method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + return; + } + + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + ApplyToExtraTarget (a, ctor, cdata, pa); + } + + protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + throw new NotSupportedException ("You forgot to define special attribute target handling"); + } + + // It is not supported for the accessors + public sealed override bool Define() + { + throw new NotSupportedException (); + } + + public virtual void Emit (DeclSpace parent) + { + method_data.Emit (parent); + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder); + if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder); + + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); + } + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + method_data.MethodBuilder.__AddDeclarativeSecurity (de); +#else + method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + block = null; + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is MethodCore) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + // This can only happen with indexers and it will + // be catched as indexer difference + if (overload is AbstractPropertyEventMethod) + return true; + + return false; + } + + public override string GetSignatureForDocumentation () + { + // should not be called + throw new NotSupportedException (); + } + + public override bool IsClsComplianceRequired() + { + return false; + } + + public MethodSpec Spec { get; protected set; } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); } + } + + void IMethodData.EmitExtraSymbolInfo (SourceMethod source) + { } + } + + public class Operator : MethodOrOperator { + + const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.STATIC; public enum OpType : byte { @@ -57,6 +2384,8 @@ namespace Mono.CSharp { TOP }; + public readonly OpType OperatorType; + static readonly string [] [] names; static Operator () @@ -90,6 +2419,186 @@ namespace Mono.CSharp { names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" }; } + public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type, + Modifiers mod_flags, ParametersCompiled parameters, + ToplevelBlock block, Attributes attrs, Location loc) + : base (parent, null, ret_type, mod_flags, AllowedModifiers, + new MemberName (GetMetadataName (type), loc), attrs, parameters) + { + OperatorType = type; + Block = block; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC; + if ((ModFlags & RequiredModifiers) != RequiredModifiers){ + Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ()); + } + + if (!base.Define ()) + return false; + + if (block != null && block.IsIterator) { + // + // Current method is turned into automatically generated + // wrapper which creates an instance of iterator + // + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + ModFlags |= Modifiers.DEBUGGER_HIDDEN; + } + + // imlicit and explicit operator of same types are not allowed + if (OperatorType == OpType.Explicit) + Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters); + else if (OperatorType == OpType.Implicit) + Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters); + + TypeSpec declaring_type = Parent.CurrentType; + TypeSpec return_type = MemberType; + TypeSpec first_arg_type = ParameterTypes [0]; + + TypeSpec first_arg_type_unwrap = first_arg_type; + if (first_arg_type.IsNullableType) + first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type); + + TypeSpec return_type_unwrap = return_type; + if (return_type.IsNullableType) + return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type); + + // + // Rules for conversion operators + // + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) { + Report.Error (555, Location, + "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type"); + return false; + } + + TypeSpec conv_type; + if (declaring_type == return_type || declaring_type == return_type_unwrap) { + conv_type = first_arg_type; + } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) { + conv_type = return_type; + } else { + Report.Error (556, Location, + "User-defined conversion must convert to or from the enclosing type"); + return false; + } + + if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Report.Error (1964, Location, + "User-defined conversion `{0}' cannot convert to or from the dynamic type", + GetSignatureForError ()); + + return false; + } + + if (conv_type.IsInterface) { + Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type", + GetSignatureForError ()); + return false; + } + + if (conv_type.IsClass) { + if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) { + Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class", + GetSignatureForError ()); + return false; + } + + if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) { + Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class", + GetSignatureForError ()); + return false; + } + } + } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) { + if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) { + Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int"); + return false; + } + } else if (parameters.Count == 1) { + // Checks for Unary operators + + if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) { + if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) { + Report.Error (448, Location, + "The return type for ++ or -- operator must be the containing type or derived from the containing type"); + return false; + } + if (first_arg_type != declaring_type) { + Report.Error ( + 559, Location, "The parameter type for ++ or -- operator must be the containing type"); + return false; + } + } + + if (first_arg_type_unwrap != declaring_type) { + Report.Error (562, Location, + "The parameter type of a unary operator must be the containing type"); + return false; + } + + if (OperatorType == OpType.True || OperatorType == OpType.False) { + if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) { + Report.Error ( + 215, Location, + "The return type of operator True or False " + + "must be bool"); + return false; + } + } + + } else if (first_arg_type_unwrap != declaring_type) { + // Checks for Binary operators + + var second_arg_type = ParameterTypes[1]; + if (second_arg_type.IsNullableType) + second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type); + + if (second_arg_type != declaring_type) { + Report.Error (563, Location, + "One of the parameters of a binary operator must be the containing type"); + return false; + } + } + + return true; + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig; + return true; + } + + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + // Operator cannot be override + bestCandidate = null; + return null; + } + public static string GetName (OpType ot) { return names [(int) ot] [0]; @@ -127,6 +2636,56 @@ namespace Mono.CSharp { return null; } + + public OpType GetMatchingOperator () + { + switch (OperatorType) { + case OpType.Equality: + return OpType.Inequality; + case OpType.Inequality: + return OpType.Equality; + case OpType.True: + return OpType.False; + case OpType.False: + return OpType.True; + case OpType.GreaterThan: + return OpType.LessThan; + case OpType.LessThan: + return OpType.GreaterThan; + case OpType.GreaterThanOrEqual: + return OpType.LessThanOrEqual; + case OpType.LessThanOrEqual: + return OpType.GreaterThanOrEqual; + default: + return OpType.TOP; + } + } + + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + s = s + "~" + ReturnType.GetSignatureForDocumentation (); + } + + return s; + } + + public override string GetSignatureForError () + { + StringBuilder sb = new StringBuilder (); + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + sb.AppendFormat ("{0}.{1} operator {2}", + Parent.GetSignatureForError (), GetName (OperatorType), + member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ()); + } + else { + sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType)); + } + + sb.Append (parameters.GetSignatureForError ()); + return sb.ToString (); + } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs new file mode 100644 index 0000000000..3edbed6ba8 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs @@ -0,0 +1,281 @@ +// +// modifiers.cs: Modifiers handling +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2010 Novell, Inc +// + +using System; + +#if STATIC +using IKVM.Reflection; +#else +using System.Reflection; +#endif + +namespace Mono.CSharp +{ + [Flags] + public enum Modifiers + { + PROTECTED = 0x0001, + PUBLIC = 0x0002, + PRIVATE = 0x0004, + INTERNAL = 0x0008, + NEW = 0x0010, + ABSTRACT = 0x0020, + SEALED = 0x0040, + STATIC = 0x0080, + READONLY = 0x0100, + VIRTUAL = 0x0200, + OVERRIDE = 0x0400, + EXTERN = 0x0800, + VOLATILE = 0x1000, + UNSAFE = 0x2000, + ASYNC = 0x4000, + TOP = 0x8000, + + // + // Compiler specific flags + // + PROPERTY_CUSTOM = 0x10000, + + PARTIAL = 0x20000, + DEFAULT_ACCESS_MODIFER = 0x40000, + METHOD_EXTENSION = 0x80000, + COMPILER_GENERATED = 0x100000, + BACKING_FIELD = 0x200000, + DEBUGGER_HIDDEN = 0x400000, + + AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE, + AllowedExplicitImplFlags = UNSAFE | EXTERN, + } + + static class ModifiersExtensions + { + public static string AccessibilityName (Modifiers mod) + { + switch (mod & Modifiers.AccessibilityMask) { + case Modifiers.PUBLIC: + return "public"; + case Modifiers.PROTECTED: + return "protected"; + case Modifiers.PROTECTED | Modifiers.INTERNAL: + return "protected internal"; + case Modifiers.INTERNAL: + return "internal"; + case Modifiers.PRIVATE: + return "private"; + default: + throw new NotImplementedException (mod.ToString ()); + } + } + + static public string Name (Modifiers i) + { + string s = ""; + + switch (i) { + case Modifiers.NEW: + s = "new"; break; + case Modifiers.PUBLIC: + s = "public"; break; + case Modifiers.PROTECTED: + s = "protected"; break; + case Modifiers.INTERNAL: + s = "internal"; break; + case Modifiers.PRIVATE: + s = "private"; break; + case Modifiers.ABSTRACT: + s = "abstract"; break; + case Modifiers.SEALED: + s = "sealed"; break; + case Modifiers.STATIC: + s = "static"; break; + case Modifiers.READONLY: + s = "readonly"; break; + case Modifiers.VIRTUAL: + s = "virtual"; break; + case Modifiers.OVERRIDE: + s = "override"; break; + case Modifiers.EXTERN: + s = "extern"; break; + case Modifiers.VOLATILE: + s = "volatile"; break; + case Modifiers.UNSAFE: + s = "unsafe"; break; + case Modifiers.ASYNC: + s = "async"; break; + } + + return s; + } + + // + // Used by custom property accessors to check whether @modA is more restrictive than @modB + // + public static bool IsRestrictedModifier (Modifiers modA, Modifiers modB) + { + Modifiers flags = 0; + + if ((modB & Modifiers.PUBLIC) != 0) { + flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE; + } else if ((modB & Modifiers.PROTECTED) != 0) { + if ((modB & Modifiers.INTERNAL) != 0) + flags = Modifiers.PROTECTED | Modifiers.INTERNAL; + + flags |= Modifiers.PRIVATE; + } else if ((modB & Modifiers.INTERNAL) != 0) + flags = Modifiers.PRIVATE; + + return modB != modA && (modA & (~flags)) == 0; + } + + public static TypeAttributes TypeAttr (Modifiers mod_flags, bool is_toplevel) + { + TypeAttributes t = 0; + + if (is_toplevel){ + if ((mod_flags & Modifiers.PUBLIC) != 0) + t = TypeAttributes.Public; + else if ((mod_flags & Modifiers.PRIVATE) != 0) + t = TypeAttributes.NotPublic; + } else { + if ((mod_flags & Modifiers.PUBLIC) != 0) + t = TypeAttributes.NestedPublic; + else if ((mod_flags & Modifiers.PRIVATE) != 0) + t = TypeAttributes.NestedPrivate; + else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) + t = TypeAttributes.NestedFamORAssem; + else if ((mod_flags & Modifiers.PROTECTED) != 0) + t = TypeAttributes.NestedFamily; + else if ((mod_flags & Modifiers.INTERNAL) != 0) + t = TypeAttributes.NestedAssembly; + } + + if ((mod_flags & Modifiers.SEALED) != 0) + t |= TypeAttributes.Sealed; + if ((mod_flags & Modifiers.ABSTRACT) != 0) + t |= TypeAttributes.Abstract; + + return t; + } + + public static FieldAttributes FieldAttr (Modifiers mod_flags) + { + FieldAttributes fa = 0; + + if ((mod_flags & Modifiers.PUBLIC) != 0) + fa |= FieldAttributes.Public; + if ((mod_flags & Modifiers.PRIVATE) != 0) + fa |= FieldAttributes.Private; + if ((mod_flags & Modifiers.PROTECTED) != 0) { + if ((mod_flags & Modifiers.INTERNAL) != 0) + fa |= FieldAttributes.FamORAssem; + else + fa |= FieldAttributes.Family; + } else { + if ((mod_flags & Modifiers.INTERNAL) != 0) + fa |= FieldAttributes.Assembly; + } + + if ((mod_flags & Modifiers.STATIC) != 0) + fa |= FieldAttributes.Static; + if ((mod_flags & Modifiers.READONLY) != 0) + fa |= FieldAttributes.InitOnly; + + return fa; + } + + public static MethodAttributes MethodAttr (Modifiers mod_flags) + { + MethodAttributes ma = MethodAttributes.HideBySig; + + switch (mod_flags & Modifiers.AccessibilityMask) { + case Modifiers.PUBLIC: + ma |= MethodAttributes.Public; + break; + case Modifiers.PRIVATE: + ma |= MethodAttributes.Private; + break; + case Modifiers.PROTECTED | Modifiers.INTERNAL: + ma |= MethodAttributes.FamORAssem; + break; + case Modifiers.PROTECTED: + ma |= MethodAttributes.Family; + break; + case Modifiers.INTERNAL: + ma |= MethodAttributes.Assembly; + break; + default: + throw new NotImplementedException (mod_flags.ToString ()); + } + + if ((mod_flags & Modifiers.STATIC) != 0) + ma |= MethodAttributes.Static; + if ((mod_flags & Modifiers.ABSTRACT) != 0) { + ma |= MethodAttributes.Abstract | MethodAttributes.Virtual; + } + if ((mod_flags & Modifiers.SEALED) != 0) + ma |= MethodAttributes.Final; + + if ((mod_flags & Modifiers.VIRTUAL) != 0) + ma |= MethodAttributes.Virtual; + + if ((mod_flags & Modifiers.OVERRIDE) != 0) { + ma |= MethodAttributes.Virtual; + } else { + if ((ma & MethodAttributes.Virtual) != 0) + ma |= MethodAttributes.NewSlot; + } + + return ma; + } + + // + // Checks the object @mod modifiers to be in @allowed. + // Returns the new mask. Side effect: reports any + // incorrect attributes. + // + public static Modifiers Check (Modifiers allowed, Modifiers mod, Modifiers def_access, Location l, Report Report) + { + int invalid_flags = (~(int) allowed) & ((int) mod & ((int) Modifiers.TOP - 1)); + int i; + + if (invalid_flags == 0){ + // + // If no accessibility bits provided + // then provide the defaults. + // + if ((mod & Modifiers.AccessibilityMask) == 0) { + mod |= def_access; + if (def_access != 0) + mod |= Modifiers.DEFAULT_ACCESS_MODIFER; + return mod; + } + + return mod; + } + + for (i = 1; i <= (int) Modifiers.TOP; i <<= 1) { + if ((i & invalid_flags) == 0) + continue; + + Error_InvalidModifier ((Modifiers)i, l, Report); + } + + return allowed & mod; + } + + static void Error_InvalidModifier (Modifiers mod, Location l, Report Report) + { + Report.Error (106, l, "The modifier `{0}' is not valid for this item", + Name (mod)); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs new file mode 100644 index 0000000000..fdafbee39f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs @@ -0,0 +1,1227 @@ +// +// namespace.cs: Tracks namespaces +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.CSharp { + + public class RootNamespace : Namespace { + + readonly string alias_name; + readonly Dictionary all_namespaces; + + public RootNamespace (string alias_name) + : base (null, String.Empty) + { + this.alias_name = alias_name; + + all_namespaces = new Dictionary (); + all_namespaces.Add ("", this); + } + + public string Alias { + get { + return alias_name; + } + } + + public void RegisterNamespace (Namespace child) + { + if (child != this) + all_namespaces.Add (child.Name, child); + } + + public bool IsNamespace (string name) + { + return all_namespaces.ContainsKey (name); + } + + protected void RegisterNamespace (string dotted_name) + { + if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name)) + GetNamespace (dotted_name, true); + } + + public override string GetSignatureForError () + { + return alias_name + "::"; + } + } + + public class GlobalRootNamespace : RootNamespace + { + public GlobalRootNamespace () + : base ("global") + { + } + } + + // + // Namespace cache for imported and compiled namespaces + // + // This is an Expression to allow it to be referenced in the + // compiler parse/intermediate tree during name resolution. + // + public class Namespace : FullNamedExpression + { + Namespace parent; + string fullname; + protected Dictionary namespaces; + protected Dictionary> types; + Dictionary cached_types; + RootNamespace root; + bool cls_checked; + + public readonly MemberName MemberName; + + /// + /// Constructor Takes the current namespace and the + /// name. This is bootstrapped with parent == null + /// and name = "" + /// + public Namespace (Namespace parent, string name) + { + // Expression members. + this.eclass = ExprClass.Namespace; + this.Type = InternalType.Namespace; + this.loc = Location.Null; + + this.parent = parent; + + if (parent != null) + this.root = parent.root; + else + this.root = this as RootNamespace; + + if (this.root == null) + throw new InternalErrorException ("Root namespaces must be created using RootNamespace"); + + string pname = parent != null ? parent.fullname : ""; + + if (pname == "") + fullname = name; + else + fullname = parent.fullname + "." + name; + + if (fullname == null) + throw new InternalErrorException ("Namespace has a null fullname"); + + if (parent != null && parent.MemberName != MemberName.Null) + MemberName = new MemberName (parent.MemberName, name); + else if (name.Length == 0) + MemberName = MemberName.Null; + else + MemberName = new MemberName (name); + + namespaces = new Dictionary (); + cached_types = new Dictionary (); + + root.RegisterNamespace (this); + } + + #region Properties + + /// + /// The qualified name of the current namespace + /// + public string Name { + get { return fullname; } + } + + /// + /// The parent of this namespace, used by the parser to "Pop" + /// the current namespace declaration + /// + public Namespace Parent { + get { return parent; } + } + + #endregion + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc) + { + var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc); + if (retval != null) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type); + ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc); + return; + } + + retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc); + if (retval != null) { + Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, arity, loc); + return; + } + + Namespace ns; + if (arity > 0 && namespaces.TryGetValue (name, out ns)) { + ns.Error_TypeArgumentsCannotBeUsed (ctx, null, arity, loc); + return; + } + + if (this is GlobalRootNamespace) { + ctx.Module.Compiler.Report.Error (400, loc, + "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)", + name); + } else { + ctx.Module.Compiler.Report.Error (234, loc, + "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", + name, GetSignatureForError ()); + } + } + + public override string GetSignatureForError () + { + return fullname; + } + + public Namespace GetNamespace (string name, bool create) + { + int pos = name.IndexOf ('.'); + + Namespace ns; + string first; + if (pos >= 0) + first = name.Substring (0, pos); + else + first = name; + + if (!namespaces.TryGetValue (first, out ns)) { + if (!create) + return null; + + ns = new Namespace (this, first); + namespaces.Add (first, ns); + } + + if (pos >= 0) + ns = ns.GetNamespace (name.Substring (pos + 1), create); + + return ns; + } + + public IList GetAllTypes (string name) + { + IList found; + if (types == null || !types.TryGetValue (name, out found)) + return null; + + return found; + } + + public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) + { + if (types == null) + return null; + + TypeExpr te; + if (arity == 0 && cached_types.TryGetValue (name, out te)) + return te; + + IList found; + if (!types.TryGetValue (name, out found)) + return null; + + TypeSpec best = null; + foreach (var ts in found) { + if (ts.Arity == arity) { + if (best == null) { + if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility) + continue; + + best = ts; + continue; + } + + if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) { + if (mode == LookupMode.Normal) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); + ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ()); + } + break; + } + + if (best.MemberDefinition.IsImported) + best = ts; + + if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly)) + continue; + + if (mode != LookupMode.Normal) + continue; + + if (ts.MemberDefinition.IsImported) + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); + + ctx.Module.Compiler.Report.Warning (436, 2, loc, + "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition", + best.GetSignatureForError ()); + } + + // + // Lookup for the best candidate with the closest arity match + // + if (arity < 0) { + if (best == null) { + best = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { + best = ts; + } + } + } + + if (best == null) + return null; + + te = new TypeExpression (best, Location.Null); + + // TODO MemberCache: Cache more + if (arity == 0 && mode == LookupMode.Normal) + cached_types.Add (name, te); + + return te; + } + + TypeSpec LookupType (string name, int arity) + { + if (types == null) + return null; + + IList found; + if (types.TryGetValue (name, out found)) { + TypeSpec best = null; + + foreach (var ts in found) { + if (ts.Arity == arity) + return ts; + + // + // Lookup for the best candidate with closest arity match + // + if (arity < 0) { + if (best == null) { + best = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { + best = ts; + } + } + } + + return best; + } + + return null; + } + + public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) + { + var texpr = LookupType (ctx, name, arity, mode, loc); + + Namespace ns; + if (arity == 0 && namespaces.TryGetValue (name, out ns)) { + if (texpr == null) + return ns; + + if (mode != LookupMode.Probing) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type); + // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, ""); + ctx.Module.Compiler.Report.Warning (437, 2, loc, + "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file", + texpr.GetSignatureForError (), ns.GetSignatureForError ()); + } + + if (texpr.Type.MemberDefinition.IsImported) + return ns; + } + + return texpr; + } + + // + // Completes types with the given `prefix' + // + public IEnumerable CompletionGetTypesStartingWith (string prefix) + { + if (types == null) + return Enumerable.Empty (); + + var res = from item in types + where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0) + select item.Key; + + if (namespaces != null) + res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key); + + return res; + } + + /// + /// Looks for extension method in this namespace + /// + public List LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity) + { + if (types == null) + return null; + + List found = null; + + // TODO: Add per namespace flag when at least 1 type has extension + + foreach (var tgroup in types.Values) { + foreach (var ts in tgroup) { + if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) + continue; + + var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity); + if (res == null) + continue; + + if (found == null) { + found = res; + } else { + found.AddRange (res); + } + } + } + + return found; + } + + public void AddType (ModuleContainer module, TypeSpec ts) + { + if (types == null) { + types = new Dictionary> (64); + } + + var name = ts.Name; + IList existing; + if (types.TryGetValue (name, out existing)) { + TypeSpec better_type; + TypeSpec found; + if (existing.Count == 1) { + found = existing[0]; + if (ts.Arity == found.Arity) { + better_type = IsImportedTypeOverride (module, ts, found); + if (better_type == found) + return; + + if (better_type != null) { + existing [0] = better_type; + return; + } + } + + existing = new List (); + existing.Add (found); + types[name] = existing; + } else { + for (int i = 0; i < existing.Count; ++i) { + found = existing[i]; + if (ts.Arity != found.Arity) + continue; + + better_type = IsImportedTypeOverride (module, ts, found); + if (better_type == found) + return; + + if (better_type != null) { + existing.RemoveAt (i); + --i; + continue; + } + } + } + + existing.Add (ts); + } else { + types.Add (name, new TypeSpec[] { ts }); + } + } + + // + // We import any types but in the situation there are same types + // but one has better visibility (either public or internal with friend) + // the less visible type is removed from the namespace cache + // + public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found) + { + var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); + var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); + + if (ts_accessible && !found_accessible) + return ts; + + // found is better always better for accessible or inaccessible ts + if (!ts_accessible) + return found; + + return null; + } + + public void RemoveDeclSpace (string name) + { + types.Remove (name); + cached_types.Remove (name); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc) + { + return this; + } + + public void SetBuiltinType (BuiltinTypeSpec pts) + { + var found = types[pts.Name]; + cached_types.Remove (pts.Name); + if (found.Count == 1) { + types[pts.Name][0] = pts; + } else { + throw new NotImplementedException (); + } + } + + public void VerifyClsCompliance () + { + if (types == null || cls_checked) + return; + + cls_checked = true; + + // TODO: This is quite ugly way to check for CLS compliance at namespace level + + var locase_types = new Dictionary> (StringComparer.OrdinalIgnoreCase); + foreach (var tgroup in types.Values) { + foreach (var tm in tgroup) { + if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ()) + continue; + + List found; + if (!locase_types.TryGetValue (tm.Name, out found)) { + found = new List (); + locase_types.Add (tm.Name, found); + } + + found.Add (tm); + } + } + + foreach (var locase in locase_types.Values) { + if (locase.Count < 2) + continue; + + bool all_same = true; + foreach (var notcompliant in locase) { + all_same = notcompliant.Name == locase[0].Name; + if (!all_same) + break; + } + + if (all_same) + continue; + + TypeContainer compiled = null; + foreach (var notcompliant in locase) { + if (!notcompliant.MemberDefinition.IsImported) { + if (compiled != null) + compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled); + + compiled = notcompliant.MemberDefinition as TypeContainer; + } else { + compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant); + } + } + + compiled.Compiler.Report.Warning (3005, 1, compiled.Location, + "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ()); + } + } + } + + // + // Namespace block as created by the parser + // + public class NamespaceContainer : IMemberContext, ITypesContainer + { + Namespace ns; + + readonly ModuleContainer module; + readonly NamespaceContainer parent; + readonly CompilationSourceFile file; + readonly Location loc; + + NamespaceContainer implicit_parent; + int symfile_id; + + // Namespace using import block + List using_aliases; + List using_clauses; + public bool DeclarationFound; + // End + + bool resolved; + + public readonly bool IsImplicit; + public readonly TypeContainer SlaveDeclSpace; + static readonly Namespace [] empty_namespaces = new Namespace [0]; + static readonly string[] empty_using_list = new string[0]; + + Namespace [] namespace_using_table; + + public NamespaceContainer (MemberName name, ModuleContainer module, NamespaceContainer parent, CompilationSourceFile sourceFile) + { + this.module = module; + this.parent = parent; + this.file = sourceFile; + this.loc = name == null ? Location.Null : name.Location; + + if (parent != null) + ns = parent.NS.GetNamespace (name.GetName (), true); + else if (name != null) + ns = module.GlobalRootNamespace.GetNamespace (name.GetName (), true); + else + ns = module.GlobalRootNamespace; + + SlaveDeclSpace = new RootDeclSpace (module, this); + } + + private NamespaceContainer (ModuleContainer module, NamespaceContainer parent, CompilationSourceFile file, Namespace ns, bool slave) + { + this.module = module; + this.parent = parent; + this.file = file; + this.IsImplicit = true; + this.ns = ns; + this.SlaveDeclSpace = slave ? new RootDeclSpace (module, this) : null; + } + + #region Properties + + public Location Location { + get { + return loc; + } + } + + public MemberName MemberName { + get { + return ns.MemberName; + } + } + + public CompilationSourceFile SourceFile { + get { + return file; + } + } + + public List Usings { + get { + return using_clauses; + } + } + + #endregion + + // + // Extracts the using alises and using clauses into a couple of + // arrays that might already have the same information; Used by the + // C# Eval mode. + // + public void Extract (List out_using_aliases, List out_using_clauses) + { + if (using_aliases != null){ + foreach (NamespaceUsingAlias uae in using_aliases){ + bool replaced = false; + + for (int i = 0; i < out_using_aliases.Count; i++){ + NamespaceUsingAlias out_uea = (NamespaceUsingAlias) out_using_aliases [i]; + + if (out_uea.Alias == uae.Alias){ + out_using_aliases [i] = uae; + replaced = true; + break; + } + } + if (!replaced) + out_using_aliases.Add (uae); + } + } + + if (using_clauses != null){ + foreach (NamespaceUsing ue in using_clauses){ + bool found = false; + + foreach (NamespaceUsing out_ue in out_using_clauses) + if (out_ue.Name == ue.Name){ + found = true; + break; + } + if (!found) + out_using_clauses.Add (ue); + } + } + } + + // + // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is + // resolved as if the immediately containing namespace body has no using-directives. + // + // Section 16.3.2 says that the same rule is applied when resolving the namespace-name + // in the using-namespace-directive. + // + // To implement these rules, the expressions in the using directives are resolved using + // the "doppelganger" (ghostly bodiless duplicate). + // + NamespaceContainer doppelganger; + NamespaceContainer Doppelganger { + get { + if (!IsImplicit && doppelganger == null) { + doppelganger = new NamespaceContainer (module, ImplicitParent, file, ns, true); + doppelganger.using_aliases = using_aliases; + } + return doppelganger; + } + } + + public Namespace NS { + get { return ns; } + } + + public NamespaceContainer Parent { + get { return parent; } + } + + public NamespaceContainer ImplicitParent { + get { + if (parent == null) + return null; + if (implicit_parent == null) { + implicit_parent = (parent.NS == ns.Parent) + ? parent + : new NamespaceContainer (module, parent, file, ns.Parent, false); + } + return implicit_parent; + } + } + + /// + /// Records a new namespace for resolving name references + /// + public void AddUsing (MemberName name, Location loc) + { + if (DeclarationFound){ + Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations"); + } + + if (using_clauses == null) { + using_clauses = new List (); + } else { + foreach (NamespaceUsing old_entry in using_clauses) { + if (name.Equals (old_entry.MemberName)) { + Compiler.Report.SymbolRelatedToPreviousError (old_entry.Location, old_entry.GetSignatureForError ()); + Compiler.Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetSignatureForError ()); + return; + } + } + } + + using_clauses.Add (new NamespaceUsing (name)); + } + + public void AddUsingAlias (string alias, MemberName name, Location loc) + { + if (DeclarationFound){ + Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations"); + } + + AddUsingAlias (new LocalUsingAliasEntry (alias, name, loc)); + } + + public void AddUsingExternalAlias (string alias, Location loc, Report Report) + { + bool not_first = using_clauses != null || DeclarationFound; + if (using_aliases != null && !not_first) { + foreach (NamespaceUsingAlias uae in using_aliases) { + if (uae is LocalUsingAliasEntry) { + not_first = true; + break; + } + } + } + + if (not_first) + Report.Error (439, loc, "An extern alias declaration must precede all other elements"); + + if (alias == "global") { + Error_GlobalNamespaceRedefined (loc, Report); + return; + } + + AddUsingAlias (new NamespaceUsingAlias (alias, loc)); + } + + void AddUsingAlias (NamespaceUsingAlias uae) + { + if (using_aliases == null) { + using_aliases = new List (); + } else { + foreach (NamespaceUsingAlias entry in using_aliases) { + if (uae.Alias == entry.Alias) { + Compiler.Report.SymbolRelatedToPreviousError (uae.Location, uae.Alias); + Compiler.Report.Error (1537, entry.Location, "The using alias `{0}' appeared previously in this namespace", + entry.Alias); + return; + } + } + } + + using_aliases.Add (uae); + } + + // + // Does extension methods look up to find a method which matches name and extensionType. + // Search starts from this namespace and continues hierarchically up to top level. + // + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + List candidates = null; + foreach (Namespace n in GetUsingTable ()) { + var a = n.LookupExtensionMethod (this, extensionType, name, arity); + if (a == null) + continue; + + if (candidates == null) + candidates = a; + else + candidates.AddRange (a); + } + + scope = parent; + if (candidates != null) + return candidates; + + if (parent == null) + return null; + + // + // Inspect parent namespaces in namespace expression + // + Namespace parent_ns = ns.Parent; + do { + candidates = parent_ns.LookupExtensionMethod (this, extensionType, name, arity); + if (candidates != null) + return candidates; + + parent_ns = parent_ns.Parent; + } while (parent_ns != null); + + // + // Continue in parent scope + // + return parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + // Precondition: Only simple names (no dots) will be looked up with this function. + FullNamedExpression resolved = null; + for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) { + if ((resolved = curr_ns.Lookup (name, arity, mode, loc)) != null) + break; + } + + return resolved; + } + + public IList CompletionGetTypesStartingWith (string prefix) + { + IEnumerable all = Enumerable.Empty (); + + for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent){ + foreach (Namespace using_ns in GetUsingTable ()){ + if (prefix.StartsWith (using_ns.Name)){ + int ld = prefix.LastIndexOf ('.'); + if (ld != -1){ + string rest = prefix.Substring (ld+1); + + all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest)); + } + } + all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix)); + } + } + + return all.Distinct ().ToList (); + } + + // Looks-up a alias named @name in this and surrounding namespace declarations + public FullNamedExpression LookupNamespaceAlias (string name) + { + for (NamespaceContainer n = this; n != null; n = n.ImplicitParent) { + if (n.using_aliases == null) + continue; + + foreach (NamespaceUsingAlias ue in n.using_aliases) { + if (ue.Alias == name) + return ue.Resolve (Doppelganger ?? this, Doppelganger == null); + } + } + + return null; + } + + FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc) + { + // + // Check whether it's in the namespace. + // + FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc); + + // + // Check aliases. + // + if (using_aliases != null && arity == 0) { + foreach (NamespaceUsingAlias ue in using_aliases) { + if (ue.Alias == name) { + if (fne != null) { + if (Doppelganger != null) { + if (mode == LookupMode.Normal) { + // TODO: Namespace has broken location + //Report.SymbolRelatedToPreviousError (fne.Location, null); + Compiler.Report.SymbolRelatedToPreviousError (ue.Location, null); + Compiler.Report.Error (576, loc, + "Namespace `{0}' contains a definition with same name as alias `{1}'", + GetSignatureForError (), name); + } + } else { + return fne; + } + } + + return ue.Resolve (Doppelganger ?? this, Doppelganger == null); + } + } + } + + if (fne != null) + return fne; + + if (IsImplicit) + return null; + + // + // Check using entries. + // + FullNamedExpression match = null; + foreach (Namespace using_ns in GetUsingTable ()) { + // A using directive imports only types contained in the namespace, it + // does not import any nested namespaces + fne = using_ns.LookupType (this, name, arity, mode, loc); + if (fne == null) + continue; + + if (match == null) { + match = fne; + continue; + } + + // Prefer types over namespaces + var texpr_fne = fne as TypeExpr; + var texpr_match = match as TypeExpr; + if (texpr_fne != null && texpr_match == null) { + match = fne; + continue; + } else if (texpr_fne == null) { + continue; + } + + // It can be top level accessibility only + var better = Namespace.IsImportedTypeOverride (module, texpr_match.Type, texpr_fne.Type); + if (better == null) { + if (mode == LookupMode.Normal) { + Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type); + Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type); + Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'", + name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ()); + } + + return match; + } + + if (better == texpr_fne.Type) + match = texpr_fne; + } + + return match; + } + + Namespace [] GetUsingTable () + { + if (namespace_using_table != null) + return namespace_using_table; + + if (using_clauses == null) { + namespace_using_table = empty_namespaces; + return namespace_using_table; + } + + var list = new List (using_clauses.Count); + + foreach (NamespaceUsing ue in using_clauses) { + Namespace using_ns = ue.Resolve (Doppelganger); + if (using_ns == null) + continue; + + list.Add (using_ns); + } + + namespace_using_table = list.ToArray (); + return namespace_using_table; + } + + public int SymbolFileID { + get { + if (symfile_id == 0 && file.SourceFileEntry != null) { + int parent_id = parent == null ? 0 : parent.SymbolFileID; + + string [] using_list = empty_using_list; + if (using_clauses != null) { + using_list = new string [using_clauses.Count]; + for (int i = 0; i < using_clauses.Count; i++) + using_list [i] = ((NamespaceUsing) using_clauses [i]).MemberName.GetName (); + } + + symfile_id = SymbolWriter.DefineNamespace (ns.Name, file.CompileUnitEntry, using_list, parent_id); + } + return symfile_id; + } + } + + static void MsgtryRef (string s) + { + Console.WriteLine (" Try using -r:" + s); + } + + static void MsgtryPkg (string s) + { + Console.WriteLine (" Try using -pkg:" + s); + } + + public static void Error_GlobalNamespaceRedefined (Location loc, Report Report) + { + Report.Error (1681, loc, "The global extern alias cannot be redefined"); + } + + public static void Error_NamespaceNotFound (Location loc, string name, Report Report) + { + Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?", + name); + + switch (name) { + case "Gtk": case "GtkSharp": + MsgtryPkg ("gtk-sharp-2.0"); + break; + + case "Gdk": case "GdkSharp": + MsgtryPkg ("gdk-sharp-2.0"); + break; + + case "Glade": case "GladeSharp": + MsgtryPkg ("glade-sharp-2.0"); + break; + + case "System.Drawing": + case "System.Web.Services": + case "System.Web": + case "System.Data": + case "System.Windows.Forms": + MsgtryRef (name); + break; + } + } + + /// + /// Used to validate that all the using clauses are correct + /// after we are finished parsing all the files. + /// + public void Resolve () + { + if (resolved) + return; + + resolved = true; + + if (using_aliases != null) { + foreach (NamespaceUsingAlias ue in using_aliases) + ue.Resolve (Doppelganger, Doppelganger == null); + } + + if (using_clauses != null) { + foreach (NamespaceUsing ue in using_clauses) + ue.Resolve (Doppelganger); + } + + if (parent != null) + parent.Resolve (); + } + + public string GetSignatureForError () + { + return ns.GetSignatureForError (); + } + + #region IMemberContext Members + + CompilerContext Compiler { + get { return module.Compiler; } + } + + public TypeSpec CurrentType { + get { return SlaveDeclSpace.CurrentType; } + } + + public MemberCore CurrentMemberDefinition { + get { return SlaveDeclSpace.CurrentMemberDefinition; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return SlaveDeclSpace.CurrentTypeParameters; } + } + + public bool IsObsolete { + get { return SlaveDeclSpace.IsObsolete; } + } + + public bool IsUnsafe { + get { return SlaveDeclSpace.IsUnsafe; } + } + + public bool IsStatic { + get { return SlaveDeclSpace.IsStatic; } + } + + public ModuleContainer Module { + get { return module; } + } + + #endregion + } + + public class NamespaceUsing + { + readonly MemberName name; + Namespace resolved; + + public NamespaceUsing (MemberName name) + { + this.name = name; + } + + public string GetSignatureForError () + { + return name.GetSignatureForError (); + } + + public Location Location + { + get { return name.Location; } + } + + public MemberName MemberName + { + get { return name; } + } + + public string Name + { + get { return GetSignatureForError (); } + } + + public Namespace Resolve (IMemberContext rc) + { + if (resolved != null) + return resolved; + + FullNamedExpression fne = name.GetTypeExpression ().ResolveAsTypeOrNamespace (rc); + if (fne == null) + return null; + + resolved = fne as Namespace; + if (resolved == null) { + rc.Module.Compiler.Report.SymbolRelatedToPreviousError (fne.Type); + rc.Module.Compiler.Report.Error (138, Location, + "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces", + GetSignatureForError ()); + } + return resolved; + } + } + + public class NamespaceUsingAlias + { + public readonly string Alias; + public Location Location; + + public NamespaceUsingAlias (string alias, Location loc) + { + this.Alias = alias; + this.Location = loc; + } + + public virtual FullNamedExpression Resolve (IMemberContext rc, bool local) + { + FullNamedExpression fne = rc.Module.GetRootNamespace (Alias); + if (fne == null) { + rc.Module.Compiler.Report.Error (430, Location, + "The extern alias `{0}' was not specified in -reference option", + Alias); + } + + return fne; + } + } + + class LocalUsingAliasEntry : NamespaceUsingAlias + { + FullNamedExpression resolved; + MemberName value; + + public LocalUsingAliasEntry (string alias, MemberName name, Location loc) + : base (alias, loc) + { + this.value = name; + } + + public override FullNamedExpression Resolve (IMemberContext rc, bool local) + { + if (resolved != null || value == null) + return resolved; + + if (local) + return null; + + resolved = value.GetTypeExpression ().ResolveAsTypeOrNamespace (rc); + if (resolved == null) { + value = null; + return null; + } + + return resolved; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs new file mode 100644 index 0000000000..f6b9abcca9 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs @@ -0,0 +1,1292 @@ +// +// nullable.cs: Nullable types support +// +// Authors: Martin Baulig (martin@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// + +using System; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp.Nullable +{ + public class NullableType : TypeExpr + { + readonly TypeSpec underlying; + + public NullableType (TypeSpec type, Location loc) + { + this.underlying = type; + this.loc = loc; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + eclass = ExprClass.Type; + + var otype = ec.Module.PredefinedTypes.Nullable.Resolve (); + if (otype == null) + return null; + + TypeArguments args = new TypeArguments (new TypeExpression (underlying, loc)); + GenericTypeExpr ctype = new GenericTypeExpr (otype, args, loc); + + type = ctype.ResolveAsType (ec); + return type; + } + } + + static class NullableInfo + { + public static MethodSpec GetConstructor (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (GetUnderlyingType (nullableType))), BindingRestriction.DeclaredOnly); + } + + public static MethodSpec GetHasValue (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("get_HasValue", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static MethodSpec GetGetValueOrDefault (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("GetValueOrDefault", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static MethodSpec GetValue (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("get_Value", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static TypeSpec GetUnderlyingType (TypeSpec nullableType) + { + return ((InflatedTypeSpec) nullableType).TypeArguments[0]; + } + } + + public class Unwrap : Expression, IMemoryLocation, IAssignMethod + { + Expression expr; + + LocalTemporary temp; + readonly bool useDefaultValue; + + Unwrap (Expression expr, bool useDefaultValue) + { + this.expr = expr; + this.loc = expr.Location; + this.useDefaultValue = useDefaultValue; + + type = NullableInfo.GetUnderlyingType (expr.Type); + eclass = expr.eclass; + } + + public static Expression Create (Expression expr) + { + // + // Avoid unwraping and wraping of same type + // + Wrap wrap = expr as Wrap; + if (wrap != null) + return wrap.Child; + + return Create (expr, false); + } + + public static Unwrap Create (Expression expr, bool useDefaultValue) + { + return new Unwrap (expr, useDefaultValue); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + expr = expr.DoResolveLValue (ec, right_side); + return this; + } + + public override void Emit (EmitContext ec) + { + Store (ec); + if (useDefaultValue) + Invocation.EmitCall (ec, this, NullableInfo.GetGetValueOrDefault (expr.Type), null, loc); + else + Invocation.EmitCall (ec, this, NullableInfo.GetValue (expr.Type), null, loc); + } + + public void EmitCheck (EmitContext ec) + { + Store (ec); + Invocation.EmitCall (ec, this, NullableInfo.GetHasValue (expr.Type), null, loc); + } + + public override bool Equals (object obj) + { + Unwrap uw = obj as Unwrap; + return uw != null && expr.Equals (uw.expr); + } + + public Expression Original { + get { + return expr; + } + } + + public override int GetHashCode () + { + return expr.GetHashCode (); + } + + public override bool IsNull { + get { + return expr.IsNull; + } + } + + void Store (EmitContext ec) + { + if (expr is VariableReference) + return; + + if (temp != null) + return; + + expr.Emit (ec); + LocalVariable.Store (ec); + } + + public void Load (EmitContext ec) + { + if (expr is VariableReference) + expr.Emit (ec); + else + LocalVariable.Emit (ec); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return expr.MakeExpression (ctx); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + IMemoryLocation ml = expr as VariableReference; + if (ml != null) + ml.AddressOf (ec, mode); + else + LocalVariable.AddressOf (ec, mode); + } + + // + // Keeps result of non-variable expression + // + LocalTemporary LocalVariable { + get { + if (temp == null) + temp = new LocalTemporary (expr.Type); + return temp; + } + } + + public void Emit (EmitContext ec, bool leave_copy) + { + if (leave_copy) + Load (ec); + + Emit (ec); + } + + public void EmitAssign (EmitContext ec, Expression source, + bool leave_copy, bool prepare_for_load) + { + InternalWrap wrap = new InternalWrap (source, expr.Type, loc); + ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false); + } + + class InternalWrap : Expression + { + public Expression expr; + + public InternalWrap (Expression expr, TypeSpec type, Location loc) + { + this.expr = expr; + this.loc = loc; + this.type = type; + + eclass = ExprClass.Value; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } + } + } + + // + // Calls get_Value method on nullable expression + // + public class UnwrapCall : CompositeExpression + { + public UnwrapCall (Expression expr) + : base (expr) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + base.DoResolve (rc); + + if (type != null) + type = NullableInfo.GetUnderlyingType (type); + + return this; + } + + public override void Emit (EmitContext ec) + { + Invocation.EmitCall (ec, Child, NullableInfo.GetValue (Child.Type), null, loc); + } + } + + public class Wrap : TypeCast + { + private Wrap (Expression expr, TypeSpec type) + : base (expr, type) + { + eclass = ExprClass.Value; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + TypeCast child_cast = child as TypeCast; + if (child_cast != null) { + child.Type = type; + return child_cast.CreateExpressionTree (ec); + } + + return base.CreateExpressionTree (ec); + } + + public static Expression Create (Expression expr, TypeSpec type) + { + // + // Avoid unwraping and wraping of the same type + // + Unwrap unwrap = expr as Unwrap; + if (unwrap != null && expr.Type == NullableInfo.GetUnderlyingType (type)) + return unwrap.Original; + + return new Wrap (expr, type); + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } + } + + // + // Represents null literal lifted to nullable type + // + public class LiftedNull : NullConstant, IMemoryLocation + { + private LiftedNull (TypeSpec nullable_type, Location loc) + : base (nullable_type, loc) + { + eclass = ExprClass.Value; + } + + public static Constant Create (TypeSpec nullable, Location loc) + { + return new LiftedNull (nullable, loc); + } + + public static Constant CreateFromExpression (ResolveContext ec, Expression e) + { + ec.Report.Warning (458, 2, e.Location, "The result of the expression is always `null' of type `{0}'", + TypeManager.CSharpName (e.Type)); + + return ReducedExpression.Create (Create (e.Type, e.Location), e); + } + + public override void Emit (EmitContext ec) + { + // TODO: generate less temporary variables + LocalTemporary value_target = new LocalTemporary (type); + + value_target.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + value_target.Emit (ec); + } + + public void AddressOf (EmitContext ec, AddressOp Mode) + { + LocalTemporary value_target = new LocalTemporary (type); + + value_target.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + ((IMemoryLocation) value_target).AddressOf (ec, Mode); + } + } + + // + // Generic lifting expression, supports all S/S? -> T/T? cases + // + public class Lifted : Expression, IMemoryLocation + { + Expression expr, null_value; + Unwrap unwrap; + + public Lifted (Expression expr, Unwrap unwrap, TypeSpec type) + { + this.expr = expr; + this.unwrap = unwrap; + this.loc = expr.Location; + this.type = type; + } + + public Lifted (Expression expr, Expression unwrap, TypeSpec type) + : this (expr, unwrap as Unwrap, type) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // + // It's null when lifting non-nullable type + // + if (unwrap == null) { + // S -> T? is wrap only + if (type.IsNullableType) + return Wrap.Create (expr, type); + + // S -> T can be simplified + return expr; + } + + // Wrap target for T? + if (type.IsNullableType) { + expr = Wrap.Create (expr, type); + if (expr == null) + return null; + + null_value = LiftedNull.Create (type, loc); + } else if (TypeSpec.IsValueType (type)) { + null_value = LiftedNull.Create (type, loc); + } else { + null_value = new NullConstant (type, loc); + } + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + expr.Emit (ec); + + ec.Emit (OpCodes.Br, end_label); + ec.MarkLabel (is_null_label); + + null_value.Emit (ec); + ec.MarkLabel (end_label); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + unwrap.AddressOf (ec, mode); + } + } + + public class LiftedUnaryOperator : Unary, IMemoryLocation + { + Unwrap unwrap; + Expression user_operator; + + public LiftedUnaryOperator (Unary.Operator op, Expression expr, Location loc) + : base (op, expr, loc) + { + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + unwrap.AddressOf (ec, mode); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (user_operator != null) + return user_operator.CreateExpressionTree (ec); + + if (Oper == Operator.UnaryPlus) + return Expr.CreateExpressionTree (ec); + + return base.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + unwrap = Unwrap.Create (Expr, false); + if (unwrap == null) + return null; + + Expression res = base.ResolveOperator (ec, unwrap); + if (res != this) { + if (user_operator == null) + return res; + } else { + res = Expr = LiftExpression (ec, Expr); + } + + if (res == null) + return null; + + eclass = ExprClass.Value; + type = res.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + if (user_operator != null) { + user_operator.Emit (ec); + } else { + EmitOperator (ec, NullableInfo.GetUnderlyingType (type)); + } + + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + ec.Emit (OpCodes.Br_S, end_label); + + ec.MarkLabel (is_null_label); + LiftedNull.Create (type, loc).Emit (ec); + + ec.MarkLabel (end_label); + } + + Expression LiftExpression (ResolveContext ec, Expression expr) + { + var lifted_type = new NullableType (expr.Type, expr.Location); + if (lifted_type.ResolveAsType (ec) == null) + return null; + + expr.Type = lifted_type.Type; + return expr; + } + + protected override Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + expr = base.ResolveEnumOperator (ec, expr, predefined); + if (expr == null) + return null; + + Expr = LiftExpression (ec, Expr); + return LiftExpression (ec, expr); + } + + protected override Expression ResolveUserOperator (ResolveContext ec, Expression expr) + { + expr = base.ResolveUserOperator (ec, expr); + if (expr == null) + return null; + + // + // When a user operator is of non-nullable type + // + if (Expr is Unwrap) { + user_operator = LiftExpression (ec, expr); + return user_operator; + } + + return expr; + } + } + + public class LiftedBinaryOperator : Binary + { + Unwrap left_unwrap, right_unwrap; + Expression left_orig, right_orig; + Expression user_operator; + MethodSpec wrap_ctor; + + public LiftedBinaryOperator (Binary.Operator op, Expression left, Expression right, Location loc) + : base (op, left, right, loc) + { + } + + bool IsBitwiseBoolean { + get { + return (Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && + ((left_unwrap != null && left_unwrap.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) || + (right_unwrap != null && right_unwrap.Type.BuiltinType == BuiltinTypeSpec.Type.Bool)); + } + } + + bool IsLeftNullLifted { + get { + return (state & State.LeftNullLifted) != 0; + } + } + + bool IsRightNullLifted { + get { + return (state & State.RightNullLifted) != 0; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (user_operator != null) + return user_operator.CreateExpressionTree (ec); + + return base.CreateExpressionTree (ec); + } + + // + // CSC 2 has this behavior, it allows structs to be compared + // with the null literal *outside* of a generics context and + // inlines that as true or false. + // + Constant CreateNullConstant (ResolveContext ec, Expression expr) + { + // FIXME: Handle side effect constants + Constant c = new BoolConstant (ec.BuiltinTypes, Oper == Operator.Inequality, loc); + + if ((Oper & Operator.EqualityMask) != 0) { + ec.Report.Warning (472, 2, loc, "The result of comparing value type `{0}' with null is `{1}'", + TypeManager.CSharpName (expr.Type), c.GetValueAsLiteral ()); + } else { + ec.Report.Warning (464, 2, loc, "The result of comparing type `{0}' with null is always `{1}'", + TypeManager.CSharpName (expr.Type), c.GetValueAsLiteral ()); + } + + return ReducedExpression.Create (c, this); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if ((Oper & Operator.LogicalMask) != 0) { + Error_OperatorCannotBeApplied (ec, left, right); + return null; + } + + bool use_default_call = (Oper & (Operator.BitwiseMask | Operator.EqualityMask)) != 0; + left_orig = left; + if (left.Type.IsNullableType) { + left = left_unwrap = Unwrap.Create (left, use_default_call); + if (left == null) + return null; + } + + right_orig = right; + if (right.Type.IsNullableType) { + right = right_unwrap = Unwrap.Create (right, use_default_call); + if (right == null) + return null; + } + + // + // Some details are in 6.4.2, 7.2.7 + // Arguments can be lifted for equal operators when the return type is bool and both + // arguments are of same type + // + if (left_orig is NullLiteral) { + left = right; + state |= State.LeftNullLifted; + type = ec.BuiltinTypes.Bool; + } + + if (right_orig.IsNull) { + if ((Oper & Operator.ShiftMask) != 0) + right = new EmptyExpression (ec.BuiltinTypes.Int); + else + right = left; + + state |= State.RightNullLifted; + type = ec.BuiltinTypes.Bool; + } + + eclass = ExprClass.Value; + return DoResolveCore (ec, left_orig, right_orig); + } + + void EmitBitwiseBoolean (EmitContext ec) + { + Label load_left = ec.DefineLabel (); + Label load_right = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + // null & value, null | value + if (left_unwrap == null) { + left_unwrap = right_unwrap; + right_unwrap = null; + right = left; + } + + left_unwrap.Emit (ec); + ec.Emit (OpCodes.Brtrue_S, load_right); + + // value & null, value | null + if (right_unwrap != null) { + right_unwrap.Emit (ec); + ec.Emit (OpCodes.Brtrue_S, load_left); + } + + left_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse_S, load_right); + + // load left + ec.MarkLabel (load_left); + + if (Oper == Operator.BitwiseAnd) { + left_unwrap.Load (ec); + } else { + if (right_unwrap == null) { + right.Emit (ec); + if (right is EmptyConstantCast || right is EmptyCast) + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } else { + right_unwrap.Load (ec); + right_unwrap = left_unwrap; + } + } + ec.Emit (OpCodes.Br_S, end_label); + + // load right + ec.MarkLabel (load_right); + if (right_unwrap == null) { + if (Oper == Operator.BitwiseAnd) { + right.Emit (ec); + if (right is EmptyConstantCast || right is EmptyCast) + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } else { + left_unwrap.Load (ec); + } + } else { + right_unwrap.Load (ec); + } + + ec.MarkLabel (end_label); + } + + // + // Emits optimized equality or inequality operator when possible + // + void EmitEquality (EmitContext ec) + { + // + // Either left or right is null + // + if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) { + left_unwrap.EmitCheck (ec); + if (Oper == Binary.Operator.Equality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + return; + } + + if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) { + right_unwrap.EmitCheck (ec); + if (Oper == Binary.Operator.Equality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + return; + } + + Label dissimilar_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + if (user_operator != null) { + user_operator.Emit (ec); + ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label); + } else { + left.Emit (ec); + right.Emit (ec); + + ec.Emit (OpCodes.Bne_Un_S, dissimilar_label); + } + + if (left_unwrap != null) + left_unwrap.EmitCheck (ec); + + if (right_unwrap != null) + right_unwrap.EmitCheck (ec); + + if (left_unwrap != null && right_unwrap != null) { + if (Oper == Operator.Inequality) + ec.Emit (OpCodes.Xor); + else + ec.Emit (OpCodes.Ceq); + } else { + if (Oper == Operator.Inequality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + } + + ec.Emit (OpCodes.Br_S, end_label); + + ec.MarkLabel (dissimilar_label); + if (Oper == Operator.Inequality) + ec.Emit (OpCodes.Ldc_I4_1); + else + ec.Emit (OpCodes.Ldc_I4_0); + + ec.MarkLabel (end_label); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool onTrue) + { + Emit (ec); + ec.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + public override void Emit (EmitContext ec) + { + // + // Optimize same expression operation + // + if (right_unwrap != null && right.Equals (left)) + right_unwrap = left_unwrap; + + if (user_operator == null && IsBitwiseBoolean) { + EmitBitwiseBoolean (ec); + return; + } + + if ((Oper & Operator.EqualityMask) != 0) { + EmitEquality (ec); + return; + } + + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + if (left_unwrap != null) { + left_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + } + + // + // Don't emit HasValue check when left and right expressions are same + // + if (right_unwrap != null && !left.Equals (right)) { + right_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + } + + EmitOperator (ec, left.Type); + + if (wrap_ctor != null) + ec.Emit (OpCodes.Newobj, wrap_ctor); + + ec.Emit (OpCodes.Br_S, end_label); + ec.MarkLabel (is_null_label); + + if ((Oper & Operator.ComparisonMask) != 0) { + ec.Emit (OpCodes.Ldc_I4_0); + } else { + LiftedNull.Create (type, loc).Emit (ec); + } + + ec.MarkLabel (end_label); + } + + protected override void EmitOperator (EmitContext ec, TypeSpec l) + { + if (user_operator != null) { + user_operator.Emit (ec); + return; + } + + if (l.IsNullableType) + l = TypeManager.GetTypeArguments (l) [0]; + + base.EmitOperator (ec, l); + } + + Expression LiftResult (ResolveContext ec, Expression res_expr) + { + TypeSpec lifted_type; + + // + // Avoid double conversion + // + if (left_unwrap == null || IsLeftNullLifted || left_unwrap.Type != left.Type || (left_unwrap != null && IsRightNullLifted)) { + lifted_type = new NullableType (left.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + if (left is UserCast || left is TypeCast) + left.Type = lifted_type; + else + left = EmptyCast.Create (left, lifted_type); + } + + if (left != right && (right_unwrap == null || IsRightNullLifted || right_unwrap.Type != right.Type || (right_unwrap != null && IsLeftNullLifted))) { + lifted_type = new NullableType (right.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + var r = right; + if (r is ReducedExpression) + r = ((ReducedExpression) r).OriginalExpression; + + if (r is UserCast || r is TypeCast) + r.Type = lifted_type; + else + right = EmptyCast.Create (right, lifted_type); + } + + if ((Oper & Operator.ComparisonMask) == 0) { + lifted_type = new NullableType (res_expr.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + wrap_ctor = NullableInfo.GetConstructor (lifted_type); + type = res_expr.Type = lifted_type; + } + + if (IsLeftNullLifted) { + left = LiftedNull.Create (right.Type, left.Location); + + // + // Special case for bool?, the result depends on both null right side and left side value + // + if ((Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && NullableInfo.GetUnderlyingType (type).BuiltinType == BuiltinTypeSpec.Type.Bool) { + return res_expr; + } + + if ((Oper & (Operator.ArithmeticMask | Operator.ShiftMask | Operator.BitwiseMask)) != 0) + return LiftedNull.CreateFromExpression (ec, res_expr); + + // + // Value types and null comparison + // + if (right_unwrap == null || (Oper & Operator.RelationalMask) != 0) + return CreateNullConstant (ec, right_orig); + } + + if (IsRightNullLifted) { + right = LiftedNull.Create (left.Type, right.Location); + + // + // Special case for bool?, the result depends on both null right side and left side value + // + if ((Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && NullableInfo.GetUnderlyingType (type).BuiltinType == BuiltinTypeSpec.Type.Bool) { + return res_expr; + } + + if ((Oper & (Operator.ArithmeticMask | Operator.ShiftMask | Operator.BitwiseMask)) != 0) + return LiftedNull.CreateFromExpression (ec, res_expr); + + // + // Value types and null comparison + // + if (left_unwrap == null || (Oper & Operator.RelationalMask) != 0) + return CreateNullConstant (ec, left_orig); + } + + return res_expr; + } + + protected override Expression ResolveOperatorPredefined (ResolveContext ec, Binary.PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type) + { + Expression e = base.ResolveOperatorPredefined (ec, operators, primitives_only, enum_type); + + if (e == this || enum_type != null) + return LiftResult (ec, e); + + // + // 7.9.9 Equality operators and null + // + // The == and != operators permit one operand to be a value of a nullable type and + // the other to be the null literal, even if no predefined or user-defined operator + // (in unlifted or lifted form) exists for the operation. + // + if (e == null && (Oper & Operator.EqualityMask) != 0) { + if ((IsLeftNullLifted && right_unwrap != null) || (IsRightNullLifted && left_unwrap != null)) + return LiftResult (ec, this); + } + + return e; + } + + protected override Expression ResolveUserOperator (ResolveContext ec, Expression left, Expression right) + { + // + // Try original types first for exact match without unwrapping + // + Expression expr = base.ResolveUserOperator (ec, left_orig, right_orig); + if (expr != null) + return expr; + + State orig_state = state; + + // + // One side is a nullable type, try to match underlying types + // + if (left_unwrap != null || right_unwrap != null || (state & (State.RightNullLifted | State.LeftNullLifted)) != 0) { + expr = base.ResolveUserOperator (ec, left, right); + } + + if (expr == null) + return null; + + // + // Lift the result in the case it can be null and predefined or user operator + // result type is of a value type + // + if (!TypeSpec.IsValueType (expr.Type)) + return null; + + if (state != orig_state) + return expr; + + expr = LiftResult (ec, expr); + if (expr is Constant) + return expr; + + type = expr.Type; + user_operator = expr; + return this; + } + } + + public class NullCoalescingOperator : Expression + { + Expression left, right; + Unwrap unwrap; + + public Expression Left { + get { return this.left; } + } + + public Expression Right { + get { return this.right; } + } + + public NullCoalescingOperator (Expression left, Expression right, Location loc) + { + this.left = left; + this.right = right; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (left is NullLiteral) + ec.Report.Error (845, loc, "An expression tree cannot contain a coalescing operator with null left side"); + + UserCast uc = left as UserCast; + Expression conversion = null; + if (uc != null) { + left = uc.Source; + + Arguments c_args = new Arguments (2); + c_args.Add (new Argument (uc.CreateExpressionTree (ec))); + c_args.Add (new Argument (left.CreateExpressionTree (ec))); + conversion = CreateExpressionFactoryCall (ec, "Lambda", c_args); + } + + Arguments args = new Arguments (3); + args.Add (new Argument (left.CreateExpressionTree (ec))); + args.Add (new Argument (right.CreateExpressionTree (ec))); + if (conversion != null) + args.Add (new Argument (conversion)); + + return CreateExpressionFactoryCall (ec, "Coalesce", args); + } + + Expression ConvertExpression (ResolveContext ec) + { + // TODO: ImplicitConversionExists should take care of this + if (left.eclass == ExprClass.MethodGroup) + return null; + + TypeSpec ltype = left.Type; + + // + // If left is a nullable type and an implicit conversion exists from right to underlying type of left, + // the result is underlying type of left + // + if (ltype.IsNullableType) { + unwrap = Unwrap.Create (left, false); + if (unwrap == null) + return null; + + // + // Reduce (left ?? null) to left + // + if (right.IsNull) + return ReducedExpression.Create (left, this); + + if (Convert.ImplicitConversionExists (ec, right, unwrap.Type)) { + left = unwrap; + ltype = left.Type; + + // + // If right is a dynamic expression, the result type is dynamic + // + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + type = right.Type; + + // Need to box underlying value type + left = Convert.ImplicitBoxingConversion (left, ltype, type); + return this; + } + + right = Convert.ImplicitConversion (ec, right, ltype, loc); + type = ltype; + return this; + } + } else if (TypeSpec.IsReferenceType (ltype)) { + if (Convert.ImplicitConversionExists (ec, right, ltype)) { + // + // If right is a dynamic expression, the result type is dynamic + // + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + type = right.Type; + return this; + } + + // + // Reduce ("foo" ?? expr) to expression + // + Constant lc = left as Constant; + if (lc != null && !lc.IsDefaultValue) + return ReducedExpression.Create (lc, this); + + // + // Reduce (left ?? null) to left OR (null-constant ?? right) to right + // + if (right.IsNull || lc != null) + return ReducedExpression.Create (lc != null ? right : left, this); + + right = Convert.ImplicitConversion (ec, right, ltype, loc); + type = ltype; + return this; + } + + // + // Special case null ?? null + // + if (ltype == right.Type) { + type = ltype; + return this; + } + } else { + return null; + } + + TypeSpec rtype = right.Type; + if (!Convert.ImplicitConversionExists (ec, unwrap != null ? unwrap : left, rtype) || right.eclass == ExprClass.MethodGroup) + return null; + + // + // Reduce (null ?? right) to right + // + if (left.IsNull) + return ReducedExpression.Create (right, this).Resolve (ec); + + left = Convert.ImplicitConversion (ec, unwrap != null ? unwrap : left, rtype, loc); + type = rtype; + return this; + } + + protected override Expression DoResolve (ResolveContext ec) + { + left = left.Resolve (ec); + right = right.Resolve (ec); + + if (left == null || right == null) + return null; + + eclass = ExprClass.Value; + + Expression e = ConvertExpression (ec); + if (e == null) { + Binary.Error_OperatorCannotBeApplied (ec, left, right, "??", loc); + return null; + } + + return e; + } + + public override void Emit (EmitContext ec) + { + Label end_label = ec.DefineLabel (); + + if (unwrap != null) { + Label is_null_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + left.Emit (ec); + ec.Emit (OpCodes.Br, end_label); + + ec.MarkLabel (is_null_label); + right.Emit (ec); + + ec.MarkLabel (end_label); + return; + } + + left.Emit (ec); + ec.Emit (OpCodes.Dup); + + // Only to make verifier happy + if (left.Type.IsGenericParameter) + ec.Emit (OpCodes.Box, left.Type); + + ec.Emit (OpCodes.Brtrue, end_label); + + ec.Emit (OpCodes.Pop); + right.Emit (ec); + + ec.MarkLabel (end_label); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + NullCoalescingOperator target = (NullCoalescingOperator) t; + + target.left = left.Clone (clonectx); + target.right = right.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class LiftedUnaryMutator : ExpressionStatement + { + public readonly UnaryMutator.Mode Mode; + Expression expr; + UnaryMutator underlying; + Unwrap unwrap; + + public LiftedUnaryMutator (UnaryMutator.Mode mode, Expression expr, Location loc) + { + this.expr = expr; + this.Mode = mode; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return new SimpleAssign (this, this).CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + unwrap = Unwrap.Create (expr, false); + if (unwrap == null) + return null; + + underlying = (UnaryMutator) new UnaryMutator (Mode, unwrap, loc).Resolve (ec); + if (underlying == null) + return null; + + + eclass = ExprClass.Value; + type = expr.Type; + return this; + } + + void DoEmit (EmitContext ec, bool is_expr) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + if (is_expr) { + underlying.Emit (ec); + ec.Emit (OpCodes.Br_S, end_label); + } else { + underlying.EmitStatement (ec); + } + + ec.MarkLabel (is_null_label); + if (is_expr) + LiftedNull.Create (type, loc).Emit (ec); + + ec.MarkLabel (end_label); + } + + public override void Emit (EmitContext ec) + { + DoEmit (ec, true); + } + + public override void EmitStatement (EmitContext ec) + { + DoEmit (ec, false); + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs new file mode 100644 index 0000000000..784cece95b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs @@ -0,0 +1,1024 @@ +// +// outline -- support for rendering in monop +// Some code stolen from updater.cs in monodoc. +// +// Authors: +// Ben Maurer (bmaurer@users.sourceforge.net) +// +// (C) 2004 Ben Maurer +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using System.Collections; +using System.CodeDom.Compiler; +using System.IO; +using System.Text; + +namespace Mono.CSharp { +public class Outline { + + bool declared_only; + bool show_private; + bool filter_obsolete; + + IndentedTextWriter o; + Type t; + + public Outline (Type t, TextWriter output, bool declared_only, bool show_private, bool filter_obsolete) + { + this.t = t; + this.o = new IndentedTextWriter (output, "\t"); + this.declared_only = declared_only; + this.show_private = show_private; + this.filter_obsolete = filter_obsolete; + } + + public void OutlineType () + { + bool first; + + OutlineAttributes (); + o.Write (GetTypeVisibility (t)); + + if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) { + if (t.IsSealed) + o.Write (t.IsAbstract ? " static" : " sealed"); + else if (t.IsAbstract) + o.Write (" abstract"); + } + + o.Write (" "); + o.Write (GetTypeKind (t)); + o.Write (" "); + + Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, declared_only)); + Type parent = t.BaseType; + + if (t.IsSubclassOf (typeof (System.MulticastDelegate))) { + MethodInfo method; + + method = t.GetMethod ("Invoke"); + + o.Write (FormatType (method.ReturnType)); + o.Write (" "); + o.Write (GetTypeName (t)); + o.Write (" ("); + OutlineParams (method.GetParameters ()); + o.Write (")"); + +#if NET_2_0 + WriteGenericConstraints (t.GetGenericArguments ()); +#endif + + o.WriteLine (";"); + return; + } + + o.Write (GetTypeName (t)); + if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) { + first = true; + o.Write (" : "); + + if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) { + o.Write (FormatType (parent)); + first = false; + } + + foreach (Type intf in interfaces) { + if (!first) o.Write (", "); + first = false; + + o.Write (FormatType (intf)); + } + } + + if (t.IsEnum) { + Type underlyingType = System.Enum.GetUnderlyingType (t); + if (underlyingType != typeof (int)) + o.Write (" : {0}", FormatType (underlyingType)); + } +#if NET_2_0 + WriteGenericConstraints (t.GetGenericArguments ()); +#endif + o.WriteLine (" {"); + o.Indent++; + + if (t.IsEnum) { + bool is_first = true; + foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) { + + if (! is_first) + o.WriteLine (","); + is_first = false; + o.Write (fi.Name); + } + o.WriteLine (); + o.Indent--; o.WriteLine ("}"); + return; + } + + first = true; + + foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) { + + if (! ShowMember (ci)) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineConstructor (ci); + + o.WriteLine (); + } + + + first = true; + + foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) { + + if (! ShowMember (m)) + continue; + + if ((m.Attributes & MethodAttributes.SpecialName) != 0) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineMethod (m); + + o.WriteLine (); + } + + first = true; + + foreach (MethodInfo m in t.GetMethods (DefaultFlags)) { + + if (! ShowMember (m)) + continue; + + if ((m.Attributes & MethodAttributes.SpecialName) == 0) + continue; + if (!(m.Name.StartsWith ("op_"))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineOperator (m); + + o.WriteLine (); + } + + first = true; + + foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) { + + if (! ((pi.CanRead && ShowMember (pi.GetGetMethod (true))) || + (pi.CanWrite && ShowMember (pi.GetSetMethod (true))))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineProperty (pi); + + o.WriteLine (); + } + + first = true; + + foreach (FieldInfo fi in t.GetFields (DefaultFlags)) { + + if (! ShowMember (fi)) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineField (fi); + + o.WriteLine (); + } + + first = true; + + foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) { + + if (! ShowMember (ei.GetAddMethod (true))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineEvent (ei); + + o.WriteLine (); + } + + first = true; + + foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) { + + if (! ShowMember (ntype)) + continue; + + if (first) + o.WriteLine (); + first = false; + + new Outline (ntype, o, declared_only, show_private, filter_obsolete).OutlineType (); + } + + o.Indent--; o.WriteLine ("}"); + } + + BindingFlags DefaultFlags { + get { + BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + + if (declared_only) + f |= BindingFlags.DeclaredOnly; + + return f; + } + } + + // FIXME: add other interesting attributes? + void OutlineAttributes () + { + if (t.IsSerializable) + o.WriteLine ("[Serializable]"); + + if (t.IsDefined (typeof (System.FlagsAttribute), true)) + o.WriteLine ("[Flags]"); + + if (t.IsDefined (typeof (System.ObsoleteAttribute), true)) + o.WriteLine ("[Obsolete]"); + } + + void OutlineEvent (EventInfo ei) + { + MethodBase accessor = ei.GetAddMethod (true); + + o.Write (GetMethodVisibility (accessor)); + o.Write ("event "); + o.Write (FormatType (ei.EventHandlerType)); + o.Write (" "); + o.Write (ei.Name); + o.Write (";"); + } + + void OutlineConstructor (ConstructorInfo ci) + { + o.Write (GetMethodVisibility (ci)); + o.Write (RemoveGenericArity (t.Name)); + o.Write (" ("); + OutlineParams (ci.GetParameters ()); + o.Write (");"); + } + + + void OutlineProperty (PropertyInfo pi) + { + ParameterInfo [] idxp = pi.GetIndexParameters (); + MethodBase g = pi.GetGetMethod (true); + MethodBase s = pi.GetSetMethod (true); + MethodBase accessor = g != null ? g : s; + + if (pi.CanRead && pi.CanWrite) { + + + // Get the more accessible accessor + if ((g.Attributes & MethodAttributes.MemberAccessMask) != + (s.Attributes & MethodAttributes.MemberAccessMask)) { + + if (g.IsPublic) accessor = g; + else if (s.IsPublic) accessor = s; + else if (g.IsFamilyOrAssembly) accessor = g; + else if (s.IsFamilyOrAssembly) accessor = s; + else if (g.IsAssembly || g.IsFamily) accessor = g; + else if (s.IsAssembly || s.IsFamily) accessor = s; + } + } + + o.Write (GetMethodVisibility (accessor)); + o.Write (GetMethodModifiers (accessor)); + o.Write (FormatType (pi.PropertyType)); + o.Write (" "); + + if (idxp.Length == 0) + o.Write (pi.Name); + else { + o.Write ("this ["); + OutlineParams (idxp); + o.Write ("]"); + } + + o.WriteLine (" {"); + o.Indent ++; + + if (g != null && ShowMember (g)) { + if ((g.Attributes & MethodAttributes.MemberAccessMask) != + (accessor.Attributes & MethodAttributes.MemberAccessMask)) + o.Write (GetMethodVisibility (g)); + o.WriteLine ("get;"); + } + + if (s != null && ShowMember (s)) { + if ((s.Attributes & MethodAttributes.MemberAccessMask) != + (accessor.Attributes & MethodAttributes.MemberAccessMask)) + o.Write (GetMethodVisibility (s)); + o.WriteLine ("set;"); + } + + o.Indent --; + o.Write ("}"); + } + + void OutlineMethod (MethodInfo mi) + { + if (MethodIsExplicitIfaceImpl (mi)) { + o.Write (FormatType (mi.ReturnType)); + o.Write (" "); + // MSFT has no way to get the method that we are overriding + // from the interface. this would allow us to pretty print + // the type name (and be more correct if there compiler + // were to do some strange naming thing). + } else { + o.Write (GetMethodVisibility (mi)); + o.Write (GetMethodModifiers (mi)); + o.Write (FormatType (mi.ReturnType)); + o.Write (" "); + } + + o.Write (mi.Name); +#if NET_2_0 + o.Write (FormatGenericParams (mi.GetGenericArguments ())); +#endif + o.Write (" ("); + OutlineParams (mi.GetParameters ()); + o.Write (")"); +#if NET_2_0 + WriteGenericConstraints (mi.GetGenericArguments ()); +#endif + o.Write (";"); + } + + void OutlineOperator (MethodInfo mi) + { + o.Write (GetMethodVisibility (mi)); + o.Write (GetMethodModifiers (mi)); + if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") { + o.Write (mi.Name.Substring (3).ToLower ()); + o.Write (" operator "); + o.Write (FormatType (mi.ReturnType)); + } else { + o.Write (FormatType (mi.ReturnType)); + o.Write (" operator "); + o.Write (OperatorFromName (mi.Name)); + } + o.Write (" ("); + OutlineParams (mi.GetParameters ()); + o.Write (");"); + } + + void OutlineParams (ParameterInfo [] pi) + { + int i = 0; + foreach (ParameterInfo p in pi) { + if (p.ParameterType.IsByRef) { + o.Write (p.IsOut ? "out " : "ref "); + o.Write (FormatType (p.ParameterType.GetElementType ())); + } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) { + o.Write ("params "); + o.Write (FormatType (p.ParameterType)); + } else { + o.Write (FormatType (p.ParameterType)); + } + + o.Write (" "); + o.Write (p.Name); + if (i + 1 < pi.Length) + o.Write (", "); + i++; + } + } + + void OutlineField (FieldInfo fi) + { + if (fi.IsPublic) o.Write ("public "); + if (fi.IsFamily) o.Write ("protected "); + if (fi.IsPrivate) o.Write ("private "); + if (fi.IsAssembly) o.Write ("internal "); + if (fi.IsLiteral) o.Write ("const "); + else if (fi.IsStatic) o.Write ("static "); + if (fi.IsInitOnly) o.Write ("readonly "); + + o.Write (FormatType (fi.FieldType)); + o.Write (" "); + o.Write (fi.Name); + if (fi.IsLiteral) { + object v = fi.GetValue (this); + + // TODO: Escape values here + o.Write (" = "); + if (v is char) + o.Write ("'{0}'", v); + else if (v is string) + o.Write ("\"{0}\"", v); + else + o.Write (fi.GetValue (this)); + } + o.Write (";"); + } + + static string GetMethodVisibility (MethodBase m) + { + // itnerfaces have no modifiers here + if (m.DeclaringType.IsInterface) + return ""; + + if (m.IsPublic) return "public "; + if (m.IsFamily) return "protected "; + if (m.IsPrivate) return "private "; + if (m.IsAssembly) return "internal "; + + return null; + } + + static string GetMethodModifiers (MethodBase method) + { + if (method.IsStatic) + return "static "; + + if (method.IsFinal) { + // This will happen if you have + // class X : IA { + // public void A () {} + // static void Main () {} + // } + // interface IA { + // void A (); + // } + // + // A needs to be virtual (the CLR requires + // methods implementing an iface be virtual), + // but can not be inherited. It also can not + // be inherited. In C# this is represented + // with no special modifiers + + if (method.IsVirtual) + return null; + return "sealed "; + } + + // all interface methods are "virtual" but we don't say that in c# + if (method.IsVirtual && !method.DeclaringType.IsInterface) { + if (method.IsAbstract) + return "abstract "; + + return ((method.Attributes & MethodAttributes.NewSlot) != 0) ? + "virtual " : + "override "; + } + + return null; + } + + static string GetTypeKind (Type t) + { + if (t.IsEnum) + return "enum"; + if (t.IsClass) { + if (t.IsSubclassOf (typeof (System.MulticastDelegate))) + return "delegate"; + else + return "class"; + } + if (t.IsInterface) + return "interface"; + if (t.IsValueType) + return "struct"; + return "class"; + } + + static string GetTypeVisibility (Type t) + { + switch (t.Attributes & TypeAttributes.VisibilityMask){ + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + return "public"; + + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamANDAssem: + case TypeAttributes.NestedFamORAssem: + return "protected"; + + default: + return "internal"; + } + } + +#if NET_2_0 + string FormatGenericParams (Type [] args) + { + StringBuilder sb = new StringBuilder (); + if (args.Length == 0) + return ""; + + sb.Append ("<"); + for (int i = 0; i < args.Length; i++) { + if (i > 0) + sb.Append (","); + sb.Append (FormatType (args [i])); + } + sb.Append (">"); + return sb.ToString (); + } +#endif + + // TODO: fine tune this so that our output is less verbose. We need to figure + // out a way to do this while not making things confusing. + string FormatType (Type t) + { + if (t == null) + return ""; + + string type = GetFullName (t); + if (type == null) + return t.ToString (); + + if (!type.StartsWith ("System.")) { + if (t.Namespace == this.t.Namespace) + return t.Name; + return type; + } + + if (t.HasElementType) { + Type et = t.GetElementType (); + if (t.IsArray) + return FormatType (et) + " []"; + if (t.IsPointer) + return FormatType (et) + " *"; + if (t.IsByRef) + return "ref " + FormatType (et); + } + + switch (type) { + case "System.Byte": return "byte"; + case "System.SByte": return "sbyte"; + case "System.Int16": return "short"; + case "System.Int32": return "int"; + case "System.Int64": return "long"; + + case "System.UInt16": return "ushort"; + case "System.UInt32": return "uint"; + case "System.UInt64": return "ulong"; + + case "System.Single": return "float"; + case "System.Double": return "double"; + case "System.Decimal": return "decimal"; + case "System.Boolean": return "bool"; + case "System.Char": return "char"; + case "System.String": return "string"; + + case "System.Object": return "object"; + case "System.Void": return "void"; + } + + if (type.LastIndexOf(".") == 6) + return type.Substring(7); + + // + // If the namespace of the type is the namespace of what + // we are printing (or is a member of one if its children + // don't print it. This basically means that in C# we would + // automatically get the namespace imported by virtue of the + // namespace {} block. + // + if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace) + return type.Substring (t.Namespace.Length + 1); + + return type; + } + + public static string RemoveGenericArity (string name) + { + int start = 0; + StringBuilder sb = new StringBuilder (); + while (start < name.Length) { + int pos = name.IndexOf ('`', start); + if (pos < 0) { + sb.Append (name.Substring (start)); + break; + } + sb.Append (name.Substring (start, pos-start)); + + pos++; + + while ((pos < name.Length) && Char.IsNumber (name [pos])) + pos++; + + start = pos; + } + + return sb.ToString (); + } + + string GetTypeName (Type t) + { + StringBuilder sb = new StringBuilder (); + GetTypeName (sb, t); + return sb.ToString (); + } + + void GetTypeName (StringBuilder sb, Type t) + { + sb.Append (RemoveGenericArity (t.Name)); +#if NET_2_0 + sb.Append (FormatGenericParams (t.GetGenericArguments ())); +#endif + } + + string GetFullName (Type t) + { + StringBuilder sb = new StringBuilder (); + GetFullName_recursed (sb, t, false); + return sb.ToString (); + } + + void GetFullName_recursed (StringBuilder sb, Type t, bool recursed) + { +#if NET_2_0 + if (t.IsGenericParameter) { + sb.Append (t.Name); + return; + } +#endif + + if (t.DeclaringType != null) { + GetFullName_recursed (sb, t.DeclaringType, true); + sb.Append ("."); + } + + if (!recursed) { + string ns = t.Namespace; + if ((ns != null) && (ns != "")) { + sb.Append (ns); + sb.Append ("."); + } + } + + GetTypeName (sb, t); + } + +#if NET_2_0 + void WriteGenericConstraints (Type [] args) + { + + foreach (Type t in args) { + bool first = true; + Type[] ifaces = TypeGetInterfaces (t, true); + + GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + GenericParameterAttributes [] interesting = { + GenericParameterAttributes.ReferenceTypeConstraint, + GenericParameterAttributes.NotNullableValueTypeConstraint, + GenericParameterAttributes.DefaultConstructorConstraint + }; + + if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) { + o.Write (" where "); + o.Write (FormatType (t)); + o.Write (" : "); + } + + if (t.BaseType != typeof (object)) { + o.Write (FormatType (t.BaseType)); + first = false; + } + + foreach (Type iface in ifaces) { + if (!first) + o.Write (", "); + first = false; + + o.Write (FormatType (iface)); + } + + foreach (GenericParameterAttributes a in interesting) { + if ((attrs & a) == 0) + continue; + + if (!first) + o.Write (", "); + first = false; + + switch (a) { + case GenericParameterAttributes.ReferenceTypeConstraint: + o.Write ("class"); + break; + case GenericParameterAttributes.NotNullableValueTypeConstraint: + o.Write ("struct"); + break; + case GenericParameterAttributes.DefaultConstructorConstraint: + o.Write ("new ()"); + break; + } + } + } + } +#endif + + string OperatorFromName (string name) + { + switch (name) { + case "op_UnaryPlus": return "+"; + case "op_UnaryNegation": return "-"; + case "op_LogicalNot": return "!"; + case "op_OnesComplement": return "~"; + case "op_Increment": return "++"; + case "op_Decrement": return "--"; + case "op_True": return "true"; + case "op_False": return "false"; + case "op_Addition": return "+"; + case "op_Subtraction": return "-"; + case "op_Multiply": return "*"; + case "op_Division": return "/"; + case "op_Modulus": return "%"; + case "op_BitwiseAnd": return "&"; + case "op_BitwiseOr": return "|"; + case "op_ExclusiveOr": return "^"; + case "op_LeftShift": return "<<"; + case "op_RightShift": return ">>"; + case "op_Equality": return "=="; + case "op_Inequality": return "!="; + case "op_GreaterThan": return ">"; + case "op_LessThan": return "<"; + case "op_GreaterThanOrEqual": return ">="; + case "op_LessThanOrEqual": return "<="; + default: return name; + } + } + + bool MethodIsExplicitIfaceImpl (MethodBase mb) + { + if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate)) + return false; + + // UGH msft has no way to get the info about what method is + // getting overriden. Another reason to use cecil :-) + // + //MethodInfo mi = mb as MethodInfo; + //if (mi == null) + // return false; + // + //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType); + //return mi.GetBaseDefinition ().DeclaringType.IsInterface; + + // So, we guess that virtual final private methods only come + // from ifaces :-) + return true; + } + + bool ShowMember (MemberInfo mi) + { + if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic) + return false; + + if (show_private) + return true; + + if (filter_obsolete && mi.IsDefined (typeof (ObsoleteAttribute), false)) + return false; + + switch (mi.MemberType) { + case MemberTypes.Constructor: + case MemberTypes.Method: + MethodBase mb = mi as MethodBase; + + if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly) + return true; + + if (MethodIsExplicitIfaceImpl (mb)) + return true; + + return false; + + + case MemberTypes.Field: + FieldInfo fi = mi as FieldInfo; + + if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly) + return true; + + return false; + + + case MemberTypes.NestedType: + case MemberTypes.TypeInfo: + Type t = mi as Type; + + switch (t.Attributes & TypeAttributes.VisibilityMask){ + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamORAssem: + return true; + } + + return false; + } + + // What am I !!! + return true; + } + + static Type [] TypeGetInterfaces (Type t, bool declonly) + { + if (t.IsGenericParameter) + return new Type [0]; + + Type [] ifaces = t.GetInterfaces (); + if (! declonly) + return ifaces; + + // Handle Object. Also, optimize for no interfaces + if (t.BaseType == null || ifaces.Length == 0) + return ifaces; + + ArrayList ar = new ArrayList (); + + foreach (Type i in ifaces) + if (! i.IsAssignableFrom (t.BaseType)) + ar.Add (i); + + return (Type []) ar.ToArray (typeof (Type)); + } +} + +public class Comparer : IComparer { + delegate int ComparerFunc (object a, object b); + + ComparerFunc cmp; + + Comparer (ComparerFunc f) + { + this.cmp = f; + } + + public int Compare (object a, object b) + { + return cmp (a, b); + } + + static int CompareType (object a, object b) + { + Type type1 = (Type) a; + Type type2 = (Type) b; + + if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate))) + return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1; + return string.Compare (type1.Name, type2.Name); + + } + +// static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType)); + +// static Type [] Sort (Type [] types) +// { +// Array.Sort (types, TypeComparer); +// return types; +// } + + static int CompareMemberInfo (object a, object b) + { + return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name); + } + + static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo)); + + public static MemberInfo [] Sort (MemberInfo [] inf) + { + Array.Sort (inf, MemberInfoComparer); + return inf; + } + + static int CompareMethodBase (object a, object b) + { + MethodBase aa = (MethodBase) a, bb = (MethodBase) b; + + if (aa.IsStatic == bb.IsStatic) { + int c = CompareMemberInfo (a, b); + if (c != 0) + return c; + ParameterInfo [] ap, bp; + + // + // Sort overloads by the names of their types + // put methods with fewer params first. + // + + ap = aa.GetParameters (); + bp = bb.GetParameters (); + int n = System.Math.Min (ap.Length, bp.Length); + + for (int i = 0; i < n; i ++) + if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0) + return c; + + return ap.Length.CompareTo (bp.Length); + } + if (aa.IsStatic) + return -1; + + return 1; + } + + static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase)); + + public static MethodBase [] Sort (MethodBase [] inf) + { + Array.Sort (inf, MethodBaseComparer); + return inf; + } + + static int ComparePropertyInfo (object a, object b) + { + PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b; + + bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic; + bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic; + + if (astatic == bstatic) + return CompareMemberInfo (a, b); + + if (astatic) + return -1; + + return 1; + } + + static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo)); + + public static PropertyInfo [] Sort (PropertyInfo [] inf) + { + Array.Sort (inf, PropertyInfoComparer); + return inf; + } + + static int CompareEventInfo (object a, object b) + { + EventInfo aa = (EventInfo) a, bb = (EventInfo) b; + + bool astatic = aa.GetAddMethod (true).IsStatic; + bool bstatic = bb.GetAddMethod (true).IsStatic; + + if (astatic == bstatic) + return CompareMemberInfo (a, b); + + if (astatic) + return -1; + + return 1; + } + + static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo)); + + public static EventInfo [] Sort (EventInfo [] inf) + { + Array.Sort (inf, EventInfoComparer); + return inf; + } +} +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs new file mode 100644 index 0000000000..c36699f93c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs @@ -0,0 +1,1306 @@ +// +// parameter.cs: Parameter definition. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// +// +using System; +using System.Text; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Abstract Base class for parameters of a method. + /// + public abstract class ParameterBase : Attributable + { + protected ParameterBuilder builder; + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { +#if false + if (a.Type == pa.MarshalAs) { + UnmanagedMarshal marshal = a.GetMarshal (this); + if (marshal != null) { + builder.SetMarshal (marshal); + } + return; + } +#endif + if (a.HasSecurityAttribute) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public ParameterBuilder Builder { + get { + return builder; + } + } + + public override bool IsClsComplianceRequired() + { + return false; + } + } + + /// + /// Class for applying custom attributes on the return type + /// + public class ReturnParameter : ParameterBase + { + MemberCore method; + + // TODO: merge method and mb + public ReturnParameter (MemberCore method, MethodBuilder mb, Location location) + { + this.method = method; + try { + builder = mb.DefineParameter (0, ParameterAttributes.None, ""); + } + catch (ArgumentOutOfRangeException) { + method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type"); + } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.CLSCompliant) { + method.Compiler.Report.Warning (3023, 1, a.Location, + "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead"); + } + + // This occurs after Warning -28 + if (builder == null) + return; + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.ReturnValue; + } + } + + /// + /// Is never called + /// + public override string[] ValidAttributeTargets { + get { + return null; + } + } + } + + public class ImplicitLambdaParameter : Parameter + { + public ImplicitLambdaParameter (string name, Location loc) + : base (null, name, Modifier.NONE, null, loc) + { + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + if (parameter_type == null) + throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set", + Name); + + base.idx = index; + return parameter_type; + } + + public void SetParameterType (TypeSpec type) + { + parameter_type = type; + } + } + + public class ParamsParameter : Parameter { + public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc): + base (type, name, Parameter.Modifier.PARAMS, attrs, loc) + { + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + if (base.Resolve (ec, index) == null) + return null; + + var ac = parameter_type as ArrayContainer; + if (ac == null || ac.Rank != 1) { + ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array"); + return null; + } + + return parameter_type; + } + + public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + base.ApplyAttributes (mb, cb, index, pa); + pa.ParamArray.EmitAttribute (builder); + } + } + + public class ArglistParameter : Parameter { + // Doesn't have proper type because it's never chosen for better conversion + public ArglistParameter (Location loc) : + base (null, String.Empty, Parameter.Modifier.NONE, null, loc) + { + parameter_type = InternalType.Arglist; + } + + public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + // Nothing to do + } + + public override bool CheckAccessibility (InterfaceMemberBase member) + { + return true; + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + return parameter_type; + } + } + + public interface IParameterData + { + Expression DefaultValue { get; } + bool HasExtensionMethodModifier { get; } + bool HasDefaultValue { get; } + Parameter.Modifier ModFlags { get; } + string Name { get; } + } + + // + // Parameter information created by parser + // + public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable + { + [Flags] + public enum Modifier : byte { + NONE = 0, + REF = REFMASK | ISBYREF, + OUT = OUTMASK | ISBYREF, + PARAMS = 4, + // This is a flag which says that it's either REF or OUT. + ISBYREF = 8, + REFMASK = 32, + OUTMASK = 64, + SignatureMask = REFMASK | OUTMASK, + This = 128 + } + + static readonly string[] attribute_targets = new string[] { "param" }; + + FullNamedExpression texpr; + readonly Modifier modFlags; + string name; + Expression default_expr; + protected TypeSpec parameter_type; + readonly Location loc; + protected int idx; + public bool HasAddressTaken; + + TemporaryVariableReference expr_tree_variable; + + HoistedVariable hoisted_variant; + + public Modifier ParameterModifier { get { return modFlags; }} + public Expression DefaultExpression { get { return default_expr; }} + + public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc) + { + this.name = name; + modFlags = mod; + this.loc = loc; + texpr = type; + + // Only assign, attributes will be attached during resolve + base.attributes = attrs; + } + + #region Properties + + public DefaultParameterValueExpression DefaultValue { + get { + return default_expr as DefaultParameterValueExpression; + } + set { + default_expr = value; + } + } + + Expression IParameterData.DefaultValue { + get { + var expr = default_expr as DefaultParameterValueExpression; + return expr == null ? default_expr : expr.Child; + } + } + + bool HasOptionalExpression { + get { + return default_expr is DefaultParameterValueExpression; + } + } + + public Location Location { + get { + return loc; + } + } + + public TypeSpec Type { + get { + return parameter_type; + } + set { + parameter_type = value; + } + } + + public FullNamedExpression TypeExpression { + get { + return texpr; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.In && ModFlags == Modifier.OUT) { + a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute"); + return; + } + + if (a.Type == pa.ParamArray) { + a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead"); + return; + } + + if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF && + !OptAttributes.Contains (pa.In)) { + a.Report.Error (662, a.Location, + "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither"); + return; + } + + if (a.Type == pa.CLSCompliant) { + a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead"); + } + + if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) { + if (HasOptionalExpression) { + a.Report.Error (1745, a.Location, + "Cannot specify `{0}' attribute on optional parameter `{1}'", + TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name); + } + + if (a.Type == pa.DefaultParameterValue) + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public virtual bool CheckAccessibility (InterfaceMemberBase member) + { + if (parameter_type == null) + return true; + + return member.IsAccessibleAs (parameter_type); + } + + // + // Resolve is used in method definitions + // + public virtual TypeSpec Resolve (IMemberContext rc, int index) + { + if (parameter_type != null) + return parameter_type; + + if (attributes != null) + attributes.AttachTo (this, rc); + + parameter_type = texpr.ResolveAsType (rc); + if (parameter_type == null) + return null; + + this.idx = index; + + if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) { + rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", + GetSignatureForError ()); + return null; + } + + TypeManager.CheckTypeVariance (parameter_type, + (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, + rc); + + if (parameter_type.IsStatic) { + rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters", + texpr.GetSignatureForError ()); + return parameter_type; + } + + if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) { + rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'", + TypeManager.CSharpName (parameter_type)); + } + + return parameter_type; + } + + public void ResolveDefaultValue (ResolveContext rc) + { + // + // Default value was specified using an expression + // + if (default_expr != null) { + ((DefaultParameterValueExpression)default_expr).Resolve (rc, this); + return; + } + + if (attributes == null) + return; + + var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter); + var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue); + if (def_attr != null) { + if (def_attr.Resolve () == null) + return; + + var default_expr_attr = def_attr.GetParameterDefaultValue (); + if (default_expr_attr == null) + return; + + var dpa_rc = def_attr.CreateResolveContext (); + default_expr = default_expr_attr.Resolve (dpa_rc); + + if (default_expr is BoxedCast) + default_expr = ((BoxedCast) default_expr).Child; + + Constant c = default_expr as Constant; + if (c == null) { + if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + rc.Report.Error (1910, default_expr.Location, + "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute", + default_expr.Type.GetSignatureForError ()); + } else { + rc.Report.Error (1909, default_expr.Location, + "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'", + default_expr.Type.GetSignatureForError ()); ; + } + + default_expr = null; + return; + } + + if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) || + (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) || + parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + return; + } + + // + // LAMESPEC: Some really weird csc behaviour which we have to mimic + // User operators returning same type as parameter type are considered + // valid for this attribute only + // + // struct S { public static implicit operator S (int i) {} } + // + // void M ([DefaultParameterValue (3)]S s) + // + var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc); + if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) { + return; + } + + rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter"); + return; + } + + if (opt_attr != null) { + default_expr = EmptyExpression.MissingValue; + } + } + + public bool HasDefaultValue { + get { return default_expr != null; } + } + + public bool HasExtensionMethodModifier { + get { return (modFlags & Modifier.This) != 0; } + } + + // + // Hoisted parameter variant + // + public HoistedVariable HoistedVariant { + get { + return hoisted_variant; + } + set { + hoisted_variant = value; + } + } + + public Modifier ModFlags { + get { return modFlags & ~Modifier.This; } + } + + public string Name { + get { return name; } + set { name = value; } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Parameter; + } + } + + public void Error_DuplicateName (Report r) + { + r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name); + } + + public virtual string GetSignatureForError () + { + string type_name; + if (parameter_type != null) + type_name = TypeManager.CSharpName (parameter_type); + else + type_name = texpr.GetSignatureForError (); + + string mod = GetModifierSignature (modFlags); + if (mod.Length > 0) + return String.Concat (mod, " ", type_name); + + return type_name; + } + + public static string GetModifierSignature (Modifier mod) + { + switch (mod) { + case Modifier.OUT: + return "out"; + case Modifier.PARAMS: + return "params"; + case Modifier.REF: + return "ref"; + case Modifier.This: + return "this"; + default: + return ""; + } + } + + public void IsClsCompliant (IMemberContext ctx) + { + if (parameter_type.IsCLSCompliant ()) + return; + + ctx.Module.Compiler.Report.Warning (3001, 1, Location, + "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ()); + } + + public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + if (builder != null) + throw new InternalErrorException ("builder already exists"); + + var pattrs = ParametersCompiled.GetParameterAttribute (modFlags); + if (HasOptionalExpression) + pattrs |= ParameterAttributes.Optional; + + if (mb == null) + builder = cb.DefineParameter (index, pattrs, Name); + else + builder = mb.DefineParameter (index, pattrs, Name); + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (HasDefaultValue) { + // + // Emit constant values for true constants only, the other + // constant-like expressions will rely on default value expression + // + var def_value = DefaultValue; + Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant; + if (c != null) { + if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location); + } else { + builder.SetConstant (c.GetValue ()); + } + } else if (default_expr.Type.IsStruct) { + // + // Handles special case where default expression is used with value-type + // + // void Foo (S s = default (S)) {} + // + builder.SetConstant (null); + } + } + + if (parameter_type != null) { + if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + pa.Dynamic.EmitAttribute (builder); + } else if (parameter_type.HasDynamicElement) { + pa.Dynamic.EmitAttribute (builder, parameter_type, Location); + } + } + } + + public Parameter Clone () + { + Parameter p = (Parameter) MemberwiseClone (); + if (attributes != null) + p.attributes = attributes.Clone (); + + return p; + } + + public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec) + { + if ((modFlags & Modifier.ISBYREF) != 0) + ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); + + expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); + expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec); + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (new TypeOf (parameter_type, Location))); + arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location))); + return new SimpleAssign (ExpressionTreeVariableReference (), + Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location)); + } + + public void Emit (EmitContext ec) + { + int arg_idx = idx; + if (!ec.IsStatic) + arg_idx++; + + ParameterReference.EmitLdArg (ec, arg_idx); + } + + public void EmitAssign (EmitContext ec) + { + int arg_idx = idx; + if (!ec.IsStatic) + arg_idx++; + + if (arg_idx <= 255) + ec.Emit (OpCodes.Starg_S, (byte) arg_idx); + else + ec.Emit (OpCodes.Starg, arg_idx); + } + + public void EmitAddressOf (EmitContext ec) + { + int arg_idx = idx; + + if (!ec.IsStatic) + arg_idx++; + + bool is_ref = (ModFlags & Modifier.ISBYREF) != 0; + if (is_ref) { + ParameterReference.EmitLdArg (ec, arg_idx); + } else { + if (arg_idx <= 255) + ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx); + else + ec.Emit (OpCodes.Ldarga, arg_idx); + } + } + + public TemporaryVariableReference ExpressionTreeVariableReference () + { + return expr_tree_variable; + } + + // + // System.Linq.Expressions.ParameterExpression type + // + public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location) + { + TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve (); + return new TypeExpression (p_type, location); + } + + public void Warning_UselessOptionalParameter (Report Report) + { + Report.Warning (1066, 1, Location, + "The default value specified for optional parameter `{0}' will never be used", + Name); + } + } + + // + // Imported or resolved parameter information + // + public class ParameterData : IParameterData + { + readonly string name; + readonly Parameter.Modifier modifiers; + readonly Expression default_value; + + public ParameterData (string name, Parameter.Modifier modifiers) + { + this.name = name; + this.modifiers = modifiers; + } + + public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue) + : this (name, modifiers) + { + this.default_value = defaultValue; + } + + #region IParameterData Members + + public Expression DefaultValue { + get { return default_value; } + } + + public bool HasExtensionMethodModifier { + get { return (modifiers & Parameter.Modifier.This) != 0; } + } + + public bool HasDefaultValue { + get { return default_value != null; } + } + + public Parameter.Modifier ModFlags { + get { return modifiers & ~Parameter.Modifier.This; } + } + + public string Name { + get { return name; } + } + + #endregion + } + + public abstract class AParametersCollection + { + protected bool has_arglist; + protected bool has_params; + + // Null object pattern + protected IParameterData [] parameters; + protected TypeSpec [] types; + + public CallingConventions CallingConvention { + get { + return has_arglist ? + CallingConventions.VarArgs : + CallingConventions.Standard; + } + } + + public int Count { + get { return parameters.Length; } + } + + public TypeSpec ExtensionMethodType { + get { + if (Count == 0) + return null; + + return FixedParameters [0].HasExtensionMethodModifier ? + types [0] : null; + } + } + + public IParameterData [] FixedParameters { + get { + return parameters; + } + } + + public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags) + { + return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ? + ParameterAttributes.Out : ParameterAttributes.None; + } + + // Very expensive operation + public MetaType[] GetMetaInfo () + { + MetaType[] types; + if (has_arglist) { + if (Count == 1) + return MetaType.EmptyTypes; + + types = new MetaType[Count - 1]; + } else { + if (Count == 0) + return MetaType.EmptyTypes; + + types = new MetaType[Count]; + } + + for (int i = 0; i < types.Length; ++i) { + types[i] = Types[i].GetMetaInfo (); + + if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0) + continue; + + // TODO MemberCache: Should go to MetaInfo getter + types [i] = types [i].MakeByRefType (); + } + + return types; + } + + // + // Returns the parameter information based on the name + // + public int GetParameterIndexByName (string name) + { + for (int idx = 0; idx < Count; ++idx) { + if (parameters [idx].Name == name) + return idx; + } + + return -1; + } + + public string GetSignatureForDocumentation () + { + if (IsEmpty) + return string.Empty; + + StringBuilder sb = new StringBuilder ("("); + for (int i = 0; i < Count; ++i) { + if (i != 0) + sb.Append (","); + + sb.Append (types [i].GetSignatureForDocumentation ()); + + if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) + sb.Append ("@"); + } + sb.Append (")"); + + return sb.ToString (); + } + + public string GetSignatureForError () + { + return GetSignatureForError ("(", ")", Count); + } + + public string GetSignatureForError (string start, string end, int count) + { + StringBuilder sb = new StringBuilder (start); + for (int i = 0; i < count; ++i) { + if (i != 0) + sb.Append (", "); + sb.Append (ParameterDesc (i)); + } + sb.Append (end); + return sb.ToString (); + } + + public bool HasArglist { + get { return has_arglist; } + } + + public bool HasExtensionMethodType { + get { + if (Count == 0) + return false; + + return FixedParameters [0].HasExtensionMethodModifier; + } + } + + public bool HasParams { + get { return has_params; } + } + + public bool IsEmpty { + get { return parameters.Length == 0; } + } + + public AParametersCollection Inflate (TypeParameterInflator inflator) + { + TypeSpec[] inflated_types = null; + bool default_value = false; + + for (int i = 0; i < Count; ++i) { + var inflated_param = inflator.Inflate (types[i]); + if (inflated_types == null) { + if (inflated_param == types[i]) + continue; + + default_value |= FixedParameters[i] is DefaultValueExpression; + inflated_types = new TypeSpec[types.Length]; + Array.Copy (types, inflated_types, types.Length); + } + + inflated_types[i] = inflated_param; + } + + if (inflated_types == null) + return this; + + var clone = (AParametersCollection) MemberwiseClone (); + clone.types = inflated_types; + if (default_value) { + for (int i = 0; i < Count; ++i) { + var dve = clone.FixedParameters[i] as DefaultValueExpression; + if (dve != null) { + throw new NotImplementedException ("net"); + // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression (); + } + } + } + + return clone; + } + + public string ParameterDesc (int pos) + { + if (types == null || types [pos] == null) + return ((Parameter)FixedParameters [pos]).GetSignatureForError (); + + string type = TypeManager.CSharpName (types [pos]); + if (FixedParameters [pos].HasExtensionMethodModifier) + return "this " + type; + + Parameter.Modifier mod = FixedParameters [pos].ModFlags; + if (mod == 0) + return type; + + return Parameter.GetModifierSignature (mod) + " " + type; + } + + public TypeSpec[] Types { + get { return types; } + set { types = value; } + } + } + + // + // A collection of imported or resolved parameters + // + public class ParametersImported : AParametersCollection + { + public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams) + { + this.parameters = parameters; + this.types = types; + this.has_arglist = hasArglist; + this.has_params = hasParams; + } + + public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams) + { + this.parameters = param; + this.types = types; + this.has_params = hasParams; + } + } + + /// + /// Represents the methods parameters + /// + public class ParametersCompiled : AParametersCollection + { + public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled (); + + // Used by C# 2.0 delegates + public static readonly ParametersCompiled Undefined = new ParametersCompiled (); + + private ParametersCompiled () + { + parameters = new Parameter [0]; + types = TypeSpec.EmptyTypes; + } + + private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types) + { + this.parameters = parameters; + this.types = types; + } + + public ParametersCompiled (params Parameter[] parameters) + { + if (parameters == null || parameters.Length == 0) + throw new ArgumentException ("Use EmptyReadOnlyParameters"); + + this.parameters = parameters; + int count = parameters.Length; + + for (int i = 0; i < count; i++){ + has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0; + } + } + + public ParametersCompiled (Parameter [] parameters, bool has_arglist) : + this (parameters) + { + this.has_arglist = has_arglist; + } + + public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type) + { + return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type }); + } + + public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types) + { + return new ParametersCompiled (parameters, types); + } + + // + // TODO: This does not fit here, it should go to different version of AParametersCollection + // as the underlying type is not Parameter and some methods will fail to cast + // + public static AParametersCollection CreateFullyResolved (params TypeSpec[] types) + { + var pd = new ParameterData [types.Length]; + for (int i = 0; i < pd.Length; ++i) + pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null); + + return new ParametersCompiled (pd, types); + } + + public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc) + { + return new ParametersCompiled ( + new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) }, + null); + } + + public void CheckConstraints (IMemberContext mc) + { + foreach (Parameter p in parameters) { + // + // It's null for compiler generated types or special types like __arglist + // + if (p.TypeExpression != null) + ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location); + } + } + + // + // Returns non-zero value for equal CLS parameter signatures + // + public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b) + { + int res = 0; + + for (int i = 0; i < a.Count; ++i) { + var a_type = a.Types[i]; + var b_type = b.Types[i]; + if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) { + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out)) + res |= 1; + + continue; + } + + var ac_a = a_type as ArrayContainer; + if (ac_a == null) + return 0; + + var ac_b = b_type as ArrayContainer; + if (ac_b == null) + return 0; + + if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) { + res |= 2; + continue; + } + + if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) { + res |= 1; + continue; + } + + return 0; + } + + return res; + } + + public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes) + { + return MergeGenerated (ctx, userParams, checkConflicts, + new Parameter [] { compilerParams }, + new TypeSpec [] { compilerTypes }); + } + + // + // Use this method when you merge compiler generated parameters with user parameters + // + public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes) + { + Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length]; + userParams.FixedParameters.CopyTo(all_params, 0); + + TypeSpec [] all_types; + if (userParams.types != null) { + all_types = new TypeSpec [all_params.Length]; + userParams.Types.CopyTo (all_types, 0); + } else { + all_types = null; + } + + int last_filled = userParams.Count; + int index = 0; + foreach (Parameter p in compilerParams) { + for (int i = 0; i < last_filled; ++i) { + while (p.Name == all_params [i].Name) { + if (checkConflicts && i < userParams.Count) { + ctx.Report.Error (316, userParams[i].Location, + "The parameter name `{0}' conflicts with a compiler generated name", p.Name); + } + p.Name = '_' + p.Name; + } + } + all_params [last_filled] = p; + if (all_types != null) + all_types [last_filled] = compilerTypes [index++]; + ++last_filled; + } + + ParametersCompiled parameters = new ParametersCompiled (all_params, all_types); + parameters.has_params = userParams.has_params; + return parameters; + } + + // + // Parameters checks for members which don't have a block + // + public void CheckParameters (MemberCore member) + { + for (int i = 0; i < parameters.Length; ++i) { + var name = parameters[i].Name; + for (int ii = i + 1; ii < parameters.Length; ++ii) { + if (parameters[ii].Name == name) + this[ii].Error_DuplicateName (member.Compiler.Report); + } + } + } + + public bool Resolve (IMemberContext ec) + { + if (types != null) + return true; + + types = new TypeSpec [Count]; + + bool ok = true; + Parameter p; + for (int i = 0; i < FixedParameters.Length; ++i) { + p = this [i]; + TypeSpec t = p.Resolve (ec, i); + if (t == null) { + ok = false; + continue; + } + + types [i] = t; + } + + return ok; + } + + public void ResolveDefaultValues (MemberCore m) + { + ResolveContext rc = null; + for (int i = 0; i < parameters.Length; ++i) { + Parameter p = (Parameter) parameters [i]; + + // + // Try not to enter default values resolution if there are is not any default value possible + // + if (p.HasDefaultValue || p.OptAttributes != null) { + if (rc == null) + rc = new ResolveContext (m); + + p.ResolveDefaultValue (rc); + } + } + } + + // Define each type attribute (in/out/ref) and + // the argument names. + public void ApplyAttributes (IMemberContext mc, MethodBase builder) + { + if (Count == 0) + return; + + MethodBuilder mb = builder as MethodBuilder; + ConstructorBuilder cb = builder as ConstructorBuilder; + var pa = mc.Module.PredefinedAttributes; + + for (int i = 0; i < Count; i++) { + this [i].ApplyAttributes (mb, cb, i + 1, pa); + } + } + + public void VerifyClsCompliance (IMemberContext ctx) + { + foreach (Parameter p in FixedParameters) + p.IsClsCompliant (ctx); + } + + public Parameter this [int pos] { + get { return (Parameter) parameters [pos]; } + } + + public Expression CreateExpressionTree (BlockContext ec, Location loc) + { + var initializers = new ArrayInitializer (Count, loc); + foreach (Parameter p in FixedParameters) { + // + // Each parameter expression is stored to local variable + // to save some memory when referenced later. + // + StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec)); + if (se.Resolve (ec)) { + ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ())); + ec.CurrentBlock.AddScopeStatement (se); + } + + initializers.Add (p.ExpressionTreeVariableReference ()); + } + + return new ArrayCreation ( + Parameter.ResolveParameterExpressionType (ec, loc), + initializers, loc); + } + + public ParametersCompiled Clone () + { + ParametersCompiled p = (ParametersCompiled) MemberwiseClone (); + + p.parameters = new IParameterData [parameters.Length]; + for (int i = 0; i < Count; ++i) + p.parameters [i] = this [i].Clone (); + + return p; + } + } + + // + // Default parameter value expression. We need this wrapper to handle + // default parameter values of folded constants when for indexer parameters + // The expression is resolved only once but applied to two methods which + // both share reference to this expression and we ensure that resolving + // this expression always returns same instance + // + public class DefaultParameterValueExpression : CompositeExpression + { + public DefaultParameterValueExpression (Expression expr) + : base (expr) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + return base.DoResolve (rc); + } + + public void Resolve (ResolveContext rc, Parameter p) + { + var expr = Resolve (rc); + if (expr == null) + return; + + expr = Child; + + if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) { + rc.Report.Error (1736, Location, + "The expression being assigned to optional parameter `{0}' must be a constant or default value", + p.Name); + + return; + } + + var parameter_type = p.Type; + if (type == parameter_type) + return; + + var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location); + if (res != null) { + if (parameter_type.IsNullableType && res is Nullable.Wrap) { + Nullable.Wrap wrap = (Nullable.Wrap) res; + res = wrap.Child; + if (!(res is Constant)) { + rc.Report.Error (1770, Location, + "The expression being assigned to nullable optional parameter `{0}' must be default value", + p.Name); + return; + } + } + + if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) { + rc.Report.Error (1763, Location, + "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", + p.Name, parameter_type.GetSignatureForError ()); + + return; + } + + this.expr = res; + return; + } + + rc.Report.Error (1750, Location, + "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'", + type.GetSignatureForError (), parameter_type.GetSignatureForError ()); + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs new file mode 100644 index 0000000000..696797aa01 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs @@ -0,0 +1,641 @@ +// +// pending.cs: Pending method implementation +// +// Authors: +// Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + struct TypeAndMethods { + public TypeSpec type; + public IList methods; + + // + // Whether it is optional, this is used to allow the explicit/implicit + // implementation when a base class already implements an interface. + // + // For example: + // + // class X : IA { } class Y : X, IA { IA.Explicit (); } + // + public bool optional; + + // + // This flag on the method says `We found a match, but + // because it was private, we could not use the match + // + public MethodData [] found; + + // If a method is defined here, then we always need to + // create a proxy for it. This is used when implementing + // an interface's indexer with a different IndexerName. + public MethodSpec [] need_proxy; + } + + public class PendingImplementation + { + /// + /// The container for this PendingImplementation + /// + readonly TypeContainer container; + + /// + /// This is the array of TypeAndMethods that describes the pending implementations + /// (both interfaces and abstract methods in base class) + /// + TypeAndMethods [] pending_implementations; + + PendingImplementation (TypeContainer container, MissingInterfacesInfo[] missing_ifaces, MethodSpec[] abstract_methods, int total) + { + var type_builder = container.Definition; + + this.container = container; + pending_implementations = new TypeAndMethods [total]; + + int i = 0; + if (abstract_methods != null) { + int count = abstract_methods.Length; + pending_implementations [i].methods = new MethodSpec [count]; + pending_implementations [i].need_proxy = new MethodSpec [count]; + + pending_implementations [i].methods = abstract_methods; + pending_implementations [i].found = new MethodData [count]; + pending_implementations [i].type = type_builder; + ++i; + } + + foreach (MissingInterfacesInfo missing in missing_ifaces) { + var iface = missing.Type; + var mi = MemberCache.GetInterfaceMethods (iface); + + int count = mi.Count; + pending_implementations [i].type = iface; + pending_implementations [i].optional = missing.Optional; + pending_implementations [i].methods = mi; + pending_implementations [i].found = new MethodData [count]; + pending_implementations [i].need_proxy = new MethodSpec [count]; + i++; + } + } + + Report Report { + get { + return container.Module.Compiler.Report; + } + } + + struct MissingInterfacesInfo { + public TypeSpec Type; + public bool Optional; + + public MissingInterfacesInfo (TypeSpec t) + { + Type = t; + Optional = false; + } + } + + static readonly MissingInterfacesInfo [] EmptyMissingInterfacesInfo = new MissingInterfacesInfo [0]; + + static MissingInterfacesInfo [] GetMissingInterfaces (TypeContainer container) + { + // + // Notice that Interfaces will only return the interfaces that the Type + // is supposed to implement, not all the interfaces that the type implements. + // + var impl = container.Definition.Interfaces; + + if (impl == null || impl.Count == 0) + return EmptyMissingInterfacesInfo; + + MissingInterfacesInfo[] ret = new MissingInterfacesInfo[impl.Count]; + + for (int i = 0; i < impl.Count; i++) + ret [i] = new MissingInterfacesInfo (impl [i]); + + // we really should not get here because Object doesnt implement any + // interfaces. But it could implement something internal, so we have + // to handle that case. + if (container.BaseType == null) + return ret; + + var base_impls = container.BaseType.Interfaces; + if (base_impls != null) { + foreach (TypeSpec t in base_impls) { + for (int i = 0; i < ret.Length; i++) { + if (t == ret[i].Type) { + ret[i].Optional = true; + break; + } + } + } + } + + return ret; + } + + // + // Factory method: if there are pending implementation methods, we return a PendingImplementation + // object, otherwise we return null. + // + // Register method implementations are either abstract methods + // flagged as such on the base class or interface methods + // + static public PendingImplementation GetPendingImplementations (TypeContainer container) + { + TypeSpec b = container.BaseType; + + var missing_interfaces = GetMissingInterfaces (container); + + // + // If we are implementing an abstract class, and we are not + // ourselves abstract, and there are abstract methods (C# allows + // abstract classes that have no abstract methods), then allocate + // one slot. + // + // We also pre-compute the methods. + // + bool implementing_abstract = ((b != null) && b.IsAbstract && (container.ModFlags & Modifiers.ABSTRACT) == 0); + MethodSpec[] abstract_methods = null; + + if (implementing_abstract){ + var am = MemberCache.GetNotImplementedAbstractMethods (b); + + if (am == null) { + implementing_abstract = false; + } else { + abstract_methods = new MethodSpec[am.Count]; + am.CopyTo (abstract_methods, 0); + } + } + + int total = missing_interfaces.Length + (implementing_abstract ? 1 : 0); + if (total == 0) + return null; + + var pending = new PendingImplementation (container, missing_interfaces, abstract_methods, total); + + // + // check for inherited conflicting methods + // + foreach (var p in pending.pending_implementations) { + // + // It can happen for generic interfaces only + // + if (!p.type.IsGeneric) + continue; + + // + // CLR does not distinguishes between ref and out + // + for (int i = 0; i < p.methods.Count; ++i) { + MethodSpec compared_method = p.methods[i]; + if (compared_method.Parameters.IsEmpty) + continue; + + for (int ii = i + 1; ii < p.methods.Count; ++ii) { + MethodSpec tested_method = p.methods[ii]; + if (compared_method.Name != tested_method.Name) + continue; + + if (p.type != tested_method.DeclaringType) + continue; + + if (!TypeSpecComparer.Override.IsSame (compared_method.Parameters.Types, tested_method.Parameters.Types)) + continue; + + bool exact_match = true; + bool ref_only_difference = false; + var cp = compared_method.Parameters.FixedParameters; + var tp = tested_method.Parameters.FixedParameters; + + for (int pi = 0; pi < cp.Length; ++pi) { + // + // First check exact modifiers match + // + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((cp[pi].ModFlags & ref_out) == (tp[pi].ModFlags & ref_out)) + continue; + + if ((cp[pi].ModFlags & tp[pi].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + ref_only_difference = true; + continue; + } + + exact_match = false; + break; + } + + if (!exact_match || !ref_only_difference) + continue; + + pending.Report.SymbolRelatedToPreviousError (compared_method); + pending.Report.SymbolRelatedToPreviousError (tested_method); + pending.Report.Error (767, container.Location, + "Cannot implement interface `{0}' with the specified type parameters because it causes method `{1}' to differ on parameter modifiers only", + p.type.GetDefinition().GetSignatureForError (), compared_method.GetSignatureForError ()); + + break; + } + } + } + + return pending; + } + + public enum Operation { + // + // If you change this, review the whole InterfaceMethod routine as there + // are a couple of assumptions on these three states + // + Lookup, ClearOne, ClearAll + } + + /// + /// Whether the specified method is an interface method implementation + /// + public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate) + { + return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate); + } + + public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate) + { + InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate); + } + + /// + /// If a method in Type `t' (or null to look in all interfaces + /// and the base abstract class) with name `Name', return type `ret_type' and + /// arguments `args' implements an interface, this method will + /// return the MethodInfo that this method implements. + /// + /// If `name' is null, we operate solely on the method's signature. This is for + /// instance used when implementing indexers. + /// + /// The `Operation op' controls whether to lookup, clear the pending bit, or clear + /// all the methods with the given signature. + /// + /// The `MethodInfo need_proxy' is used when we're implementing an interface's + /// indexer in a class. If the new indexer's IndexerName does not match the one + /// that was used in the interface, then we always need to create a proxy for it. + /// + /// + public MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate) + { + ambiguousCandidate = null; + + if (pending_implementations == null) + return null; + + TypeSpec ret_type = method.method.ReturnType; + ParametersCompiled args = method.method.ParameterInfo; + bool is_indexer = method.method is Indexer.SetIndexerMethod || method.method is Indexer.GetIndexerMethod; + MethodSpec m; + + foreach (TypeAndMethods tm in pending_implementations){ + if (!(iType == null || tm.type == iType)) + continue; + + int method_count = tm.methods.Count; + for (int i = 0; i < method_count; i++){ + m = tm.methods [i]; + + if (m == null) + continue; + + if (is_indexer) { + if (!m.IsAccessor || m.Parameters.IsEmpty) + continue; + } else { + if (name.Name != m.Name) + continue; + + if (m.Arity != name.Arity) + continue; + } + + if (!TypeSpecComparer.Override.IsEqual (m.Parameters, args)) + continue; + + if (!TypeSpecComparer.Override.IsEqual (m.ReturnType, ret_type)) { + tm.found[i] = method; + continue; + } + + // + // `need_proxy' is not null when we're implementing an + // interface indexer and this is Clear(One/All) operation. + // + // If `name' is null, then we do a match solely based on the + // signature and not on the name (this is done in the Lookup + // for an interface indexer). + // + if (op != Operation.Lookup) { + if (m.IsAccessor != method.method.IsAccessor) + continue; + + // If `t != null', then this is an explicitly interface + // implementation and we can always clear the method. + // `need_proxy' is not null if we're implementing an + // interface indexer. In this case, we need to create + // a proxy if the implementation's IndexerName doesn't + // match the IndexerName in the interface. + if (m.DeclaringType.IsInterface && iType == null && name.Name != m.Name) { // TODO: This is very expensive comparison + tm.need_proxy[i] = method.method.Spec; + } else { + tm.methods[i] = null; + } + } else { + tm.found [i] = method; + } + + if (op == Operation.Lookup && name.Left != null && ambiguousCandidate == null) { + ambiguousCandidate = m; + continue; + } + + // + // Lookups and ClearOne return + // + if (op != Operation.ClearAll) + return m; + } + + // If a specific type was requested, we can stop now. + if (tm.type == iType) + break; + } + + m = ambiguousCandidate; + ambiguousCandidate = null; + return m; + } + + /// + /// C# allows this kind of scenarios: + /// interface I { void M (); } + /// class X { public void M (); } + /// class Y : X, I { } + /// + /// For that case, we create an explicit implementation function + /// I.M in Y. + /// + void DefineProxy (TypeSpec iface, MethodSpec base_method, MethodSpec iface_method) + { + // TODO: Handle nested iface names + string proxy_name; + var ns = iface.MemberDefinition.Namespace; + if (string.IsNullOrEmpty (ns)) + proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name; + else + proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name; + + var param = iface_method.Parameters; + + MethodBuilder proxy = container.TypeBuilder.DefineMethod ( + proxy_name, + MethodAttributes.Private | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.CheckAccessOnOverride | + MethodAttributes.Virtual | MethodAttributes.Final, + CallingConventions.Standard | CallingConventions.HasThis, + base_method.ReturnType.GetMetaInfo (), param.GetMetaInfo ()); + + if (iface_method.IsGeneric) { + var gnames = iface_method.GenericDefinition.TypeParameters.Select (l => l.Name).ToArray (); + proxy.DefineGenericParameters (gnames); + } + + for (int i = 0; i < param.Count; i++) { + string name = param.FixedParameters [i].Name; + ParameterAttributes attr = ParametersCompiled.GetParameterAttribute (param.FixedParameters [i].ModFlags); + proxy.DefineParameter (i + 1, attr, name); + } + + int top = param.Count; + var ec = new EmitContext (null, proxy.GetILGenerator (), null); + // TODO: GetAllParametersArguments + for (int i = 0; i <= top; i++) + ParameterReference.EmitLdArg (ec, i); + + ec.Emit (OpCodes.Call, base_method); + ec.Emit (OpCodes.Ret); + + container.TypeBuilder.DefineMethodOverride (proxy, (MethodInfo) iface_method.GetMetaInfo ()); + } + + /// + /// This function tells whether one of our base classes implements + /// the given method (which turns out, it is valid to have an interface + /// implementation in a base + /// + bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method) + { + base_method = null; + var base_type = container.BaseType; + + // + // Setup filter with no return type to give better error message + // about mismatch at return type when the check bellow rejects them + // + var parameters = mi.Parameters; + while (true) { + var candidates = MemberCache.FindMembers (base_type, mi.Name, false); + if (candidates == null) + return false; + + MethodSpec similar_candidate = null; + foreach (var candidate in candidates) { + if (candidate.Kind != MemberKind.Method) + continue; + + if (candidate.Arity != mi.Arity) + continue; + + var candidate_param = ((MethodSpec) candidate).Parameters; + if (!TypeSpecComparer.Override.IsSame (parameters.Types, candidate_param.Types)) + continue; + + bool modifiers_match = true; + for (int i = 0; i < parameters.Count; ++i) { + // + // First check exact ref/out match + // + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out)) + continue; + + modifiers_match = false; + + // + // Different in ref/out only + // + if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + if (similar_candidate == null) { + if (!candidate.IsPublic) + break; + + if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, ((MethodSpec) candidate).ReturnType)) + break; + + // It's used for ref/out ambiguity overload check + similar_candidate = (MethodSpec) candidate; + } + + continue; + } + + similar_candidate = null; + break; + } + + if (!modifiers_match) + continue; + + // + // From this point on the candidate is used for detailed error reporting + // because it's very close match to what we are looking for + // + base_method = (MethodSpec) candidate; + + if (!candidate.IsPublic) + return false; + + if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType)) + return false; + } + + if (base_method != null) { + if (similar_candidate != null) { + Report.SymbolRelatedToPreviousError (similar_candidate); + Report.SymbolRelatedToPreviousError (mi); + Report.SymbolRelatedToPreviousError (container); + Report.Warning (1956, 1, ((MemberCore) base_method.MemberDefinition).Location, + "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'", + mi.GetSignatureForError (), base_method.GetSignatureForError (), similar_candidate.GetSignatureForError (), container.GetSignatureForError ()); + } + + break; + } + + base_type = candidates[0].DeclaringType.BaseType; + if (base_type == null) + return false; + } + + if (!base_method.IsVirtual) { +#if STATIC + var base_builder = base_method.GetMetaInfo () as MethodBuilder; + if (base_builder != null) { + // + // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can + // be done for all methods from compiled assembly + // + base_builder.__SetAttributes (base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); + return true; + } +#endif + DefineProxy (iface_type, base_method, mi); + } + + return true; + } + + /// + /// Verifies that any pending abstract methods or interface methods + /// were implemented. + /// + public bool VerifyPendingMethods () + { + int top = pending_implementations.Length; + bool errors = false; + int i; + + for (i = 0; i < top; i++){ + TypeSpec type = pending_implementations [i].type; + + bool base_implements_type = type.IsInterface && + container.BaseType != null && + container.BaseType.ImplementsInterface (type, false); + + for (int j = 0; j < pending_implementations [i].methods.Count; ++j) { + var mi = pending_implementations[i].methods[j]; + if (mi == null) + continue; + + if (type.IsInterface){ + var need_proxy = + pending_implementations [i].need_proxy [j]; + + if (need_proxy != null) { + DefineProxy (type, need_proxy, mi); + continue; + } + + if (pending_implementations [i].optional) + continue; + + MethodSpec candidate = null; + if (base_implements_type || BaseImplements (type, mi, out candidate)) + continue; + + if (candidate == null) { + MethodData md = pending_implementations [i].found [j]; + if (md != null) + candidate = md.method.Spec; + } + + Report.SymbolRelatedToPreviousError (mi); + if (candidate != null) { + Report.SymbolRelatedToPreviousError (candidate); + if (candidate.IsStatic) { + Report.Error (736, container.Location, + "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is static", + container.GetSignatureForError (), mi.GetSignatureForError (), TypeManager.CSharpSignature (candidate)); + } else if ((candidate.Modifiers & Modifiers.PUBLIC) == 0) { + Report.Error (737, container.Location, + "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' in not public", + container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ()); + } else { + Report.Error (738, container.Location, + "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not match interface member return type `{4}'", + container.GetSignatureForError (), mi.GetSignatureForError (), TypeManager.CSharpSignature (candidate), + TypeManager.CSharpName (candidate.ReturnType), TypeManager.CSharpName (mi.ReturnType)); + } + } else { + Report.Error (535, container.Location, "`{0}' does not implement interface member `{1}'", + container.GetSignatureForError (), mi.GetSignatureForError ()); + } + } else { + Report.SymbolRelatedToPreviousError (mi); + Report.Error (534, container.Location, "`{0}' does not implement inherited abstract member `{1}'", + container.GetSignatureForError (), mi.GetSignatureForError ()); + } + errors = true; + } + } + return errors; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs new file mode 100644 index 0000000000..d5adfccad9 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs @@ -0,0 +1,1675 @@ +// +// property.cs: Property based handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// + +using System; +using System.Collections.Generic; +using System.Text; + +#if NET_2_1 +using XmlElement = System.Object; +#endif + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // It is used as a base class for all property based members + // This includes properties, indexers, and events + public abstract class PropertyBasedMember : InterfaceMemberBase + { + public PropertyBasedMember (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs) + : base (parent, generic, type, mod, allowed_mod, name, attrs) + { + } + + protected void CheckReservedNameConflict (string prefix, MethodSpec accessor) + { + string name; + AParametersCollection parameters; + if (accessor != null) { + name = accessor.Name; + parameters = accessor.Parameters; + } else { + name = prefix + ShortName; + if (IsExplicitImpl) + name = MemberName.Left + "." + name; + + if (this is Indexer) { + parameters = ((Indexer) this).ParameterInfo; + if (prefix[0] == 's') { + var data = new IParameterData[parameters.Count + 1]; + Array.Copy (parameters.FixedParameters, data, data.Length - 1); + data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE); + var types = new TypeSpec[data.Length]; + Array.Copy (parameters.Types, types, data.Length - 1); + types[data.Length - 1] = member_type; + + parameters = new ParametersImported (data, types, false); + } + } else { + if (prefix[0] == 's') + parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type }); + else + parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + } + + var conflict = MemberCache.FindMember (Parent.Definition, + new MemberFilter (name, 0, MemberKind.Method, parameters, null), + BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors); + + if (conflict != null) { + Report.SymbolRelatedToPreviousError (conflict); + Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ()); + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (!MemberType.IsCLSCompliant ()) { + Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + + } + + public class PropertySpec : MemberSpec, IInterfaceMemberSpec + { + PropertyInfo info; + TypeSpec memberType; + MethodSpec set, get; + + public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers) + : base (kind, declaringType, definition, modifiers) + { + this.info = info; + this.memberType = memberType; + } + + #region Properties + + public MethodSpec Get { + get { + return get; + } + set { + get = value; + get.IsAccessor = true; + } + } + + public MethodSpec Set { + get { + return set; + } + set { + set = value; + set.IsAccessor = true; + } + } + + public bool HasDifferentAccessibility { + get { + return HasGet && HasSet && + (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask); + } + } + + public bool HasGet { + get { + return Get != null; + } + } + + public bool HasSet { + get { + return Set != null; + } + } + + public PropertyInfo MetaInfo { + get { + if ((state & StateFlags.PendingMetaInflate) != 0) + throw new NotSupportedException (); + + return info; + } + } + + public TypeSpec MemberType { + get { + return memberType; + } + } + + #endregion + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var ps = (PropertySpec) base.InflateMember (inflator); + ps.memberType = inflator.Inflate (memberType); + return ps; + } + + public override List ResolveMissingDependencies () + { + return memberType.ResolveMissingDependencies (); + } + } + + // + // Properties and Indexers both generate PropertyBuilders, we use this to share + // their common bits. + // + abstract public class PropertyBase : PropertyBasedMember { + + public class GetMethod : PropertyMethod + { + static readonly string[] attribute_targets = new string [] { "method", "return" }; + + internal const string Prefix = "get_"; + + public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc) + : base (method, Prefix, modifiers, attrs, loc) + { + } + + public override MethodBuilder Define (DeclSpace parent) + { + base.Define (parent); + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags); + + method_data = new MethodData (method, ModFlags, flags, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + Spec.SetMetaInfo (method_data.MethodBuilder); + + return method_data.MethodBuilder; + } + + public override TypeSpec ReturnType { + get { + return method.MemberType; + } + } + + public override ParametersCompiled ParameterInfo { + get { + return ParametersCompiled.EmptyReadOnlyParameters; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + public class SetMethod : PropertyMethod { + + static readonly string[] attribute_targets = new string[] { "method", "param", "return" }; + + internal const string Prefix = "set_"; + + protected ParametersCompiled parameters; + + public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (method, Prefix, modifiers, attrs, loc) + { + this.parameters = parameters; + } + + protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Parameter) { + parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + public override MethodBuilder Define (DeclSpace parent) + { + parameters.Resolve (this); + + base.Define (parent); + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags); + + method_data = new MethodData (method, ModFlags, flags, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + Spec.SetMetaInfo (method_data.MethodBuilder); + + return method_data.MethodBuilder; + } + + public override TypeSpec ReturnType { + get { + return Parent.Compiler.BuiltinTypes.Void; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + static readonly string[] attribute_targets = new string[] { "property" }; + + public abstract class PropertyMethod : AbstractPropertyEventMethod + { + const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + protected readonly PropertyBase method; + protected MethodAttributes flags; + + public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + this.method = method; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report); + this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.MethodImpl) { + method.is_external_implementation = a.IsInternalCall (); + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + public override bool IsClsComplianceRequired () + { + return method.IsClsComplianceRequired (); + } + + public virtual MethodBuilder Define (DeclSpace parent) + { + TypeContainer container = parent.PartialContainer; + + // + // Check for custom access modifier + // + if ((ModFlags & Modifiers.AccessibilityMask) == 0) { + ModFlags |= method.ModFlags; + flags = method.flags; + } else { + if (container.Kind == MemberKind.Interface) + Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface", + GetSignatureForError ()); + else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) { + Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ()); + } + + CheckModifiers (ModFlags); + ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask)); + ModFlags |= Modifiers.PROPERTY_CUSTOM; + flags = ModifiersExtensions.MethodAttr (ModFlags); + flags |= (method.flags & (~MethodAttributes.MemberAccessMask)); + } + + CheckAbstractAndExtern (block != null); + CheckProtectedModifier (); + + if (block != null && block.IsIterator) + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + + return null; + } + + public bool HasCustomAccessModifier { + get { + return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0; + } + } + + public PropertyBase Property { + get { + return method; + } + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return method.GetAttributeObsolete (); + } + + public override string GetSignatureForError() + { + return method.GetSignatureForError () + "." + prefix.Substring (0, 3); + } + + void CheckModifiers (Modifiers modflags) + { + if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) { + Report.Error (273, Location, + "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'", + GetSignatureForError (), method.GetSignatureForError ()); + } + } + } + + PropertyMethod get, set, first; + PropertyBuilder PropertyBuilder; + + public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, + Modifiers allowed_mod, MemberName name, Attributes attrs) + : base (parent, null, type, mod_flags, allowed_mod, name, attrs) + { + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Property; + } + } + + public PropertyMethod AccessorFirst { + get { + return first; + } + } + + public PropertyMethod AccessorSecond { + get { + return first == get ? set : get; + } + } + + public override Variance ExpectedMemberTypeVariance { + get { + return (get != null && set != null) ? + Variance.None : set == null ? + Variance.Covariant : + Variance.Contravariant; + } + } + + public PropertyMethod Get { + get { + return get; + } + set { + get = value; + if (first == null) + first = value; + + Parent.AddMember (get); + } + } + + public PropertyMethod Set { + get { + return set; + } + set { + set = value; + if (first == null) + first = value; + + Parent.AddMember (set); + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.HasSecurityAttribute) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get) + { + if (IsExplicitImpl) { + MemberFilter filter; + if (kind == MemberKind.Indexer) + filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null); + else + filter = new MemberFilter (MemberName.Name, 0, kind, null, null); + + var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec; + + if (implementing == null) + return; + + var accessor = get ? implementing.Get : implementing.Set; + if (accessor != null) { + Report.SymbolRelatedToPreviousError (accessor); + Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'", + GetSignatureForError (), accessor.GetSignatureForError ()); + } + } + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + var ok = base.CheckOverrideAgainstBase (base_member); + + // + // Check base property accessors conflict + // + var base_prop = (PropertySpec) base_member; + if (Get != null) { + if (!base_prop.HasGet) { + if (ok) { + Report.SymbolRelatedToPreviousError (base_prop); + Report.Error (545, Get.Location, + "`{0}': cannot override because `{1}' does not have an overridable get accessor", + Get.GetSignatureForError (), base_prop.GetSignatureForError ()); + ok = false; + } + } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) { + if (!CheckAccessModifiers (Get, base_prop.Get)) { + Error_CannotChangeAccessModifiers (Get, base_prop.Get); + ok = false; + } + } + } + + if (Set != null) { + if (!base_prop.HasSet) { + if (ok) { + Report.SymbolRelatedToPreviousError (base_prop); + Report.Error (546, Set.Location, + "`{0}': cannot override because `{1}' does not have an overridable set accessor", + Set.GetSignatureForError (), base_prop.GetSignatureForError ()); + ok = false; + } + } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) { + if (!CheckAccessModifiers (Set, base_prop.Set)) { + Error_CannotChangeAccessModifiers (Set, base_prop.Set); + ok = false; + } + } + } + + if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) { + if (!CheckAccessModifiers (this, base_prop)) { + Error_CannotChangeAccessModifiers (this, base_prop); + ok = false; + } + } + + return ok; + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + IsTypePermitted (); + + if (MemberType.IsStatic) + Error_StaticReturnType (); + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + // + // Accessors modifiers check + // + if (AccessorSecond != null) { + if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) { + Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer", + GetSignatureForError ()); + } + } else if ((ModFlags & Modifiers.OVERRIDE) == 0 && + (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) || + (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) { + Report.Error (276, Location, + "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor", + GetSignatureForError ()); + } + } + + protected bool DefineAccessors () + { + first.Define (Parent); + if (AccessorSecond != null) + AccessorSecond.Define (Parent); + + return true; + } + + protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters) + { + PropertyBuilder = Parent.TypeBuilder.DefineProperty ( + GetFullName (MemberName), PropertyAttributes.None, +#if !BOOTSTRAP_BASIC // Requires trunk version mscorlib + IsStatic ? 0 : CallingConventions.HasThis, +#endif + MemberType.GetMetaInfo (), null, null, + parameters.GetMetaInfo (), null, null); + + PropertySpec spec; + if (kind == MemberKind.Indexer) + spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags); + else + spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags); + + if (Get != null) { + spec.Get = Get.Spec; + + var method = Get.Spec.GetMetaInfo () as MethodBuilder; + if (method != null) { + PropertyBuilder.SetGetMethod (method); + Parent.MemberCache.AddMember (this, method.Name, Get.Spec); + } + } else { + CheckMissingAccessor (kind, parameters, true); + } + + if (Set != null) { + spec.Set = Set.Spec; + + var method = Set.Spec.GetMetaInfo () as MethodBuilder; + if (method != null) { + PropertyBuilder.SetSetMethod (method); + Parent.MemberCache.AddMember (this, method.Name, Set.Spec); + } + } else { + CheckMissingAccessor (kind, parameters, false); + } + + Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec); + } + + public override void Emit () + { + CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec); + CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec); + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder); + } else if (member_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + first.Emit (Parent); + if (AccessorSecond != null) + AccessorSecond.Emit (Parent); + + base.Emit (); + } + + public override bool IsUsed { + get { + if (IsExplicitImpl) + return true; + + return Get.IsUsed | Set.IsUsed; + } + } + + protected override void SetMemberName (MemberName new_name) + { + base.SetMemberName (new_name); + + if (Get != null) + Get.UpdateName (this); + + if (Set != null) + Set.UpdateName (this); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "P:"; } + } + } + + public class Property : PropertyBase + { + public sealed class BackingField : Field + { + readonly Property property; + + public BackingField (Property p) + : base (p.Parent, p.type_expr, + Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), + new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null) + { + this.property = p; + } + + public string OriginalName { + get { + return property.Name; + } + } + + public override string GetSignatureForError () + { + return property.GetSignatureForError (); + } + } + + public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod, + MemberName name, Attributes attrs) + : base (parent, type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct : + AllowedModifiersClass, + name, attrs) + { + } + + void CreateAutomaticProperty () + { + // Create backing field + Field field = new BackingField (this); + if (!field.Define ()) + return; + + Parent.PartialContainer.AddField (field); + + FieldExpr fe = new FieldExpr (field, Location); + if ((field.ModFlags & Modifiers.STATIC) == 0) + fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location); + + // Create get block + Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + Return r = new Return (fe, Location); + Get.Block.AddStatement (r); + + // Create set block + Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location); + Assign a = new SimpleAssign (fe, new SimpleName ("value", Location)); + Set.Block.AddStatement (new StatementExpression (a)); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + + if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 && + AccessorSecond != null && Get.Block == null && Set.Block == null) { + if (Compiler.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties"); + + Get.ModFlags |= Modifiers.COMPILER_GENERATED; + Set.ModFlags |= Modifiers.COMPILER_GENERATED; + CreateAutomaticProperty (); + } + + if (!DefineAccessors ()) + return false; + + if (!CheckBase ()) + return false; + + DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters); + return true; + } + + public override void Emit () + { + if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) { + Report.Error (842, Location, + "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute", + GetSignatureForError ()); + } + + base.Emit (); + } + } + + /// + /// For case when event is declared like property (with add and remove accessors). + /// + public class EventProperty: Event { + public abstract class AEventPropertyAccessor : AEventAccessor + { + protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + } + + public override MethodBuilder Define (DeclSpace ds) + { + CheckAbstractAndExtern (block != null); + return base.Define (ds); + } + + public override string GetSignatureForError () + { + return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1); + } + } + + public sealed class AddDelegateMethod: AEventPropertyAccessor + { + public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc) + : base (method, AddPrefix, attrs, loc) + { + } + } + + public sealed class RemoveDelegateMethod: AEventPropertyAccessor + { + public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc) + : base (method, RemovePrefix, attrs, loc) + { + } + } + + static readonly string[] attribute_targets = new string [] { "event" }; + + public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, name, attrs) + { + } + + public override bool Define() + { + if (!base.Define ()) + return false; + + SetIsUsed (); + return true; + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + } + + /// + /// Event is declared like field. + /// + public class EventField : Event + { + abstract class EventFieldAccessor : AEventAccessor + { + protected EventFieldAccessor (EventField method, string prefix) + : base (method, prefix, null, Location.Null) + { + } + + protected abstract MethodSpec GetOperation (Location loc); + + public override void Emit (DeclSpace parent) + { + if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) { + block = new ToplevelBlock (Compiler, ParameterInfo, Location); + FabricateBodyStatement (); + } + + base.Emit (parent); + } + + void FabricateBodyStatement () + { + // + // Delegate obj1 = backing_field + // do { + // Delegate obj2 = obj1; + // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); + // } while (obj1 != obj2) + // + + var field_info = ((EventField) method).backing_field; + FieldExpr f_expr = new FieldExpr (field_info, Location); + if (!IsStatic) + f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); + + var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); + var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); + + block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); + + var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, + new LocalVariableReference (obj1, Location), new LocalVariableReference (obj2, Location), Location)); + + var body = new ExplicitBlock (block, Location, Location); + block.AddStatement (new Do (body, cond, Location)); + + body.AddStatement (new StatementExpression ( + new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); + + var args_oper = new Arguments (2); + args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); + args_oper.Add (new Argument (block.GetParameterReference (0, Location))); + + var op_method = GetOperation (Location); + + var args = new Arguments (3); + args.Add (new Argument (f_expr, Argument.AType.Ref)); + args.Add (new Argument (new Cast ( + new TypeExpression (field_info.MemberType, Location), + new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper), + Location))); + args.Add (new Argument (new LocalVariableReference (obj1, Location))); + + var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location); + if (cas == null) + return; + + body.AddStatement (new StatementExpression (new SimpleAssign ( + new LocalVariableReference (obj1, Location), + new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); + } + } + + sealed class AddDelegateMethod: EventFieldAccessor + { + public AddDelegateMethod (EventField method): + base (method, AddPrefix) + { + } + + protected override MethodSpec GetOperation (Location loc) + { + return Module.PredefinedMembers.DelegateCombine.Resolve (loc); + } + } + + sealed class RemoveDelegateMethod: EventFieldAccessor + { + public RemoveDelegateMethod (EventField method): + base (method, RemovePrefix) + { + } + + protected override MethodSpec GetOperation (Location loc) + { + return Module.PredefinedMembers.DelegateRemove.Resolve (loc); + } + } + + + static readonly string[] attribute_targets = new string [] { "event", "field", "method" }; + static readonly string[] attribute_targets_interface = new string[] { "event", "method" }; + + Expression initializer; + Field backing_field; + List declarators; + + public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, name, attrs) + { + Add = new AddDelegateMethod (this); + Remove = new RemoveDelegateMethod (this); + } + + #region Properties + + bool HasBackingField { + get { + return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + public override string[] ValidAttributeTargets { + get { + return HasBackingField ? attribute_targets : attribute_targets_interface; + } + } + + public List Declarators { + get { + return this.declarators; + } + } + + #endregion + + public void AddDeclarator (FieldDeclarator declarator) + { + if (declarators == null) + declarators = new List (2); + + declarators.Add (declarator); + + // TODO: This will probably break + Parent.AddMember (this, declarator.Name.Value); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Field) { + backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Target == AttributeTargets.Method) { + int errors = Report.Errors; + Add.ApplyAttributeBuilder (a, ctor, cdata, pa); + if (errors == Report.Errors) + Remove.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override bool Define() + { + var mod_flags_src = ModFlags; + + if (!base.Define ()) + return false; + + if (declarators != null) { + if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) + mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER); + + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Events.IndexOf (this); + foreach (var d in declarators) { + var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + + if (d.Initializer != null) + ef.initializer = d.Initializer; + + Parent.PartialContainer.Events.Insert (++index, ef); + } + } + + if (!HasBackingField) { + SetIsUsed (); + return true; + } + + if (Add.IsInterfaceImplementation) + SetIsUsed (); + + backing_field = new Field (Parent, + new TypeExpression (MemberType, Location), + Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), + MemberName, null); + + Parent.PartialContainer.AddField (backing_field); + backing_field.Initializer = Initializer; + backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED; + + // Call define because we passed fields definition + backing_field.Define (); + + // Set backing field for event fields + spec.BackingField = backing_field.Spec; + + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public abstract class Event : PropertyBasedMember + { + public abstract class AEventAccessor : AbstractPropertyEventMethod + { + protected readonly Event method; + readonly ParametersCompiled parameters; + + static readonly string[] attribute_targets = new string [] { "method", "param", "return" }; + + public const string AddPrefix = "add_"; + public const string RemovePrefix = "remove_"; + + protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + this.method = method; + this.ModFlags = method.ModFlags; + this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc); + } + + public bool IsInterfaceImplementation { + get { return method_data.implementing != null; } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.MethodImpl) { + method.is_external_implementation = a.IsInternalCall (); + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Parameter) { + parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + public override bool IsClsComplianceRequired () + { + return method.IsClsComplianceRequired (); + } + + public virtual MethodBuilder Define (DeclSpace parent) + { + // Fill in already resolved event type to speed things up and + // avoid confusing duplicate errors + ((Parameter) parameters.FixedParameters[0]).Type = method.member_type; + parameters.Types = new TypeSpec[] { method.member_type }; + + method_data = new MethodData (method, method.ModFlags, + method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + MethodBuilder mb = method_data.MethodBuilder; + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags); + Spec.IsAccessor = true; + + return mb; + } + + public override TypeSpec ReturnType { + get { + return Parent.Compiler.BuiltinTypes.Void; + } + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return method.GetAttributeObsolete (); + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + } + + AEventAccessor add, remove; + EventBuilder EventBuilder; + protected EventSpec spec; + + protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, null, type, mod_flags, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct : + AllowedModifiersClass, + name, attrs) + { + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Event; + } + } + + public AEventAccessor Add { + get { + return this.add; + } + set { + add = value; + Parent.AddMember (value); + } + } + + public override Variance ExpectedMemberTypeVariance { + get { + return Variance.Contravariant; + } + } + + public AEventAccessor Remove { + get { + return this.remove; + } + set { + remove = value; + Parent.AddMember (value); + } + } + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if ((a.HasSecurityAttribute)) { + a.Error_InvalidSecurityParent (); + return; + } + + EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + var ok = base.CheckOverrideAgainstBase (base_member); + + if (!CheckAccessModifiers (this, base_member)) { + Error_CannotChangeAccessModifiers (this, base_member); + ok = false; + } + + return ok; + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!TypeManager.IsDelegateType (MemberType)) { + Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ()); + } + + if (!CheckBase ()) + return false; + + // + // Now define the accessors + // + var AddBuilder = Add.Define (Parent); + if (AddBuilder == null) + return false; + + var RemoveBuilder = remove.Define (Parent); + if (RemoveBuilder == null) + return false; + + EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ()); + EventBuilder.SetAddOnMethod (AddBuilder); + EventBuilder.SetRemoveOnMethod (RemoveBuilder); + + spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec); + + Parent.MemberCache.AddMember (this, Name, spec); + Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec); + Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec); + + return true; + } + + public override void Emit () + { + CheckReservedNameConflict (null, add.Spec); + CheckReservedNameConflict (null, remove.Spec); + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + Add.Emit (Parent); + Remove.Emit (Parent); + + base.Emit (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "E:"; } + } + } + + public class EventSpec : MemberSpec, IInterfaceMemberSpec + { + MethodSpec add, remove; + FieldSpec backing_field; + + public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove) + : base (MemberKind.Event, declaringType, definition, modifiers) + { + this.AccessorAdd = add; + this.AccessorRemove = remove; + this.MemberType = eventType; + } + + #region Properties + + public MethodSpec AccessorAdd { + get { + return add; + } + set { + add = value; + } + } + + public MethodSpec AccessorRemove { + get { + return remove; + } + set { + remove = value; + } + } + + public FieldSpec BackingField { + get { + return backing_field; + } + set { + backing_field = value; + } + } + + public TypeSpec MemberType { get; private set; } + + #endregion + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var es = (EventSpec) base.InflateMember (inflator); + es.MemberType = inflator.Inflate (MemberType); + + if (backing_field != null) + es.backing_field = (FieldSpec) backing_field.InflateMember (inflator); + + return es; + } + + public override List ResolveMissingDependencies () + { + return MemberType.ResolveMissingDependencies (); + } + } + + public class Indexer : PropertyBase, IParametersMember + { + public class GetIndexerMethod : GetMethod, IParametersMember + { + ParametersCompiled parameters; + + public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (property, modifiers, attrs, loc) + { + this.parameters = parameters; + } + + public override MethodBuilder Define (DeclSpace parent) + { + parameters.Resolve (this); + return base.Define (parent); + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + #region IParametersMember Members + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return ReturnType; + } + } + + #endregion + } + + public class SetIndexerMethod : SetMethod, IParametersMember + { + public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (property, modifiers, parameters, attrs, loc) + { + } + + #region IParametersMember Members + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return ReturnType; + } + } + + #endregion + } + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.VIRTUAL | + Modifiers.SEALED | + Modifiers.OVERRIDE | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.ABSTRACT; + + const Modifiers AllowedInterfaceModifiers = + Modifiers.NEW; + + readonly ParametersCompiled parameters; + + public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod, + ParametersCompiled parameters, Attributes attrs) + : base (parent, type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers, + name, attrs) + { + this.parameters = parameters; + } + + #region Properties + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + public ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.IndexerName) { + if (IsExplicitImpl) { + Report.Error (415, a.Location, + "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration", + TypeManager.CSharpName (a.Type)); + } + + // Attribute was copied to container + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!DefineParameters (parameters)) + return false; + + if (OptAttributes != null) { + Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName); + if (indexer_attr != null) { + var compiling = indexer_attr.Type.MemberDefinition as TypeContainer; + if (compiling != null) + compiling.Define (); + + string name = indexer_attr.GetIndexerAttributeValue (); + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + Report.Error (609, indexer_attr.Location, + "Cannot set the `IndexerName' attribute on an indexer marked override"); + } + + if (!string.IsNullOrEmpty (name)) + ShortName = name; + } + } + + if (InterfaceType != null) { + string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember (); + if (base_IndexerName != Name) + ShortName = base_IndexerName; + } + + if (!Parent.PartialContainer.AddMember (this)) + return false; + + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + + if (!DefineAccessors ()) + return false; + + if (!CheckBase ()) + return false; + + DefineBuilders (MemberKind.Indexer, parameters); + return true; + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is Indexer) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + return base.EnableOverloadChecks (overload); + } + + public override void Emit () + { + parameters.CheckConstraints (this); + + base.Emit (); + } + + public override string GetSignatureForError () + { + StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ()); + if (MemberName.Left != null) { + sb.Append ("."); + sb.Append (MemberName.Left.GetSignatureForError ()); + } + + sb.Append (".this"); + sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count)); + return sb.ToString (); + } + + public override string GetSignatureForDocumentation () + { + return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation (); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + parameters.VerifyClsCompliance (this); + return true; + } + } + + public class IndexerSpec : PropertySpec, IParametersMember + { + AParametersCollection parameters; + + public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers) + : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers) + { + this.parameters = parameters; + } + + #region Properties + public AParametersCollection Parameters { + get { + return parameters; + } + } + #endregion + + public override string GetSignatureForDocumentation () + { + return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation (); + } + + public override string GetSignatureForError () + { + return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count); + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var spec = (IndexerSpec) base.InflateMember (inflator); + spec.parameters = parameters.Inflate (inflator); + return spec; + } + + public override List ResolveMissingDependencies () + { + var missing = base.ResolveMissingDependencies (); + foreach (var pt in parameters.Types) { + var m = pt.GetMissingDependencies (); + if (m == null) + continue; + + if (missing == null) + missing = new List (); + + missing.AddRange (m); + } + + return missing; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs new file mode 100644 index 0000000000..6f2f183a83 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs @@ -0,0 +1,557 @@ +// +// reflection.cs: System.Reflection and System.Reflection.Emit specific implementations +// +// Author: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009-2010 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using System.Runtime.CompilerServices; +using System.Reflection.Emit; +using System.Security; + +namespace Mono.CSharp +{ +#if STATIC + public class ReflectionImporter + { + public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin) + { + throw new NotSupportedException (); + } + + public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace) + { + throw new NotSupportedException (); + } + + public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace) + { + throw new NotSupportedException (); + } + + public TypeSpec ImportType (Type type) + { + throw new NotSupportedException (); + } + } +#else + public sealed class ReflectionImporter : MetadataImporter + { + public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin) + : base (module) + { + Initialize (builtin); + } + + public override void AddCompiledType (TypeBuilder builder, TypeSpec spec) + { + } + + protected override MemberKind DetermineKindFromBaseType (Type baseType) + { + if (baseType == typeof (ValueType)) + return MemberKind.Struct; + + if (baseType == typeof (System.Enum)) + return MemberKind.Enum; + + if (baseType == typeof (MulticastDelegate)) + return MemberKind.Delegate; + + return MemberKind.Class; + } + + protected override bool HasVolatileModifier (Type[] modifiers) + { + foreach (var t in modifiers) { + if (t == typeof (IsVolatile)) + return true; + } + + return false; + } + + public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace) + { + // It can be used more than once when importing same assembly + // into 2 or more global aliases + var definition = GetAssemblyDefinition (assembly); + + // + // This part tries to simulate loading of top-level + // types only, any missing dependencies are ignores here. + // Full error report is reported later when the type is + // actually used + // + Type[] all_types; + try { + all_types = assembly.GetTypes (); + } catch (ReflectionTypeLoadException e) { + all_types = e.Types; + } + + ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod); + } + + public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace) + { + var module_definition = new ImportedModuleDefinition (module); + module_definition.ReadAttributes (); + + Type[] all_types; + try { + all_types = module.GetTypes (); + } catch (ReflectionTypeLoadException e) { + all_types = e.Types; + } + + ImportTypes (all_types, targetNamespace, false); + + return module_definition; + } + + void Initialize (BuiltinTypes builtin) + { + // + // Setup mapping for build-in types to avoid duplication of their definition + // + compiled_types.Add (typeof (object), builtin.Object); + compiled_types.Add (typeof (System.ValueType), builtin.ValueType); + compiled_types.Add (typeof (System.Attribute), builtin.Attribute); + + compiled_types.Add (typeof (int), builtin.Int); + compiled_types.Add (typeof (long), builtin.Long); + compiled_types.Add (typeof (uint), builtin.UInt); + compiled_types.Add (typeof (ulong), builtin.ULong); + compiled_types.Add (typeof (byte), builtin.Byte); + compiled_types.Add (typeof (sbyte), builtin.SByte); + compiled_types.Add (typeof (short), builtin.Short); + compiled_types.Add (typeof (ushort), builtin.UShort); + + compiled_types.Add (typeof (System.Collections.IEnumerator), builtin.IEnumerator); + compiled_types.Add (typeof (System.Collections.IEnumerable), builtin.IEnumerable); + compiled_types.Add (typeof (System.IDisposable), builtin.IDisposable); + + compiled_types.Add (typeof (char), builtin.Char); + compiled_types.Add (typeof (string), builtin.String); + compiled_types.Add (typeof (float), builtin.Float); + compiled_types.Add (typeof (double), builtin.Double); + compiled_types.Add (typeof (decimal), builtin.Decimal); + compiled_types.Add (typeof (bool), builtin.Bool); + compiled_types.Add (typeof (System.IntPtr), builtin.IntPtr); + compiled_types.Add (typeof (System.UIntPtr), builtin.UIntPtr); + + compiled_types.Add (typeof (System.MulticastDelegate), builtin.MulticastDelegate); + compiled_types.Add (typeof (System.Delegate), builtin.Delegate); + compiled_types.Add (typeof (System.Enum), builtin.Enum); + compiled_types.Add (typeof (System.Array), builtin.Array); + compiled_types.Add (typeof (void), builtin.Void); + compiled_types.Add (typeof (System.Type), builtin.Type); + compiled_types.Add (typeof (System.Exception), builtin.Exception); + compiled_types.Add (typeof (System.RuntimeFieldHandle), builtin.RuntimeFieldHandle); + compiled_types.Add (typeof (System.RuntimeTypeHandle), builtin.RuntimeTypeHandle); + } + } + + [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)] + struct SingleConverter + { + [System.Runtime.InteropServices.FieldOffset (0)] + int i; + [System.Runtime.InteropServices.FieldOffset (0)] + float f; + + public static int SingleToInt32Bits (float v) + { + SingleConverter c = new SingleConverter (); + c.f = v; + return c.i; + } + } + +#endif + + public class AssemblyDefinitionDynamic : AssemblyDefinition + { + // + // In-memory only assembly container + // + public AssemblyDefinitionDynamic (ModuleContainer module, string name) + : base (module, name) + { + } + + // + // Assembly container with file output + // + public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName) + : base (module, name, fileName) + { + } + + public Module IncludeModule (string moduleFile) + { + return builder_extra.AddModule (moduleFile); + } + +#if !STATIC + public override ModuleBuilder CreateModuleBuilder () + { + if (file_name == null) + return Builder.DefineDynamicModule (Name, false); + + return base.CreateModuleBuilder (); + } +#endif + // + // Initializes the code generator + // + public bool Create (AppDomain domain, AssemblyBuilderAccess access) + { +#if STATIC + throw new NotSupportedException (); +#else + ResolveAssemblySecurityAttributes (); + var an = CreateAssemblyName (); + + Builder = file_name == null ? + domain.DefineDynamicAssembly (an, access) : + domain.DefineDynamicAssembly (an, access, Dirname (file_name)); + + module.Create (this, CreateModuleBuilder ()); + builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler); + return true; +#endif + } + + static string Dirname (string name) + { + int pos = name.LastIndexOf ('/'); + + if (pos != -1) + return name.Substring (0, pos); + + pos = name.LastIndexOf ('\\'); + if (pos != -1) + return name.Substring (0, pos); + + return "."; + } + +#if !STATIC + protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine) + { + try { + var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + var set_module_only = module_only.GetSetMethod (true); + + set_module_only.Invoke (Builder, new object[] { true }); + } catch { + base.SaveModule (pekind, machine); + } + + Builder.Save (file_name, pekind, machine); + } +#endif + } + + // + // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible + // compiler + // + class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension + { + static MethodInfo adder_method; + static MethodInfo add_permission; + static MethodInfo add_type_forwarder; + static MethodInfo win32_icon_define; + static FieldInfo assembly_version; + static FieldInfo assembly_algorithm; + static FieldInfo assembly_culture; + static FieldInfo assembly_flags; + + AssemblyBuilder builder; + + public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx) + : base (ctx) + { + this.builder = ab; + } + + public override Module AddModule (string module) + { + try { + if (adder_method == null) + adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic); + + return (Module) adder_method.Invoke (builder, new object[] { module }); + } catch { + return base.AddModule (module); + } + } + + public override void AddPermissionRequests (PermissionSet[] permissions) + { + try { + if (add_permission == null) + add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); + + add_permission.Invoke (builder, permissions); + } catch { + base.AddPermissionRequests (permissions); + } + } + + public override void AddTypeForwarder (TypeSpec type, Location loc) + { + try { + if (add_type_forwarder == null) { + add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance); + } + + add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () }); + } catch { + base.AddTypeForwarder (type, loc); + } + } + + public override void DefineWin32IconResource (string fileName) + { + try { + if (win32_icon_define == null) + win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic); + + win32_icon_define.Invoke (builder, new object[] { fileName }); + } catch { + base.DefineWin32IconResource (fileName); + } + } + + public override void SetAlgorithmId (uint value, Location loc) + { + try { + if (assembly_algorithm == null) + assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_algorithm.SetValue (builder, value); + } catch { + base.SetAlgorithmId (value, loc); + } + } + + public override void SetCulture (string culture, Location loc) + { + try { + if (assembly_culture == null) + assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_culture.SetValue (builder, culture); + } catch { + base.SetCulture (culture, loc); + } + } + + public override void SetFlags (uint flags, Location loc) + { + try { + if (assembly_flags == null) + assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_flags.SetValue (builder, flags); + } catch { + base.SetFlags (flags, loc); + } + } + + public override void SetVersion (Version version, Location loc) + { + try { + if (assembly_version == null) + assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_version.SetValue (builder, version.ToString (4)); + } catch { + base.SetVersion (version, loc); + } + } + } + + // + // Reflection based references loader + // + class DynamicLoader : AssemblyReferencesLoader + { + readonly ReflectionImporter importer; + + public DynamicLoader (ReflectionImporter importer, CompilerContext compiler) + : base (compiler) + { + paths.Add (GetSystemDir ()); + + this.importer = importer; + } + + public ReflectionImporter Importer { + get { + return importer; + } + } + + protected override string[] GetDefaultReferences () + { + // + // For now the "default config" is harcoded into the compiler + // we can move this outside later + // + var default_references = new List (8); + + default_references.Add ("System"); + default_references.Add ("System.Xml"); +#if NET_2_1 + default_references.Add ("System.Net"); + default_references.Add ("System.Windows"); + default_references.Add ("System.Windows.Browser"); +#endif + + if (compiler.Settings.Version > LanguageVersion.ISO_2) + default_references.Add ("System.Core"); + if (compiler.Settings.Version > LanguageVersion.V_3) + default_references.Add ("Microsoft.CSharp"); + + return default_references.ToArray (); + } + + // + // Returns the directory where the system assemblies are installed + // + static string GetSystemDir () + { + return Path.GetDirectoryName (typeof (object).Assembly.Location); + } + + public override bool HasObjectType (Assembly assembly) + { + return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null; + } + + public override Assembly LoadAssemblyFile (string fileName) + { + return LoadAssemblyFile (fileName, false); + } + + Assembly LoadAssemblyFile (string assembly, bool soft) + { + Assembly a = null; + + try { + try { + char[] path_chars = { '/', '\\' }; + + if (assembly.IndexOfAny (path_chars) != -1) { + a = Assembly.LoadFrom (assembly); + } else { + string ass = assembly; + if (ass.EndsWith (".dll") || ass.EndsWith (".exe")) + ass = assembly.Substring (0, assembly.Length - 4); + a = Assembly.Load (ass); + } + } catch (FileNotFoundException) { + bool err = !soft; + foreach (string dir in paths) { + string full_path = Path.Combine (dir, assembly); + if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) + full_path += ".dll"; + + try { + a = Assembly.LoadFrom (full_path); + err = false; + break; + } catch (FileNotFoundException) { + } + } + + if (err) { + Error_FileNotFound (assembly); + return a; + } + } + } catch (BadImageFormatException) { + Error_FileCorrupted (assembly); + } + + return a; + } + + public override Assembly LoadAssemblyDefault (string fileName) + { + return LoadAssemblyFile (fileName, true); + } + + Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module) + { + string total_log = ""; + + try { + try { + return assembly.IncludeModule (module); + } catch (FileNotFoundException) { + bool err = true; + foreach (string dir in paths) { + string full_path = Path.Combine (dir, module); + if (!module.EndsWith (".netmodule")) + full_path += ".netmodule"; + + try { + return assembly.IncludeModule (full_path); + } catch (FileNotFoundException ff) { + total_log += ff.FusionLog; + } + } + if (err) { + Error_FileNotFound (module); + return null; + } + } + } catch (BadImageFormatException) { + Error_FileCorrupted (module); + } + + return null; + } + + public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace) + { + foreach (var moduleName in compiler.Settings.Modules) { + var m = LoadModuleFile (assembly, moduleName); + if (m == null) + continue; + + var md = importer.ImportModule (m, targetNamespace); + assembly.AddModule (md); + } + } + + public override void LoadReferences (ModuleContainer module) + { + Assembly corlib; + List> loaded; + base.LoadReferencesCore (module, out corlib, out loaded); + + if (corlib == null) + return; + + importer.ImportAssembly (corlib, module.GlobalRootNamespace); + foreach (var entry in loaded) { + importer.ImportAssembly (entry.Item2, entry.Item1); + } + } + } +} \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt new file mode 100644 index 0000000000..4f71772f6c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt @@ -0,0 +1,168 @@ +Things to do for the REPL support in MCS: + +Documentation for the REPL mode for MCS can be found here: + + http://mono-project.com/CsharpRepl + +* Embedding API + + * Booting the compiler without Main () + * Expose LoadAssembly/LoadPackage + * Register fields? + * Register a lookup function for fields? + * Register classes to expose to REPL + +* Embedded Library + + * Run a REPL on a socket (from Joe Shaw) + * Host a REPL on XSP (from Nat). + +* TODO + + Clear struct fields inside the clearing code. + +* Other ideas: + + MD addin for "csharp" + +* Supporting class-level declarations + + Currently the evaluator has this feature disabled, to enable + it edit the eval.cs file and make this be the default: + +- parser.Lexer.putback_char = Tokenizer.EvalUsingDeclarationsParserCharacter; +- //parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; ++ //parser.Lexer.putback_char = Tokenizer.EvalUsingDeclarationsParserCharacter; ++ parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; + + + It currently has a few problems: + + * Support for overwritting existing defined + classes is not supported. + + * The usability is not as useful, since the defaults + for C# are still to make members private, we should + change this default to be public in those cases. + + * The error lookup system lacks information from types, for + example this causes an unsupported call into a TypeBuilder: + + csharp>class D { void DD () {} } + csharp>var d = new D (); + csharp>d.DD (); + + Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class0::Host] + System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in :0 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00000] in + at Mono.CSharp.MethodGroupExpr.NoExactMatch (Mono.CSharp.ResolveContext ec, + Mono.CSharp.Arguments& Arguments, IDictionary`2 c + + + The above is caused by TypeManager.LookupDeclSpace (dt) + failing to return a value (it returns null) so our code + assumes we have an Assembly instead of an assemblybuilder. + + + +* Declaring a class twice produces an internal parse error: + + class X {} + class X {} + + The second declaration will no longer be parsed, so it could even + contain junk, and wont be flagged. We probably need to allow for + type redefinition in REPL modes, the exception from the second is: + + csharp -v -v + > class X {} + > class X {} + + System.ArgumentException: An element with the same key already exists in the dictionary. + at System.Collections.Generic.Dictionary`2[System.String,Mono.CSharp.DeclSpace].Add (System.String key, Mono.CSharp.DeclSpace value) [0x00000] in :0 + at Mono.CSharp.Namespace.AddDeclSpace (System.String name, Mono.CSharp.DeclSpace ds) [0x00000] in :0 + at Mono.CSharp.ModuleCompiled.AddMemberType (Mono.CSharp.DeclSpace ds) [0x00000] in :0 + at Mono.CSharp.TypeContainer.AddTypeContainer (Mono.CSharp.TypeContainer tc) [0x00000] in :0 + at Mono.CSharp.CSharpParser.push_current_class (Mono.CSharp.TypeContainer tc, System.Object partial_token) [0x00000] in :0 + at Mono.CSharp.CSharpParser.yyparse (yyInput yyLex) [0x00000] in :0 + at Mono.CSharp.CSharpParser.yyparse (yyInput yyLex, System.Object yyd) [0x00000] in :0 + at Mono.CSharp.CSharpParser.parse () [0x00000] in :0 + +* Mix statements with other top-level declarations. + +csharp> class Y {static void Main () {Console.WriteLine ("Foo"); }} +csharp> typeof (Y); +Y +csharp> Y.Main (); +Exception caught by the compiler while compiling: + Block that caused the problem begin at: Internal(1,1): + Block being compiled: [(1,2):,(1,11):] +System.NotSupportedException: The invoked member is not supported in a dynamic module. +Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class2::Host] +System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 + at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 + at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression right_side) [0x00230] in /second/home/cvs/mcs/mcs/expression.cs:7426 + at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/expression.cs:7494 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Invocation.DoResolve (Mono.CSharp.EmitContext ec) [0x0000d] in /second/home/cvs/mcs/mcs/expression.cs:4725 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:681 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 + at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 + at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 + at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 + at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 +csharp> + +* Another one: + +csharp> class X { X (){ Console.WriteLine ("Called"); } } +csharp> new X (); +Exception caught by the compiler while compiling: + Block that caused the problem begin at: Internal(1,1): + Block being compiled: [(1,2):,(1,10):] +System.NotSupportedException: The invoked member is not supported in a dynamic module. +Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class0::Host] +System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 + at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 + at Mono.CSharp.Expression.MemberLookupFinal (Mono.CSharp.EmitContext ec, System.Type qualifier_type, System.Type queried_type, System.String name, MemberTypes mt, BindingFlags bf, Location loc) [0x0002f] in /second/home/cvs/mcs/mcs/ecore.cs:804 + at Mono.CSharp.New.DoResolve (Mono.CSharp.EmitContext ec) [0x002ad] in /second/home/cvs/mcs/mcs/expression.cs:5486 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:687 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 + at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 + at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 + at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 + at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 +csharp> + +* Important: we need to replace TypeBuidlers with Types after things + have been emitted, or stuff like this happens: + +csharp> public class y {} +csharp> typeof (y); +Class1 + + +* Clearing data + + TODO: when clearing data for variables that have been overwritten + we need to check for structs and clear all the fields that contain + reference types. + +* DEBATABLE: Implement auto-insert-semicolon + + This is easy to implement, just retry the parse with a + semicolon, the question is whether this is a good idea to do + in the first place or not. diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs new file mode 100644 index 0000000000..e34e6951f0 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs @@ -0,0 +1,1221 @@ +// +// report.cs: report errors and warnings. +// +// Author: Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. (http://www.ximian.com) +// + +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Mono.CSharp { + + // + // Errors and warnings manager + // + public class Report + { + /// + /// Whether warnings should be considered errors + /// + public bool WarningsAreErrors; + List warnings_as_error; + List warnings_only; + + public const int RuntimeErrorId = 10000; + + // + // Keeps track of the warnings that we are ignoring + // + HashSet warning_ignore_table; + + Dictionary warning_regions_table; + + int warning_level; + + ReportPrinter printer; + + int reporting_disabled; + + /// + /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported. + /// + List extra_information = new List (); + + // + // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE + // + public static readonly int[] AllWarnings = new int[] { + 28, 67, 78, + 105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197, + 219, 251, 252, 253, 278, 282, + 402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473, + 612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693, + 728, + 809, 824, + 1030, 1058, 1066, + 1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592, + 1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1699, + 1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735, + 1901, 1956, 1981, + 2002, 2023, 2029, + 3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009, + 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, + 3021, 3022, 3023, 3024, 3026, 3027 + }; + + static HashSet AllWarningsHashSet; + + public Report (ReportPrinter printer) + { + if (printer == null) + throw new ArgumentNullException ("printer"); + + this.printer = printer; + warning_level = 4; + } + + public void DisableReporting () + { + ++reporting_disabled; + } + + public void EnableReporting () + { + --reporting_disabled; + } + + public void FeatureIsNotAvailable (CompilerContext compiler, Location loc, string feature) + { + string version; + switch (compiler.Settings.Version) { + case LanguageVersion.ISO_1: + version = "1.0"; + break; + case LanguageVersion.ISO_2: + version = "2.0"; + break; + case LanguageVersion.V_3: + version = "3.0"; + break; + default: + throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version); + } + + Error (1644, loc, + "Feature `{0}' cannot be used because it is not part of the C# {1} language specification", + feature, version); + } + + public void FeatureIsNotSupported (Location loc, string feature) + { + Error (1644, loc, + "Feature `{0}' is not supported in Mono mcs1 compiler. Consider using the `gmcs' compiler instead", + feature); + } + + bool IsWarningEnabled (int code, int level, Location loc) + { + if (WarningLevel < level) + return false; + + if (IsWarningDisabledGlobally (code)) + return false; + + if (warning_regions_table == null || loc.IsNull) + return true; + + WarningRegions regions; + if (!warning_regions_table.TryGetValue (loc.File, out regions)) + return true; + + return regions.IsWarningEnabled (code, loc.Row); + } + + public bool IsWarningDisabledGlobally (int code) + { + return warning_ignore_table != null && warning_ignore_table.Contains (code); + } + + bool IsWarningAsError (int code) + { + bool is_error = WarningsAreErrors; + + // Check specific list + if (warnings_as_error != null) + is_error |= warnings_as_error.Contains (code); + + // Ignore excluded warnings + if (warnings_only != null && warnings_only.Contains (code)) + is_error = false; + + return is_error; + } + + public void RuntimeMissingSupport (Location loc, string feature) + { + Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature); + } + + /// + /// In most error cases is very useful to have information about symbol that caused the error. + /// Call this method before you call Report.Error when it makes sense. + /// + public void SymbolRelatedToPreviousError (Location loc, string symbol) + { + SymbolRelatedToPreviousError (loc.ToString ()); + } + + public void SymbolRelatedToPreviousError (MemberSpec ms) + { + if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport) + return; + + var mc = ms.MemberDefinition as MemberCore; + while (ms is ElementTypeSpec) { + ms = ((ElementTypeSpec) ms).Element; + mc = ms.MemberDefinition as MemberCore; + } + + if (mc != null) { + SymbolRelatedToPreviousError (mc); + } else { + if (ms.DeclaringType != null) + ms = ms.DeclaringType; + + var imported_type = ms.MemberDefinition as ImportedTypeDefinition; + if (imported_type != null) { + var iad = imported_type.DeclaringAssembly as ImportedAssemblyDefinition; + SymbolRelatedToPreviousError (iad.Location); + } + } + } + + public void SymbolRelatedToPreviousError (MemberCore mc) + { + SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ()); + } + + public void SymbolRelatedToPreviousError (string loc) + { + string msg = String.Format ("{0} (Location of the symbol related to previous ", loc); + if (extra_information.Contains (msg)) + return; + + extra_information.Add (msg); + } + + public void AddWarningAsError (string warningId) + { + int id; + try { + id = int.Parse (warningId); + } catch { + CheckWarningCode (warningId, Location.Null); + return; + } + + if (!CheckWarningCode (id, Location.Null)) + return; + + if (warnings_as_error == null) + warnings_as_error = new List (); + + warnings_as_error.Add (id); + } + + public void RemoveWarningAsError (string warningId) + { + int id; + try { + id = int.Parse (warningId); + } catch { + CheckWarningCode (warningId, Location.Null); + return; + } + + if (!CheckWarningCode (id, Location.Null)) + return; + + if (warnings_only == null) + warnings_only = new List (); + + warnings_only.Add (id); + } + + public bool CheckWarningCode (string code, Location loc) + { + Warning (1691, 1, loc, "`{0}' is not a valid warning number", code); + return false; + } + + public bool CheckWarningCode (int code, Location loc) + { + if (AllWarningsHashSet == null) + AllWarningsHashSet = new HashSet (AllWarnings); + + if (AllWarningsHashSet.Contains (code)) + return true; + + return CheckWarningCode (code.ToString (), loc); + } + + public void ExtraInformation (Location loc, string msg) + { + extra_information.Add (String.Format ("{0} {1}", loc, msg)); + } + + public WarningRegions RegisterWarningRegion (Location location) + { + WarningRegions regions; + if (warning_regions_table == null) { + regions = null; + warning_regions_table = new Dictionary (); + } else { + warning_regions_table.TryGetValue (location.File, out regions); + } + + if (regions == null) { + regions = new WarningRegions (); + warning_regions_table.Add (location.File, regions); + } + + return regions; + } + + public void Warning (int code, int level, Location loc, string message) + { + if (reporting_disabled > 0) + return; + + if (!IsWarningEnabled (code, level, loc)) + return; + + AbstractMessage msg; + if (IsWarningAsError (code)) { + message = "Warning as Error: " + message; + msg = new ErrorMessage (code, loc, message, extra_information); + } else { + msg = new WarningMessage (code, loc, message, extra_information); + } + + extra_information.Clear (); + printer.Print (msg); + } + + public void Warning (int code, int level, Location loc, string format, string arg) + { + Warning (code, level, loc, String.Format (format, arg)); + } + + public void Warning (int code, int level, Location loc, string format, string arg1, string arg2) + { + Warning (code, level, loc, String.Format (format, arg1, arg2)); + } + + public void Warning (int code, int level, Location loc, string format, params object[] args) + { + Warning (code, level, loc, String.Format (format, args)); + } + + public void Warning (int code, int level, string message) + { + Warning (code, level, Location.Null, message); + } + + public void Warning (int code, int level, string format, string arg) + { + Warning (code, level, Location.Null, format, arg); + } + + public void Warning (int code, int level, string format, string arg1, string arg2) + { + Warning (code, level, Location.Null, format, arg1, arg2); + } + + public void Warning (int code, int level, string format, params string[] args) + { + Warning (code, level, Location.Null, String.Format (format, args)); + } + + // + // Warnings encountered so far + // + public int Warnings { + get { return printer.WarningsCount; } + } + + public void Error (int code, Location loc, string error) + { + if (reporting_disabled > 0) + return; + + ErrorMessage msg = new ErrorMessage (code, loc, error, extra_information); + extra_information.Clear (); + + printer.Print (msg); + } + + public void Error (int code, Location loc, string format, string arg) + { + Error (code, loc, String.Format (format, arg)); + } + + public void Error (int code, Location loc, string format, string arg1, string arg2) + { + Error (code, loc, String.Format (format, arg1, arg2)); + } + + public void Error (int code, Location loc, string format, params string[] args) + { + Error (code, loc, String.Format (format, args)); + } + + public void Error (int code, string error) + { + Error (code, Location.Null, error); + } + + public void Error (int code, string format, string arg) + { + Error (code, Location.Null, format, arg); + } + + public void Error (int code, string format, string arg1, string arg2) + { + Error (code, Location.Null, format, arg1, arg2); + } + + public void Error (int code, string format, params string[] args) + { + Error (code, Location.Null, String.Format (format, args)); + } + + // + // Errors encountered so far + // + public int Errors { + get { return printer.ErrorsCount; } + } + + public bool IsDisabled { + get { + return reporting_disabled > 0; + } + } + + public ReportPrinter Printer { + get { return printer; } + } + + public void SetIgnoreWarning (int code) + { + if (warning_ignore_table == null) + warning_ignore_table = new HashSet (); + + warning_ignore_table.Add (code); + } + + public ReportPrinter SetPrinter (ReportPrinter printer) + { + ReportPrinter old = this.printer; + this.printer = printer; + return old; + } + + public int WarningLevel { + get { + return warning_level; + } + set { + warning_level = value; + } + } + + [Conditional ("MCS_DEBUG")] + static public void Debug (string message, params object[] args) + { + Debug (4, message, args); + } + + [Conditional ("MCS_DEBUG")] + static public void Debug (int category, string message, params object[] args) + { +// if ((category & DebugFlags) == 0) +// return; + + StringBuilder sb = new StringBuilder (message); + + if ((args != null) && (args.Length > 0)) { + sb.Append (": "); + + bool first = true; + foreach (object arg in args) { + if (first) + first = false; + else + sb.Append (", "); + if (arg == null) + sb.Append ("null"); +// else if (arg is ICollection) +// sb.Append (PrintCollection ((ICollection) arg)); + else + sb.Append (arg); + } + } + + Console.WriteLine (sb.ToString ()); + } +/* + static public string PrintCollection (ICollection collection) + { + StringBuilder sb = new StringBuilder (); + + sb.Append (collection.GetType ()); + sb.Append ("("); + + bool first = true; + foreach (object o in collection) { + if (first) + first = false; + else + sb.Append (", "); + sb.Append (o); + } + + sb.Append (")"); + return sb.ToString (); + } +*/ + } + + public abstract class AbstractMessage + { + readonly string[] extra_info; + protected readonly int code; + protected readonly Location location; + readonly string message; + + protected AbstractMessage (int code, Location loc, string msg, List extraInfo) + { + this.code = code; + if (code < 0) + this.code = 8000 - code; + + this.location = loc; + this.message = msg; + if (extraInfo.Count != 0) { + this.extra_info = extraInfo.ToArray (); + } + } + + protected AbstractMessage (AbstractMessage aMsg) + { + this.code = aMsg.code; + this.location = aMsg.location; + this.message = aMsg.message; + this.extra_info = aMsg.extra_info; + } + + public int Code { + get { return code; } + } + + public override bool Equals (object obj) + { + AbstractMessage msg = obj as AbstractMessage; + if (msg == null) + return false; + + return code == msg.code && location.Equals (msg.location) && message == msg.message; + } + + public override int GetHashCode () + { + return code.GetHashCode (); + } + + public abstract bool IsWarning { get; } + + public Location Location { + get { return location; } + } + + public abstract string MessageType { get; } + + public string[] RelatedSymbols { + get { return extra_info; } + } + + public string Text { + get { return message; } + } + } + + sealed class WarningMessage : AbstractMessage + { + public WarningMessage (int code, Location loc, string message, List extra_info) + : base (code, loc, message, extra_info) + { + } + + public override bool IsWarning { + get { return true; } + } + + public override string MessageType { + get { + return "warning"; + } + } + } + + sealed class ErrorMessage : AbstractMessage + { + public ErrorMessage (int code, Location loc, string message, List extraInfo) + : base (code, loc, message, extraInfo) + { + } + + public ErrorMessage (AbstractMessage aMsg) + : base (aMsg) + { + } + + public override bool IsWarning { + get { return false; } + } + + public override string MessageType { + get { + return "error"; + } + } + } + + // + // Generic base for any message writer + // + public abstract class ReportPrinter + { + #region Properties + + public int FatalCounter { get; set; } + + public int ErrorsCount { get; protected set; } + + public bool ShowFullPaths { get; set; } + + // + // Whether to dump a stack trace on errors. + // + public bool Stacktrace { get; set; } + + public int WarningsCount { get; private set; } + + // + // When (symbols related to previous ...) can be used + // + public virtual bool HasRelatedSymbolSupport { + get { return true; } + } + + #endregion + + + protected virtual string FormatText (string txt) + { + return txt; + } + + public virtual void Print (AbstractMessage msg) + { + if (msg.IsWarning) { + ++WarningsCount; + } else { + ++ErrorsCount; + + if (ErrorsCount == FatalCounter) + throw new Exception (msg.Text); + } + } + + protected void Print (AbstractMessage msg, TextWriter output) + { + StringBuilder txt = new StringBuilder (); + if (!msg.Location.IsNull) { + if (ShowFullPaths) + txt.Append (msg.Location.ToStringFullName ()); + else + txt.Append (msg.Location.ToString ()); + + txt.Append (" "); + } + + txt.AppendFormat ("{0} CS{1:0000}: {2}", msg.MessageType, msg.Code, msg.Text); + + if (!msg.IsWarning) + output.WriteLine (FormatText (txt.ToString ())); + else + output.WriteLine (txt.ToString ()); + + if (msg.RelatedSymbols != null) { + foreach (string s in msg.RelatedSymbols) + output.WriteLine (s + msg.MessageType + ")"); + } + } + + public void Reset () + { + // HACK: Temporary hack for broken repl flow + ErrorsCount = WarningsCount = 0; + } + } + + sealed class NullReportPrinter : ReportPrinter + { + } + + // + // Default message recorder, it uses two types of message groups. + // Common messages: messages reported in all sessions. + // Merged messages: union of all messages in all sessions. + // + // Used by the Lambda expressions to compile the code with various + // parameter values, or by attribute resolver + // + class SessionReportPrinter : ReportPrinter + { + List session_messages; + // + // A collection of exactly same messages reported in all sessions + // + List common_messages; + + // + // A collection of unique messages reported in all sessions + // + List merged_messages; + + public override void Print (AbstractMessage msg) + { + // + // This line is useful when debugging recorded messages + // + // Console.WriteLine ("RECORDING: {0}", msg.ToString ()); + + if (session_messages == null) + session_messages = new List (); + + session_messages.Add (msg); + + base.Print (msg); + } + + public void EndSession () + { + if (session_messages == null) + return; + + // + // Handles the first session + // + if (common_messages == null) { + common_messages = new List (session_messages); + merged_messages = session_messages; + session_messages = null; + return; + } + + // + // Store common messages if any + // + for (int i = 0; i < common_messages.Count; ++i) { + AbstractMessage cmsg = common_messages[i]; + bool common_msg_found = false; + foreach (AbstractMessage msg in session_messages) { + if (cmsg.Equals (msg)) { + common_msg_found = true; + break; + } + } + + if (!common_msg_found) + common_messages.RemoveAt (i); + } + + // + // Merge session and previous messages + // + for (int i = 0; i < session_messages.Count; ++i) { + AbstractMessage msg = session_messages[i]; + bool msg_found = false; + for (int ii = 0; ii < merged_messages.Count; ++ii) { + if (msg.Equals (merged_messages[ii])) { + msg_found = true; + break; + } + } + + if (!msg_found) + merged_messages.Add (msg); + } + } + + public bool IsEmpty { + get { + return merged_messages == null && common_messages == null; + } + } + + // + // Prints collected messages, common messages have a priority + // + public bool Merge (ReportPrinter dest) + { + var messages_to_print = merged_messages; + if (common_messages != null && common_messages.Count > 0) { + messages_to_print = common_messages; + } + + if (messages_to_print == null) + return false; + + bool error_msg = false; + foreach (AbstractMessage msg in messages_to_print) { + dest.Print (msg); + error_msg |= !msg.IsWarning; + } + + return error_msg; + } + } + + public class StreamReportPrinter : ReportPrinter + { + readonly TextWriter writer; + + public StreamReportPrinter (TextWriter writer) + { + this.writer = writer; + } + + public override void Print (AbstractMessage msg) + { + Print (msg, writer); + base.Print (msg); + } + } + + public class ConsoleReportPrinter : StreamReportPrinter + { + static readonly string prefix, postfix; + + static ConsoleReportPrinter () + { + string term = Environment.GetEnvironmentVariable ("TERM"); + bool xterm_colors = false; + + switch (term){ + case "xterm": + case "rxvt": + case "rxvt-unicode": + if (Environment.GetEnvironmentVariable ("COLORTERM") != null){ + xterm_colors = true; + } + break; + + case "xterm-color": + case "xterm-256color": + xterm_colors = true; + break; + } + if (!xterm_colors) + return; + + if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2))) + return; + + string config = Environment.GetEnvironmentVariable ("MCS_COLORS"); + if (config == null){ + config = "errors=red"; + //config = "brightwhite,red"; + } + + if (config == "disable") + return; + + if (!config.StartsWith ("errors=")) + return; + + config = config.Substring (7); + + int p = config.IndexOf (","); + if (p == -1) + prefix = GetForeground (config); + else + prefix = GetBackground (config.Substring (p+1)) + GetForeground (config.Substring (0, p)); + postfix = "\x001b[0m"; + } + + public ConsoleReportPrinter () + : base (Console.Error) + { + } + + public ConsoleReportPrinter (TextWriter writer) + : base (writer) + { + } + + static int NameToCode (string s) + { + switch (s) { + case "black": + return 0; + case "red": + return 1; + case "green": + return 2; + case "yellow": + return 3; + case "blue": + return 4; + case "magenta": + return 5; + case "cyan": + return 6; + case "grey": + case "white": + return 7; + } + return 7; + } + + // + // maps a color name to its xterm color code + // + static string GetForeground (string s) + { + string highcode; + + if (s.StartsWith ("bright")) { + highcode = "1;"; + s = s.Substring (6); + } else + highcode = ""; + + return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m"; + } + + static string GetBackground (string s) + { + return "\x001b[" + (40 + NameToCode (s)).ToString () + "m"; + } + + protected override string FormatText (string txt) + { + if (prefix != null) + return prefix + txt + postfix; + + return txt; + } + + static string FriendlyStackTrace (StackTrace t) + { + StringBuilder sb = new StringBuilder (); + + bool foundUserCode = false; + + for (int i = 0; i < t.FrameCount; i++) { + StackFrame f = t.GetFrame (i); + var mb = f.GetMethod (); + + if (!foundUserCode && mb.ReflectedType == typeof (Report)) + continue; + + foundUserCode = true; + + sb.Append ("\tin "); + + if (f.GetFileLineNumber () > 0) + sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ()); + + sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name); + + bool first = true; + foreach (var pi in mb.GetParameters ()) { + if (!first) + sb.Append (", "); + first = false; + + sb.Append (pi.ParameterType.FullName); + } + sb.Append (")\n"); + } + + return sb.ToString (); + } + + public override void Print (AbstractMessage msg) + { + base.Print (msg); + + if (Stacktrace) + Console.WriteLine (FriendlyStackTrace (new StackTrace (true))); + } + + public static string FriendlyStackTrace (Exception e) + { + return FriendlyStackTrace (new StackTrace (e, true)); + } + + public static void StackTrace () + { + Console.WriteLine (FriendlyStackTrace (new StackTrace (true))); + } + } + + class TimeReporter + { + public enum TimerType + { + ParseTotal, + AssemblyBuilderSetup, + CreateTypeTotal, + ReferencesLoading, + ReferencesImporting, + PredefinedTypesInit, + ModuleDefinitionTotal, + UsingResolve, + EmitTotal, + CloseTypes, + Resouces, + OutputSave, + DebugSave, + } + + readonly Stopwatch[] timers; + Stopwatch total; + + public TimeReporter (bool enabled) + { + if (!enabled) + return; + + timers = new Stopwatch[System.Enum.GetValues(typeof (TimerType)).Length]; + } + + public void Start (TimerType type) + { + if (timers != null) { + var sw = new Stopwatch (); + timers[(int) type] = sw; + sw.Start (); + } + } + + public void StartTotal () + { + total = new Stopwatch (); + total.Start (); + } + + public void Stop (TimerType type) + { + if (timers != null) { + timers[(int) type].Stop (); + } + } + + public void StopTotal () + { + total.Stop (); + } + + public void ShowStats () + { + if (timers == null) + return; + + Dictionary timer_names = new Dictionary () { + { TimerType.ParseTotal, "Parsing source files" }, + { TimerType.AssemblyBuilderSetup, "Assembly builder setup" }, + { TimerType.CreateTypeTotal, "Compiled types created" }, + { TimerType.ReferencesLoading, "Referenced assemblies loading" }, + { TimerType.ReferencesImporting, "Referenced assemblies importing" }, + { TimerType.PredefinedTypesInit, "Predefined types initialization" }, + { TimerType.ModuleDefinitionTotal, "Module definition" }, + { TimerType.UsingResolve, "Top-level usings resolve" }, + { TimerType.EmitTotal, "Resolving and emitting members blocks" }, + { TimerType.CloseTypes, "Module types closed" }, + { TimerType.Resouces, "Embedding resources" }, + { TimerType.OutputSave, "Writing output file" }, + { TimerType.DebugSave, "Writing debug symbols file" }, + }; + + int counter = 0; + double percentage = (double) total.ElapsedMilliseconds / 100; + long subtotal = total.ElapsedMilliseconds; + foreach (var timer in timers) { + string msg = timer_names[(TimerType) counter++]; + var ms = timer == null ? 0 : timer.ElapsedMilliseconds; + Console.WriteLine ("{0,4:0.0}% {1,5}ms {2}", ms / percentage, ms, msg); + subtotal -= ms; + } + + Console.WriteLine ("{0,4:0.0}% {1,5}ms Other tasks", subtotal / percentage, subtotal); + Console.WriteLine (); + Console.WriteLine ("Total elapsed time: {0}", total.Elapsed); + } + } + + public class InternalErrorException : Exception { + public InternalErrorException (MemberCore mc, Exception e) + : base (mc.Location + " " + mc.GetSignatureForError (), e) + { + } + + public InternalErrorException () + : base ("Internal error") + { + } + + public InternalErrorException (string message) + : base (message) + { + } + + public InternalErrorException (string message, params object[] args) + : base (String.Format (message, args)) + { + } + + public InternalErrorException (Exception exception, string message, params object[] args) + : base (String.Format (message, args), exception) + { + } + + public InternalErrorException (Exception e, Location loc) + : base (loc.ToString (), e) + { + } + } + + /// + /// Handles #pragma warning + /// + public class WarningRegions { + + abstract class PragmaCmd + { + public int Line; + + protected PragmaCmd (int line) + { + Line = line; + } + + public abstract bool IsEnabled (int code, bool previous); + } + + class Disable : PragmaCmd + { + int code; + public Disable (int line, int code) + : base (line) + { + this.code = code; + } + + public override bool IsEnabled (int code, bool previous) + { + return this.code == code ? false : previous; + } + } + + class DisableAll : PragmaCmd + { + public DisableAll (int line) + : base (line) {} + + public override bool IsEnabled(int code, bool previous) + { + return false; + } + } + + class Enable : PragmaCmd + { + int code; + public Enable (int line, int code) + : base (line) + { + this.code = code; + } + + public override bool IsEnabled(int code, bool previous) + { + return this.code == code ? true : previous; + } + } + + class EnableAll : PragmaCmd + { + public EnableAll (int line) + : base (line) {} + + public override bool IsEnabled(int code, bool previous) + { + return true; + } + } + + + List regions = new List (); + + public void WarningDisable (int line) + { + regions.Add (new DisableAll (line)); + } + + public void WarningDisable (Location location, int code, Report Report) + { + if (Report.CheckWarningCode (code, location)) + regions.Add (new Disable (location.Row, code)); + } + + public void WarningEnable (int line) + { + regions.Add (new EnableAll (line)); + } + + public void WarningEnable (Location location, int code, Report Report) + { + if (!Report.CheckWarningCode (code, location)) + return; + + if (Report.IsWarningDisabledGlobally (code)) + Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code); + + regions.Add (new Enable (location.Row, code)); + } + + public bool IsWarningEnabled (int code, int src_line) + { + bool result = true; + foreach (PragmaCmd pragma in regions) { + if (src_line < pragma.Line) + break; + + result = pragma.IsEnabled (code, result); + } + return result; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs new file mode 100644 index 0000000000..a3b379ce69 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs @@ -0,0 +1,1462 @@ +// +// rootcontext.cs: keeps track of our tree representation, and assemblies loaded. +// +// Author: Miguel de Icaza (miguel@ximian.com) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc + +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Globalization; +using System; + +namespace Mono.CSharp { + + public enum LanguageVersion + { + ISO_1 = 1, + ISO_2 = 2, + V_3 = 3, + V_4 = 4, + Future = 100, + + Default = LanguageVersion.V_4, + } + + public enum RuntimeVersion + { + v1, + v2, + v4 + } + + public enum Target + { + Library, Exe, Module, WinExe + } + + public enum Platform + { + AnyCPU, X86, X64, IA64 + } + + public class CompilerSettings + { + public Target Target; + public Platform Platform; + public string TargetExt; + public bool VerifyClsCompliance; + public bool Optimize; + public LanguageVersion Version; + public bool EnhancedWarnings; + public bool LoadDefaultReferences; + public string SdkVersion; + + public string StrongNameKeyFile; + public string StrongNameKeyContainer; + public bool StrongNameDelaySign; + + // + // Assemblies references to be loaded + // + public List AssemblyReferences; + + // + // External aliases for assemblies + // + public List> AssemblyReferencesAliases; + + // + // Modules to be embedded + // + public List Modules; + + // + // Lookup paths for referenced assemblies + // + public List ReferencesLookupPaths; + + // + // Encoding. + // + public Encoding Encoding; + + // + // If set, enable XML documentation generation + // + public string DocumentationFile; + + public string MainClass; + + // + // Output file + // + public string OutputFile; + + // + // The default compiler checked state + // + public bool Checked; + + // + // If true, the compiler is operating in statement mode, + // this currently turns local variable declaration into + // static variables of a class + // + public bool StatementMode; // TODO: SUPER UGLY + + // + // Whether to allow Unsafe code + // + public bool Unsafe; + + public string Win32ResourceFile; + public string Win32IconFile; + + // + // A list of resource files for embedding + // + public List Resources; + + public bool GenerateDebugInfo; + + // Compiler debug flags only + public bool ParseOnly, TokenizeOnly, Timestamps; + public int DebugFlags; + + // + // Whether we are being linked against the standard libraries. + // This is only used to tell whether `System.Object' should + // have a base class or not. + // + public bool StdLib; + + public RuntimeVersion StdLibRuntimeVersion; + + readonly List conditional_symbols; + + readonly List source_files; + + public CompilerSettings () + { + StdLib = true; + Target = Target.Exe; + TargetExt = ".exe"; + Platform = Platform.AnyCPU; + Version = LanguageVersion.Default; + VerifyClsCompliance = true; + Optimize = true; + Encoding = Encoding.UTF8; + LoadDefaultReferences = true; + StdLibRuntimeVersion = RuntimeVersion.v4; + + AssemblyReferences = new List (); + AssemblyReferencesAliases = new List> (); + Modules = new List (); + ReferencesLookupPaths = new List (); + + conditional_symbols = new List (); + // + // Add default mcs define + // + conditional_symbols.Add ("__MonoCS__"); + + source_files = new List (); + } + + #region Properties + + public CompilationSourceFile FirstSourceFile { + get { + return source_files.Count > 0 ? source_files [0] : null; + } + } + + public bool HasKeyFileOrContainer { + get { + return StrongNameKeyFile != null || StrongNameKeyContainer != null; + } + } + + public bool NeedsEntryPoint { + get { + return Target == Target.Exe || Target == Target.WinExe; + } + } + + public List SourceFiles { + get { + return source_files; + } + } + + #endregion + + public void AddConditionalSymbol (string symbol) + { + if (!conditional_symbols.Contains (symbol)) + conditional_symbols.Add (symbol); + } + + public bool IsConditionalSymbolDefined (string symbol) + { + return conditional_symbols.Contains (symbol); + } + } + + public class CommandLineParser + { + enum ParseResult + { + Success, + Error, + Stop, + UnknownOption + } + + static readonly char[] argument_value_separator = new char[] { ';', ',' }; + static readonly char[] numeric_value_separator = new char[] { ';', ',', ' ' }; + + readonly Report report; + readonly TextWriter output; + bool stop_argument; + + Dictionary source_file_index; + + public event Func UnknownOptionHandler; + + public CommandLineParser (Report report) + : this (report, Console.Out) + { + } + + public CommandLineParser (Report report, TextWriter messagesOutput) + { + this.report = report; + this.output = messagesOutput; + } + + public bool HasBeenStopped { + get { + return stop_argument; + } + } + + void About () + { + output.WriteLine ( + "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" + + "The compiler source code is released under the terms of the \n" + + "MIT X11 or GNU GPL licenses\n\n" + + + "For more information on Mono, visit the project Web site\n" + + " http://www.mono-project.com\n\n" + + + "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto"); + } + + public CompilerSettings ParseArguments (string[] args) + { + CompilerSettings settings = new CompilerSettings (); + List response_file_list = null; + bool parsing_options = true; + stop_argument = false; + source_file_index = new Dictionary (); + + for (int i = 0; i < args.Length; i++) { + string arg = args[i]; + if (arg.Length == 0) + continue; + + if (arg[0] == '@') { + string[] extra_args; + string response_file = arg.Substring (1); + + if (response_file_list == null) + response_file_list = new List (); + + if (response_file_list.Contains (response_file)) { + report.Error (1515, "Response file `{0}' specified multiple times", response_file); + return null; + } + + response_file_list.Add (response_file); + + extra_args = LoadArgs (response_file); + if (extra_args == null) { + report.Error (2011, "Unable to open response file: " + response_file); + return null; + } + + args = AddArgs (args, extra_args); + continue; + } + + if (parsing_options) { + if (arg == "--") { + parsing_options = false; + continue; + } + + bool dash_opt = arg[0] == '-'; + bool slash_opt = arg[0] == '/'; + if (dash_opt) { + switch (ParseOptionUnix (arg, ref args, ref i, settings)) { + case ParseResult.Error: + case ParseResult.Success: + continue; + case ParseResult.Stop: + stop_argument = true; + return settings; + case ParseResult.UnknownOption: + if (UnknownOptionHandler != null) { + var ret = UnknownOptionHandler (args, i); + if (ret != -1) { + i = ret; + continue; + } + } + break; + } + } + + if (dash_opt || slash_opt) { + // Try a -CSCOPTION + string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg; + switch (ParseOption (csc_opt, ref args, settings)) { + case ParseResult.Error: + case ParseResult.Success: + continue; + case ParseResult.UnknownOption: + // Need to skip `/home/test.cs' however /test.cs is considered as error + if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0)) + break; + + if (UnknownOptionHandler != null) { + var ret = UnknownOptionHandler (args, i); + if (ret != -1) { + i = ret; + continue; + } + } + + Error_WrongOption (arg); + return null; + + case ParseResult.Stop: + stop_argument = true; + return settings; + } + } + } + + ProcessSourceFiles (arg, false, settings.SourceFiles); + } + + return settings; + } + + void ProcessSourceFiles (string spec, bool recurse, List sourceFiles) + { + string path, pattern; + + SplitPathAndPattern (spec, out path, out pattern); + if (pattern.IndexOf ('*') == -1) { + AddSourceFile (spec, sourceFiles); + return; + } + + string[] files = null; + try { + files = Directory.GetFiles (path, pattern); + } catch (System.IO.DirectoryNotFoundException) { + report.Error (2001, "Source file `" + spec + "' could not be found"); + return; + } catch (System.IO.IOException) { + report.Error (2001, "Source file `" + spec + "' could not be found"); + return; + } + foreach (string f in files) { + AddSourceFile (f, sourceFiles); + } + + if (!recurse) + return; + + string[] dirs = null; + + try { + dirs = Directory.GetDirectories (path); + } catch { + } + + foreach (string d in dirs) { + + // Don't include path in this string, as each + // directory entry already does + ProcessSourceFiles (d + "/" + pattern, true, sourceFiles); + } + } + + static string[] AddArgs (string[] args, string[] extra_args) + { + string[] new_args; + new_args = new string[extra_args.Length + args.Length]; + + // if args contains '--' we have to take that into account + // split args into first half and second half based on '--' + // and add the extra_args before -- + int split_position = Array.IndexOf (args, "--"); + if (split_position != -1) { + Array.Copy (args, new_args, split_position); + extra_args.CopyTo (new_args, split_position); + Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position); + } else { + args.CopyTo (new_args, 0); + extra_args.CopyTo (new_args, args.Length); + } + + return new_args; + } + + void AddAssemblyReference (string alias, string assembly, CompilerSettings settings) + { + if (assembly.Length == 0) { + report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias); + return; + } + + if (!IsExternAliasValid (alias)) { + report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias); + return; + } + + settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly)); + } + + void AddResource (AssemblyResource res, CompilerSettings settings) + { + if (settings.Resources == null) { + settings.Resources = new List (); + settings.Resources.Add (res); + return; + } + + if (settings.Resources.Contains (res)) { + report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name); + return; + } + + settings.Resources.Add (res); + } + + void AddSourceFile (string fileName, List sourceFiles) + { + string path = Path.GetFullPath (fileName); + + int index; + if (source_file_index.TryGetValue (path, out index)) { + string other_name = sourceFiles[index - 1].Name; + if (fileName.Equals (other_name)) + report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name); + else + report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path); + + return; + } + + var unit = new CompilationSourceFile (fileName, path, sourceFiles.Count + 1); + sourceFiles.Add (unit); + source_file_index.Add (path, unit.Index); + } + + void Error_RequiresArgument (string option) + { + report.Error (2006, "Missing argument for `{0}' option", option); + } + + void Error_RequiresFileName (string option) + { + report.Error (2005, "Missing file specification for `{0}' option", option); + } + + void Error_WrongOption (string option) + { + report.Error (2007, "Unrecognized command-line option: `{0}'", option); + } + + static bool IsExternAliasValid (string identifier) + { + if (identifier.Length == 0) + return false; + if (identifier[0] != '_' && !char.IsLetter (identifier[0])) + return false; + + for (int i = 1; i < identifier.Length; i++) { + char c = identifier[i]; + if (char.IsLetter (c) || char.IsDigit (c)) + continue; + + UnicodeCategory category = char.GetUnicodeCategory (c); + if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark || + category != UnicodeCategory.SpacingCombiningMark || + category != UnicodeCategory.ConnectorPunctuation) + return false; + } + + return true; + } + + static string[] LoadArgs (string file) + { + StreamReader f; + var args = new List (); + string line; + try { + f = new StreamReader (file); + } catch { + return null; + } + + StringBuilder sb = new StringBuilder (); + + while ((line = f.ReadLine ()) != null) { + int t = line.Length; + + for (int i = 0; i < t; i++) { + char c = line[i]; + + if (c == '"' || c == '\'') { + char end = c; + + for (i++; i < t; i++) { + c = line[i]; + + if (c == end) + break; + sb.Append (c); + } + } else if (c == ' ') { + if (sb.Length > 0) { + args.Add (sb.ToString ()); + sb.Length = 0; + } + } else + sb.Append (c); + } + if (sb.Length > 0) { + args.Add (sb.ToString ()); + sb.Length = 0; + } + } + + return args.ToArray (); + } + + void OtherFlags () + { + output.WriteLine ( + "Other flags in the compiler\n" + + " --fatal[=COUNT] Makes errors after COUNT fatal\n" + + " --lint Enhanced warnings\n" + + " --parse Only parses the source file\n" + + " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" + + " --stacktrace Shows stack trace at error location\n" + + " --timestamp Displays time stamps of various compiler events\n" + + " -v Verbose parsing (for debugging the parser)\n" + + " --mcs-debug X Sets MCS debugging level to X\n"); + } + + // + // This parses the -arg and /arg options to the compiler, even if the strings + // in the following text use "/arg" on the strings. + // + ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings) + { + int idx = option.IndexOf (':'); + string arg, value; + + if (idx == -1) { + arg = option; + value = ""; + } else { + arg = option.Substring (0, idx); + + value = option.Substring (idx + 1); + } + + switch (arg.ToLowerInvariant ()) { + case "/nologo": + return ParseResult.Success; + + case "/t": + case "/target": + switch (value) { + case "exe": + settings.Target = Target.Exe; + break; + + case "winexe": + settings.Target = Target.WinExe; + break; + + case "library": + settings.Target = Target.Library; + settings.TargetExt = ".dll"; + break; + + case "module": + settings.Target = Target.Module; + settings.TargetExt = ".netmodule"; + break; + + default: + report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'"); + return ParseResult.Error; + } + return ParseResult.Success; + + case "/out": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + settings.OutputFile = value; + return ParseResult.Success; + + case "/o": + case "/o+": + case "/optimize": + case "/optimize+": + settings.Optimize = true; + return ParseResult.Success; + + case "/o-": + case "/optimize-": + settings.Optimize = false; + return ParseResult.Success; + + // TODO: Not supported by csc 3.5+ + case "/incremental": + case "/incremental+": + case "/incremental-": + // nothing. + return ParseResult.Success; + + case "/d": + case "/define": { + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + foreach (string d in value.Split (argument_value_separator)) { + string conditional = d.Trim (); + if (!Tokenizer.IsValidIdentifier (conditional)) { + report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional); + continue; + } + + settings.AddConditionalSymbol (conditional); + } + return ParseResult.Success; + } + + case "/bugreport": + // + // We should collect data, runtime, etc and store in the file specified + // + output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs"); + return ParseResult.Success; + + case "/pkg": { + string packages; + + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' })); + string pkgout = Driver.GetPackageFlags (packages, report); + + if (pkgout == null) + return ParseResult.Error; + + string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' }); + args = AddArgs (args, xargs); + return ParseResult.Success; + } + + case "/linkres": + case "/linkresource": + case "/res": + case "/resource": + AssemblyResource res = null; + string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries); + switch (s.Length) { + case 1: + if (s[0].Length == 0) + goto default; + res = new AssemblyResource (s[0], Path.GetFileName (s[0])); + break; + case 2: + res = new AssemblyResource (s[0], s[1]); + break; + case 3: + if (s[2] != "public" && s[2] != "private") { + report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]); + return ParseResult.Error; + } + res = new AssemblyResource (s[0], s[1], s[2] == "private"); + break; + default: + report.Error (-2005, "Wrong number of arguments for option `{0}'", option); + return ParseResult.Error; + } + + if (res != null) { + res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R'; + AddResource (res, settings); + } + + return ParseResult.Success; + + case "/recurse": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + ProcessSourceFiles (value, true, settings.SourceFiles); + return ParseResult.Success; + + case "/r": + case "/reference": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + string[] refs = value.Split (argument_value_separator); + foreach (string r in refs) { + if (r.Length == 0) + continue; + + string val = r; + int index = val.IndexOf ('='); + if (index > -1) { + string alias = r.Substring (0, index); + string assembly = r.Substring (index + 1); + AddAssemblyReference (alias, assembly, settings); + if (refs.Length != 1) { + report.Error (2034, "Cannot specify multiple aliases using single /reference option"); + return ParseResult.Error; + } + } else { + settings.AssemblyReferences.Add (val); + } + } + return ParseResult.Success; + } + case "/addmodule": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + string[] refs = value.Split (argument_value_separator); + foreach (string r in refs) { + settings.Modules.Add (r); + } + return ParseResult.Success; + } + case "/win32res": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + if (settings.Win32IconFile != null) + report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); + + settings.Win32ResourceFile = value; + return ParseResult.Success; + } + case "/win32icon": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + if (settings.Win32ResourceFile != null) + report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); + + settings.Win32IconFile = value; + return ParseResult.Success; + } + case "/doc": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + settings.DocumentationFile = value; + return ParseResult.Success; + } + case "/lib": { + string[] libdirs; + + if (value.Length == 0) { + return ParseResult.Error; + } + + libdirs = value.Split (argument_value_separator); + foreach (string dir in libdirs) + settings.ReferencesLookupPaths.Add (dir); + return ParseResult.Success; + } + + case "/debug-": + settings.GenerateDebugInfo = false; + return ParseResult.Success; + + case "/debug": + if (value == "full" || value == "") + settings.GenerateDebugInfo = true; + + return ParseResult.Success; + + case "/debug+": + settings.GenerateDebugInfo = true; + return ParseResult.Success; + + case "/checked": + case "/checked+": + settings.Checked = true; + return ParseResult.Success; + + case "/checked-": + settings.Checked = false; + return ParseResult.Success; + + case "/clscheck": + case "/clscheck+": + settings.VerifyClsCompliance = true; + return ParseResult.Success; + + case "/clscheck-": + settings.VerifyClsCompliance = false; + return ParseResult.Success; + + case "/unsafe": + case "/unsafe+": + settings.Unsafe = true; + return ParseResult.Success; + + case "/unsafe-": + settings.Unsafe = false; + return ParseResult.Success; + + case "/warnaserror": + case "/warnaserror+": + if (value.Length == 0) { + report.WarningsAreErrors = true; + } else { + foreach (string wid in value.Split (numeric_value_separator)) + report.AddWarningAsError (wid); + } + return ParseResult.Success; + + case "/warnaserror-": + if (value.Length == 0) { + report.WarningsAreErrors = false; + } else { + foreach (string wid in value.Split (numeric_value_separator)) + report.RemoveWarningAsError (wid); + } + return ParseResult.Success; + + case "/warn": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + SetWarningLevel (value); + return ParseResult.Success; + + case "/nowarn": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + var warns = value.Split (numeric_value_separator); + foreach (string wc in warns) { + try { + if (wc.Trim ().Length == 0) + continue; + + int warn = Int32.Parse (wc); + if (warn < 1) { + throw new ArgumentOutOfRangeException ("warn"); + } + report.SetIgnoreWarning (warn); + } catch { + report.Error (1904, "`{0}' is not a valid warning number", wc); + return ParseResult.Error; + } + } + return ParseResult.Success; + + case "/noconfig": + settings.LoadDefaultReferences = false; + return ParseResult.Success; + + case "/platform": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value.ToLower (CultureInfo.InvariantCulture)) { + case "anycpu": + settings.Platform = Platform.AnyCPU; + break; + case "x86": + settings.Platform = Platform.X86; + break; + case "x64": + settings.Platform = Platform.X64; + break; + case "itanium": + settings.Platform = Platform.IA64; + break; + default: + report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'"); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "/sdk": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + settings.SdkVersion = value; + return ParseResult.Success; + + // We just ignore this. + case "/errorreport": + case "/filealign": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "/helpinternal": + OtherFlags (); + return ParseResult.Stop; + + case "/help": + case "/?": + Usage (); + return ParseResult.Stop; + + case "/main": + case "/m": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + settings.MainClass = value; + return ParseResult.Success; + + case "/nostdlib": + case "/nostdlib+": + settings.StdLib = false; + return ParseResult.Success; + + case "/nostdlib-": + settings.StdLib = true; + return ParseResult.Success; + + case "/fullpaths": + report.Printer.ShowFullPaths = true; + return ParseResult.Success; + + case "/keyfile": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + settings.StrongNameKeyFile = value; + return ParseResult.Success; + + case "/keycontainer": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + settings.StrongNameKeyContainer = value; + return ParseResult.Success; + + case "/delaysign+": + case "/delaysign": + settings.StrongNameDelaySign = true; + return ParseResult.Success; + + case "/delaysign-": + settings.StrongNameDelaySign = false; + return ParseResult.Success; + + case "/langversion": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value.ToLowerInvariant ()) { + case "iso-1": + settings.Version = LanguageVersion.ISO_1; + return ParseResult.Success; + case "default": + settings.Version = LanguageVersion.Default; + return ParseResult.Success; + case "iso-2": + settings.Version = LanguageVersion.ISO_2; + return ParseResult.Success; + case "3": + settings.Version = LanguageVersion.V_3; + return ParseResult.Success; + case "future": + settings.Version = LanguageVersion.Future; + return ParseResult.Success; + } + + report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value); + return ParseResult.Error; + + case "/codepage": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value) { + case "utf8": + settings.Encoding = Encoding.UTF8; + break; + case "reset": + settings.Encoding = Encoding.Default; + break; + default: + try { + settings.Encoding = Encoding.GetEncoding (int.Parse (value)); + } catch { + report.Error (2016, "Code page `{0}' is invalid or not installed", value); + } + return ParseResult.Error; + } + return ParseResult.Success; + + default: + return ParseResult.UnknownOption; + } + } + + // + // Currently handles the Unix-like command line options, but will be + // deprecated in favor of the CSCParseOption, which will also handle the + // options that start with a dash in the future. + // + ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings) + { + switch (arg){ + case "-v": + CSharpParser.yacc_verbose_flag++; + return ParseResult.Success; + + case "--version": + Version (); + return ParseResult.Stop; + + case "--parse": + settings.ParseOnly = true; + return ParseResult.Success; + + case "--main": case "-m": + report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.MainClass = args[++i]; + return ParseResult.Success; + + case "--unsafe": + report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe"); + settings.Unsafe = true; + return ParseResult.Success; + + case "/?": case "/h": case "/help": + case "--help": + Usage (); + return ParseResult.Stop; + + case "--define": + report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + settings.AddConditionalSymbol (args [++i]); + return ParseResult.Success; + + case "--tokenize": + settings.TokenizeOnly = true; + return ParseResult.Success; + + case "-o": + case "--output": + report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.OutputFile = args[++i]; + return ParseResult.Success; + + case "--checked": + report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked"); + settings.Checked = true; + return ParseResult.Success; + + case "--stacktrace": + report.Printer.Stacktrace = true; + return ParseResult.Success; + + case "--linkresource": + case "--linkres": + report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + AddResource (new AssemblyResource (args[++i], args[i]), settings); + return ParseResult.Success; + + case "--resource": + case "--res": + report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + AddResource (new AssemblyResource (args[++i], args[i], true), settings); + return ParseResult.Success; + + case "--target": + report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + string type = args [++i]; + switch (type){ + case "library": + settings.Target = Target.Library; + settings.TargetExt = ".dll"; + break; + + case "exe": + settings.Target = Target.Exe; + break; + + case "winexe": + settings.Target = Target.WinExe; + break; + + case "module": + settings.Target = Target.Module; + settings.TargetExt = ".dll"; + break; + default: + report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'"); + break; + } + return ParseResult.Success; + + case "-r": + report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + string val = args [++i]; + int idx = val.IndexOf ('='); + if (idx > -1) { + string alias = val.Substring (0, idx); + string assembly = val.Substring (idx + 1); + AddAssemblyReference (alias, assembly, settings); + return ParseResult.Success; + } + + settings.AssemblyReferences.Add (val); + return ParseResult.Success; + + case "-L": + report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.ReferencesLookupPaths.Add (args [++i]); + return ParseResult.Success; + + case "--lint": + settings.EnhancedWarnings = true; + return ParseResult.Success; + + case "--nostdlib": + report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib"); + settings.StdLib = false; + return ParseResult.Success; + + case "--nowarn": + report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + int warn = 0; + + try { + warn = int.Parse (args [++i]); + } catch { + Usage (); + Environment.Exit (1); + } + report.SetIgnoreWarning (warn); + return ParseResult.Success; + + case "--wlevel": + report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + SetWarningLevel (args [++i]); + return ParseResult.Success; + + case "--mcs-debug": + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + try { + settings.DebugFlags = int.Parse (args [++i]); + } catch { + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "--about": + About (); + return ParseResult.Stop; + + case "--recurse": + report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + ProcessSourceFiles (args [++i], true, settings.SourceFiles); + return ParseResult.Success; + + case "--timestamp": + settings.Timestamps = true; + return ParseResult.Success; + + case "--debug": case "-g": + report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug"); + settings.GenerateDebugInfo = true; + return ParseResult.Success; + + case "--noconfig": + report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig"); + settings.LoadDefaultReferences = false; + return ParseResult.Success; + + default: + if (arg.StartsWith ("--fatal")){ + int fatal = 1; + if (arg.StartsWith ("--fatal=")) + int.TryParse (arg.Substring (8), out fatal); + + report.Printer.FatalCounter = fatal; + return ParseResult.Success; + } + if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) { + string version = arg.Substring (10); + + switch (version) { + case "v1": + case "V1": + settings.StdLibRuntimeVersion = RuntimeVersion.v1; + break; + case "v2": + case "V2": + settings.StdLibRuntimeVersion = RuntimeVersion.v2; + break; + case "v4": + case "V4": + settings.StdLibRuntimeVersion = RuntimeVersion.v4; + break; + } + return ParseResult.Success; + } + + return ParseResult.UnknownOption; + } + } + + void SetWarningLevel (string s) + { + int level = -1; + + try { + level = int.Parse (s); + } catch { + } + if (level < 0 || level > 4) { + report.Error (1900, "Warning level must be in the range 0-4"); + return; + } + report.WarningLevel = level; + } + + // + // Given a path specification, splits the path from the file/pattern + // + static void SplitPathAndPattern (string spec, out string path, out string pattern) + { + int p = spec.LastIndexOf ('/'); + if (p != -1) { + // + // Windows does not like /file.cs, switch that to: + // "\", "file.cs" + // + if (p == 0) { + path = "\\"; + pattern = spec.Substring (1); + } else { + path = spec.Substring (0, p); + pattern = spec.Substring (p + 1); + } + return; + } + + p = spec.LastIndexOf ('\\'); + if (p != -1) { + path = spec.Substring (0, p); + pattern = spec.Substring (p + 1); + return; + } + + path = "."; + pattern = spec; + } + + void Usage () + { + output.WriteLine ( + "Mono C# compiler, Copyright 2001 - 2011 Novell, Inc.\n" + + "mcs [options] source-files\n" + + " --about About the Mono C# compiler\n" + + " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" + + " -checked[+|-] Sets default aritmetic overflow context\n" + + " -clscheck[+|-] Disables CLS Compliance verifications\n" + + " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" + + " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" + + " -debug[+|-], -g Generate debugging information\n" + + " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" + + " -doc:FILE Process documentation comments to XML file\n" + + " -fullpaths Any issued error or warning uses absolute file path\n" + + " -help Lists all compiler options (short: -?)\n" + + " -keycontainer:NAME The key pair container used to sign the output assembly\n" + + " -keyfile:FILE The key file used to strongname the ouput assembly\n" + + " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, Default or Future\n" + + " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" + + " -main:CLASS Specifies the class with the Main method (short: -m)\n" + + " -noconfig Disables implicitly referenced assemblies\n" + + " -nostdlib[+|-] Does not reference mscorlib.dll library\n" + + " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" + + " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" + + " -out:FILE Specifies output assembly name\n" + + " -pkg:P1[,Pn] References packages P1..Pn\n" + + " -platform:ARCH Specifies the target platform of the output assembly\n" + + " ARCH can be one of: anycpu, x86, x64 or itanium\n" + + " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" + + " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" + + " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" + + " -sdk:VERSION Specifies SDK version of referenced assemblies\n" + + " VERSION can be one of: 2, 4 (default) or custom value\n" + + " -target:KIND Specifies the format of the output assembly (short: -t)\n" + + " KIND can be one of: exe, winexe, library, module\n" + + " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" + + " -warnaserror[+|-] Treats all warnings as errors\n" + + " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" + + " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" + + " -helpinternal Shows internal and advanced compiler options\n" + + "\n" + + "Resources:\n" + + " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" + + " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" + + " -win32res:FILE Specifies Win32 resource file (.res)\n" + + " -win32icon:FILE Use this icon for the output\n" + + " @file Read response file for more options\n\n" + + "Options can be of the form -option or /option"); + } + + void Version () + { + string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString (); + output.WriteLine ("Mono C# compiler version {0}", version); + } + } + + public class RootContext + { + // + // Contains the parsed tree + // + static ModuleContainer root; + + static public ModuleContainer ToplevelTypes { + get { return root; } + set { root = value; } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs new file mode 100644 index 0000000000..df7962043c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs @@ -0,0 +1,621 @@ +// +// roottypes.cs: keeps a tree representation of the generated code +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Mono.CompilerServices.SymbolWriter; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // Module (top-level type) container + // + public sealed class ModuleContainer : TypeContainer + { +#if STATIC + // + // Compiler generated container for static data + // + sealed class StaticDataContainer : CompilerGeneratedClass + { + readonly Dictionary size_types; + new int fields; + + public StaticDataContainer (ModuleContainer module) + : base (module, new MemberName ("" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC) + { + size_types = new Dictionary (); + } + + public override void CloseType () + { + base.CloseType (); + + foreach (var entry in size_types) { + entry.Value.CloseType (); + } + } + + public FieldSpec DefineInitializedData (byte[] data, Location loc) + { + Struct size_type; + if (!size_types.TryGetValue (data.Length, out size_type)) { + // + // Build common type for this data length. We cannot use + // DefineInitializedData because it creates public type, + // and its name is not unique among modules + // + size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null); + size_type.CreateType (); + size_type.DefineType (); + + size_types.Add (data.Length, size_type); + + // It has to work even if StructLayoutAttribute does not exist + size_type.TypeBuilder.__SetLayout (1, data.Length); + } + + var name = "$field-" + fields.ToString ("X"); + ++fields; + const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL; + var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA); + fbuilder.__SetDataAndRVA (data); + + return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod); + } + } + + StaticDataContainer static_data; + + // + // Makes const data field inside internal type container + // + public FieldSpec MakeStaticData (byte[] data, Location loc) + { + if (static_data == null) { + static_data = new StaticDataContainer (this); + static_data.CreateType (); + static_data.DefineType (); + + AddCompilerGeneratedClass (static_data); + } + + return static_data.DefineInitializedData (data, loc); + } +#endif + + public CharSet? DefaultCharSet; + public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass; + + readonly Dictionary> anonymous_types; + readonly Dictionary array_types; + readonly Dictionary pointer_types; + readonly Dictionary reference_types; + readonly Dictionary attrs_cache; + + // Used for unique namespaces/types during parsing + Dictionary defined_type_containers; + + AssemblyDefinition assembly; + readonly CompilerContext context; + readonly RootNamespace global_ns; + readonly Dictionary alias_ns; + + ModuleBuilder builder; + + bool has_extenstion_method; + + PredefinedAttributes predefined_attributes; + PredefinedTypes predefined_types; + PredefinedMembers predefined_members; + + static readonly string[] attribute_targets = new string[] { "assembly", "module" }; + + public ModuleContainer (CompilerContext context) + : base (null, null, MemberName.Null, null, 0) + { + this.context = context; + + caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected); + + types = new List (); + anonymous_types = new Dictionary> (); + global_ns = new GlobalRootNamespace (); + alias_ns = new Dictionary (); + array_types = new Dictionary (); + pointer_types = new Dictionary (); + reference_types = new Dictionary (); + attrs_cache = new Dictionary (); + + defined_type_containers = new Dictionary (); + } + + #region Properties + + internal Dictionary ArrayTypesCache { + get { + return array_types; + } + } + + // + // Cache for parameter-less attributes + // + internal Dictionary AttributeConstructorCache { + get { + return attrs_cache; + } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Assembly; + } + } + + public ModuleBuilder Builder { + get { + return builder; + } + } + + public override CompilerContext Compiler { + get { + return context; + } + } + + public override AssemblyDefinition DeclaringAssembly { + get { + return assembly; + } + } + + internal DocumentationBuilder DocumentationBuilder { + get; set; + } + + public Evaluator Evaluator { + get; set; + } + + public bool HasDefaultCharSet { + get { + return DefaultCharSet.HasValue; + } + } + + public bool HasExtensionMethod { + get { + return has_extenstion_method; + } + set { + has_extenstion_method = value; + } + } + + public bool HasTypesFullyDefined { + get; set; + } + + // + // Returns module global:: namespace + // + public RootNamespace GlobalRootNamespace { + get { + return global_ns; + } + } + + public override ModuleContainer Module { + get { + return this; + } + } + + internal Dictionary PointerTypesCache { + get { + return pointer_types; + } + } + + internal PredefinedAttributes PredefinedAttributes { + get { + return predefined_attributes; + } + } + + internal PredefinedMembers PredefinedMembers { + get { + return predefined_members; + } + } + + internal PredefinedTypes PredefinedTypes { + get { + return predefined_types; + } + } + + internal Dictionary ReferenceTypesCache { + get { + return reference_types; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public void AddAnonymousType (AnonymousTypeClass type) + { + List existing; + if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing)) + if (existing == null) { + existing = new List (); + anonymous_types.Add (type.Parameters.Count, existing); + } + + existing.Add (type); + } + + public void AddAttribute (Attribute attr, IMemberContext context) + { + attr.AttachTo (this, context); + + if (attributes == null) { + attributes = new Attributes (attr); + return; + } + + attributes.AddAttribute (attr); + } + + public override TypeContainer AddPartial (TypeContainer nextPart) + { + return AddPartial (nextPart, nextPart.Name); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Assembly) { + assembly.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Type == pa.DefaultCharset) { + switch (a.GetCharSetValue ()) { + case CharSet.Ansi: + case CharSet.None: + break; + case CharSet.Auto: + DefaultCharSet = CharSet.Auto; + DefaultCharSetType = TypeAttributes.AutoClass; + break; + case CharSet.Unicode: + DefaultCharSet = CharSet.Unicode; + DefaultCharSetType = TypeAttributes.UnicodeClass; + break; + default: + Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid", + a.GetSignatureForError ()); + break; + } + } else if (a.Type == pa.CLSCompliant) { + Attribute cls = DeclaringAssembly.CLSCompliantAttribute; + if (cls == null) { + Report.Warning (3012, 1, a.Location, + "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking"); + } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) { + Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ()); + Report.Warning (3017, 1, a.Location, + "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly"); + return; + } + } + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override void CloseType () + { + foreach (TypeContainer tc in types) { + tc.CloseType (); + } + + if (compiler_generated != null) + foreach (CompilerGeneratedClass c in compiler_generated) + c.CloseType (); + } + + public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize) + { + return builder.DefineType (name, attr, null, typeSize); + } + + // + // Creates alias global namespace + // + public RootNamespace CreateRootNamespace (string alias) + { + if (alias == global_ns.Alias) { + NamespaceContainer.Error_GlobalNamespaceRedefined (Location.Null, Report); + return global_ns; + } + + RootNamespace rn; + if (!alias_ns.TryGetValue (alias, out rn)) { + rn = new RootNamespace (alias); + alias_ns.Add (alias, rn); + } + + return rn; + } + + public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder) + { + this.assembly = assembly; + builder = moduleBuilder; + } + + public new void CreateType () + { + // Release cache used by parser only + if (Evaluator == null) + defined_type_containers = null; + else + defined_type_containers.Clear (); + + foreach (TypeContainer tc in types) + tc.CreateType (); + } + + public new void Define () + { + foreach (TypeContainer tc in types) + tc.DefineType (); + + foreach (TypeContainer tc in types) + tc.ResolveTypeParameters (); + + foreach (TypeContainer tc in types) { + try { + tc.Define (); + } catch (Exception e) { + throw new InternalErrorException (tc, e); + } + } + + HasTypesFullyDefined = true; + } + + public override void Emit () + { + if (OptAttributes != null) + OptAttributes.Emit (); + + if (Compiler.Settings.Unsafe) { + var pa = PredefinedAttributes.UnverifiableCode; + if (pa.IsDefined) + pa.EmitAttribute (builder); + } + + foreach (var tc in types) + tc.DefineConstants (); + + foreach (TypeContainer tc in types) + tc.EmitType (); + + if (Compiler.Report.Errors > 0) + return; + + foreach (TypeContainer tc in types) + tc.VerifyMembers (); + + if (compiler_generated != null) + foreach (var c in compiler_generated) + c.EmitType (); + } + + internal override void GenerateDocComment (DocumentationBuilder builder) + { + foreach (var tc in types) + tc.GenerateDocComment (builder); + } + + public AnonymousTypeClass GetAnonymousType (IList parameters) + { + List candidates; + if (!anonymous_types.TryGetValue (parameters.Count, out candidates)) + return null; + + int i; + foreach (AnonymousTypeClass at in candidates) { + for (i = 0; i < parameters.Count; ++i) { + if (!parameters [i].Equals (at.Parameters [i])) + break; + } + + if (i == parameters.Count) + return at; + } + + return null; + } + + public RootNamespace GetRootNamespace (string name) + { + RootNamespace rn; + alias_ns.TryGetValue (name, out rn); + return rn; + } + + public override string GetSignatureForError () + { + return ""; + } + + public void InitializePredefinedTypes () + { + predefined_attributes = new PredefinedAttributes (this); + predefined_types = new PredefinedTypes (this); + predefined_members = new PredefinedMembers (this); + } + + public override bool IsClsComplianceRequired () + { + return DeclaringAssembly.IsCLSCompliant; + } + + protected override bool AddMemberType (TypeContainer tc) + { + if (AddTypesContainer (tc)) { + if ((tc.ModFlags & Modifiers.PARTIAL) != 0) + defined_names.Add (tc.Name, tc); + + tc.NamespaceEntry.NS.AddType (this, tc.Definition); + return true; + } + + return false; + } + + public bool AddTypesContainer (ITypesContainer container) + { + var mn = container.MemberName; + ITypesContainer found; + if (!defined_type_containers.TryGetValue (mn, out found)) { + defined_type_containers.Add (mn, container); + return true; + } + + if (container is NamespaceContainer && found is NamespaceContainer) + return true; + + var container_tc = container as TypeContainer; + var found_tc = found as TypeContainer; + if (container_tc != null && found_tc != null && container_tc.Kind == found_tc.Kind) { + if ((found_tc.ModFlags & container_tc.ModFlags & Modifiers.PARTIAL) != 0) { + return false; + } + + if (((found_tc.ModFlags | container_tc.ModFlags) & Modifiers.PARTIAL) != 0) { + Report.SymbolRelatedToPreviousError (found_tc); + Error_MissingPartialModifier (container_tc); + return false; + } + } + + string ns = mn.Left != null ? mn.Left.GetSignatureForError () : Module.GlobalRootNamespace.GetSignatureForError (); + mn = new MemberName (mn.Name, mn.TypeArguments, mn.Location); + + Report.SymbolRelatedToPreviousError (found.Location, ""); + Report.Error (101, container.Location, + "The namespace `{0}' already contains a definition for `{1}'", + ns, mn.GetSignatureForError ()); + return false; + } + + protected override void RemoveMemberType (TypeContainer ds) + { + defined_type_containers.Remove (ds.MemberName); + ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename); + base.RemoveMemberType (ds); + } + + public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type) + { + Attribute a = OptAttributes.Search ("assembly", a_type); + if (a != null) { + a.Resolve (); + } + return a; + } + + public void SetDeclaringAssembly (AssemblyDefinition assembly) + { + // TODO: This setter is quite ugly but I have not found a way around it yet + this.assembly = assembly; + } + } + + sealed class RootDeclSpace : TypeContainer { + public RootDeclSpace (ModuleContainer module, NamespaceContainer ns) + : base (ns, null, MemberName.Null, null, 0) + { + PartialContainer = module; + } + + public override AttributeTargets AttributeTargets { + get { throw new InternalErrorException ("should not be called"); } + } + + public override CompilerContext Compiler { + get { + return PartialContainer.Compiler; + } + } + + public override string DocCommentHeader { + get { throw new InternalErrorException ("should not be called"); } + } + + public override void DefineType () + { + throw new InternalErrorException ("should not be called"); + } + + public override ModuleContainer Module { + get { + return PartialContainer.Module; + } + } + + public override void Accept (StructuralVisitor visitor) + { + throw new InternalErrorException ("should not be called"); + } + + public override bool IsClsComplianceRequired () + { + return PartialContainer.IsClsComplianceRequired (); + } + + public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return null; + } + + public override FullNamedExpression LookupNamespaceAlias (string name) + { + return NamespaceEntry.LookupNamespaceAlias (name); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources new file mode 100644 index 0000000000..208d2eee29 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources @@ -0,0 +1,53 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +driver.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc-bootstrap.cs +dynamic.cs +enum.cs +ecore.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml new file mode 100644 index 0000000000..92fc799bbd --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml @@ -0,0 +1,384 @@ +../build/common/MonoTODOAttribute.cs +../build/common/Locale.cs +../class/System.XML/Mono.Xml.Schema/XmlSchemaValidatingReader.cs +../class/System.XML/Mono.Xml.Schema/XsdIdentityPath.cs +../class/System.XML/Mono.Xml.Schema/XsdIdentityState.cs +../class/System.XML/Mono.Xml.Schema/XsdKeyTable.cs +../class/System.XML/Mono.Xml.Schema/XsdParticleValidationState.cs +../class/System.XML/Mono.Xml.Schema/XsdValidatingReader.cs +../class/System.XML/Mono.Xml.Schema/XsdWildcard.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNode2.cs +../class/System.XML/Mono.Xml.XPath/IdPattern.cs +../class/System.XML/Mono.Xml.XPath/KeyPattern.cs +../class/System.XML/Mono.Xml.XPath/LocationPathPattern.cs +../class/System.XML/Mono.Xml.XPath/Pattern.cs +../class/System.XML/Mono.Xml.XPath/UnionPattern.cs +../class/System.XML/Mono.Xml.XPath/XPathEditableDocument.cs +../class/System.XML/Mono.Xml.XPath/XPathNavigatorReader.cs +../class/System.XML/Mono.Xml/IHasXmlParserContext.cs +../class/System.XML/Mono.Xml/IHasXmlSchemaInfo.cs +../class/System.XML/Mono.Xml/SubtreeXmlReader.cs +../class/System.XML/Mono.Xml/XmlFilterReader.cs +../class/System.XML/Mono.Xml/XmlNodeWriter.cs +../class/System.XML/System.Xml/ConformanceLevel.cs +../class/System.XML/System.Xml/DTDAutomata.cs +../class/System.XML/System.Xml/DTDObjectModel.cs +../class/System.XML/System.Xml/DTDReader.cs +../class/System.XML/System.Xml/DTDValidatingReader2.cs +../class/System.XML/System.Xml/EntityResolvingXmlReader.cs +../class/System.XML/System.Xml/EntityHandling.cs +../class/System.XML/System.Xml/Formatting.cs +../class/System.XML/System.Xml/IHasXmlNode.cs +../class/System.XML/System.Xml/IXmlLineInfo.cs +../class/System.XML/System.Xml/IHasXmlChildNode.cs +../class/System.XML/System.Xml/IXmlNamespaceResolver.cs +../class/System.XML/System.Xml/MonoFIXAttribute.cs +../class/System.XML/System.Xml/NameTable.cs +../class/System.XML/System.Xml/NewLineHandling.cs +../class/System.XML/System.Xml/ReadState.cs +../class/System.XML/System.Xml/ValidationType.cs +../class/System.XML/System.Xml/WhitespaceHandling.cs +../class/System.XML/System.Xml/WriteState.cs +../class/System.XML/System.Xml/XmlEntity.cs +../class/System.XML/System.Xml/XmlAttribute.cs +../class/System.XML/System.Xml/XmlAttributeCollection.cs +../class/System.XML/System.Xml/XmlCDataSection.cs +../class/System.XML/System.Xml/XmlConstructs.cs +../class/System.XML/System.Xml/XmlChar.cs +../class/System.XML/System.Xml/XmlCharacterData.cs +../class/System.XML/System.Xml/XmlComment.cs +../class/System.XML/System.Xml/XmlNotation.cs +../class/System.XML/System.Xml/XmlDeclaration.cs +../class/System.XML/System.Xml/XmlDocument.cs +../class/System.XML/System.Xml/XmlDocumentFragment.cs +../class/System.XML/System.Xml/XmlDocumentNavigator.cs +../class/System.XML/System.Xml/XmlDocumentType.cs +../class/System.XML/System.Xml/XmlElement.cs +../class/System.XML/System.Xml/XmlEntityReference.cs +../class/System.XML/System.Xml/XmlException.cs +../class/System.XML/System.Xml/XmlImplementation.cs +../class/System.XML/System.Xml/XmlConvert.cs +../class/System.XML/System.Xml/XmlDateTimeSerializationMode.cs +../class/System.XML/System.Xml/XmlLinkedNode.cs +../class/System.XML/System.Xml/XmlNameEntry.cs +../class/System.XML/System.Xml/XmlNameEntryCache.cs +../class/System.XML/System.Xml/XmlNameTable.cs +../class/System.XML/System.Xml/XmlNamedNodeMap.cs +../class/System.XML/System.Xml/XmlNamespaceScope.cs +../class/System.XML/System.Xml/XmlNamespaceManager.cs +../class/System.XML/System.Xml/XmlNode.cs +../class/System.XML/System.Xml/XmlNodeChangedAction.cs +../class/System.XML/System.Xml/XmlNodeChangedEventArgs.cs +../class/System.XML/System.Xml/XmlNodeChangedEventHandler.cs +../class/System.XML/System.Xml/XmlNodeList.cs +../class/System.XML/System.Xml/XmlNodeListChildren.cs +../class/System.XML/System.Xml/XmlNodeArrayList.cs +../class/System.XML/System.Xml/XmlIteratorNodeList.cs +../class/System.XML/System.Xml/XmlNodeOrder.cs +../class/System.XML/System.Xml/XmlNodeReader2.cs +../class/System.XML/System.Xml/XmlNodeReaderImpl.cs +../class/System.XML/System.Xml/XmlNodeType.cs +../class/System.XML/System.Xml/XmlOutputMethod.cs +../class/System.XML/System.Xml/XmlParserContext.cs +../class/System.XML/System.Xml/XmlProcessingInstruction.cs +../class/System.XML/System.Xml/XmlQualifiedName.cs +../class/System.XML/System.Xml/XmlReader.cs +../class/System.XML/System.Xml/XmlReaderBinarySupport.cs +../class/System.XML/System.Xml/XmlReaderSettings.cs +../class/System.XML/System.Xml/XmlResolver.cs +../class/System.XML/System.Xml/XmlSecureResolver.cs +../class/System.XML/System.Xml/XmlSignificantWhitespace.cs +../class/System.XML/System.Xml/XmlSpace.cs +../class/System.XML/System.Xml/XmlText.cs +../class/System.XML/System.Xml/XmlTextReader.cs +../class/System.XML/System.Xml/XmlTextReader2.cs +../class/System.XML/System.Xml/XmlTokenizedType.cs +../class/System.XML/System.Xml/XmlUrlResolver.cs +../class/System.XML/System.Xml/XmlValidatingReader.cs +../class/System.XML/System.Xml/XmlWhitespace.cs +../class/System.XML/System.Xml/XmlWriter.cs +../class/System.XML/System.Xml/XmlWriterSettings.cs +../class/System.XML/System.Xml/XmlTextWriter2.cs +../class/System.XML/System.Xml/XmlInputStream.cs +../class/System.XML/System.Xml/XmlParserInput.cs +../class/System.XML/System.Xml.XPath/IXPathNavigable.cs +../class/System.XML/System.Xml.XPath/XPathNavigator.cs +../class/System.XML/System.Xml.XPath/XPathExpression.cs +../class/System.XML/System.Xml.XPath/XPathItem.cs +../class/System.XML/System.Xml.XPath/XPathNamespaceScope.cs +../class/System.XML/System.Xml.XPath/XPathNodeIterator.cs +../class/System.XML/System.Xml.XPath/XPathResultType.cs +../class/System.XML/System.Xml.XPath/XPathNodeType.cs +../class/System.XML/System.Xml.XPath/XmlDataType.cs +../class/System.XML/System.Xml.XPath/XmlSortOrder.cs +../class/System.XML/System.Xml.XPath/XmlCaseOrder.cs +../class/System.XML/System.Xml.XPath/XPathDocument.cs +../class/System.XML/System.Xml.XPath/XPathException.cs +../class/System.XML/System.Xml.XPath/XPathComparer.cs +../class/System.XML/System.Xml.XPath/DefaultContext.cs +../class/System.XML/System.Xml.XPath/Expression.cs +../class/System.XML/System.Xml.XPath/Iterator.cs +../class/System.XML/System.Xml.XPath/Tokenizer.cs +../class/System.XML/System.Xml.XPath/Parser.cs +../class/System.XML/System.Xml.Schema/BuiltInDatatype.cs +../class/System.XML/System.Xml.Schema/IXmlSchemaInfo.cs +../class/System.XML/System.Xml.Schema/SchemaDataValueType.cs +../class/System.XML/System.Xml.Schema/ValidationEventArgs.cs +../class/System.XML/System.Xml.Schema/XmlAtomicValue.cs +../class/System.XML/System.Xml.Schema/XmlSchema.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAll.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnnotated.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnnotation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAny.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnyAttribute.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAppInfo.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttribute.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroup.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroupRef.cs +../class/System.XML/System.Xml.Schema/XmlSchemaChoice.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCollection.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCollectionEnumerator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCompilationSettings.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentExtension.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentModel.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentProcessing.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDatatype.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDatatypeVariety.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDerivationMethod.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDocumentation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaElement.cs +../class/System.XML/System.Xml.Schema/XmlSchemaEnumerationFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaExternal.cs +../class/System.XML/System.Xml.Schema/XmlSchemaFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaForm.cs +../class/System.XML/System.Xml.Schema/XmlSchemaFractionDigitsFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroup.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroupBase.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroupRef.cs +../class/System.XML/System.Xml.Schema/XmlSchemaIdentityConstraint.cs +../class/System.XML/System.Xml.Schema/XmlSchemaImport.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInclude.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInference.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInferenceException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInfo.cs +../class/System.XML/System.Xml.Schema/XmlSchemaKey.cs +../class/System.XML/System.Xml.Schema/XmlSchemaKeyref.cs +../class/System.XML/System.Xml.Schema/XmlSchemaLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxExclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxInclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinExclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinInclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaNotation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaNumericFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObject.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectCollection.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectEnumerator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectTable.cs +../class/System.XML/System.Xml.Schema/XmlSchemaParticle.cs +../class/System.XML/System.Xml.Schema/XmlSchemaPatternFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaRedefine.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSequence.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSerializer.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentExtension.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeList.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeUnion.cs +../class/System.XML/System.Xml.Schema/XmlSchemaTotalDigitsFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUnique.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUse.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidity.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidationException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaWhiteSpaceFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaXPath.cs +../class/System.XML/System.Xml.Schema/XmlSeverityType.cs +../class/System.XML/System.Xml.Schema/ValidationHandler.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUtil.cs +../class/System.XML/System.Xml.Schema/XmlSchemaReader.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidationFlags.cs +../class/System.XML/System.Xml.Schema/XmlTypeCode.cs +../class/System.XML/System.Xml.Schema/XmlValueGetter.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyImports.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyTemplates.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslAttribute.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslAvt.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCallTemplate.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslChoose.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslComment.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCompiledElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCopy.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCopyOf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslFallback.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslForEach.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslIf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslLiteralElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslMessage.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslNotSupportedOperation.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslNumber.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslOperation.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslProcessingInstruction.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslTemplateContent.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslText.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslValueOf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs +../class/System.XML/Mono.Xml.Xsl/Attribute.cs +../class/System.XML/Mono.Xml.Xsl/Compiler.cs +../class/System.XML/Mono.Xml.Xsl/Debug.cs +../class/System.XML/Mono.Xml.Xsl/Emitter.cs +../class/System.XML/Mono.Xml.Xsl/GenericOutputter.cs +../class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs +../class/System.XML/Mono.Xml.Xsl/MSXslScriptManager.cs +../class/System.XML/Mono.Xml.Xsl/Outputter.cs +../class/System.XML/Mono.Xml.Xsl/ScriptCompilerInfo.cs +../class/System.XML/Mono.Xml.Xsl/TextEmitter.cs +../class/System.XML/Mono.Xml.Xsl/TextOutputter.cs +../class/System.XML/Mono.Xml.Xsl/PatternParser.cs +../class/System.XML/Mono.Xml.Xsl/PatternTokenizer.cs +../class/System.XML/Mono.Xml.Xsl/XmlWriterEmitter.cs +../class/System.XML/Mono.Xml.Xsl/XslAttributeSet.cs +../class/System.XML/Mono.Xml.Xsl/XslDecimalFormat.cs +../class/System.XML/Mono.Xml.Xsl/XslKey.cs +../class/System.XML/Mono.Xml.Xsl/XslOutput.cs +../class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs +../class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs +../class/System.XML/Mono.Xml.Xsl/XslTemplate.cs +../class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs +../class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs +../class/System.XML/Mono.Xml.Xsl/XsltDebuggerWrapper.cs +../class/System.XML/Mono.Xml.Xsl/XslFunctions.cs +../class/System.XML/System.Xml.Xsl/IXsltContextFunction.cs +../class/System.XML/System.Xml.Xsl/IXsltContextVariable.cs +../class/System.XML/System.Xml.Xsl/XslCompiledTransform.cs +../class/System.XML/System.Xml.Xsl/XslTransform.cs +../class/System.XML/System.Xml.Xsl/XsltArgumentList.cs +../class/System.XML/System.Xml.Xsl/XsltCompileException.cs +../class/System.XML/System.Xml.Xsl/XsltContext.cs +../class/System.XML/System.Xml.Xsl/XsltException.cs +../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventArgs.cs +../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventHandler.cs +../class/System.XML/System.Xml.Xsl/XsltSettings.cs +../class/System.XML/System.Xml/XQueryConvert.cs +../class/System.XML/System.Xml.Serialization/IXmlTextParser.cs +../class/System.XML/System.Xml.Serialization/CodeExporter.cs +../class/System.XML/System.Xml.Serialization/CodeGenerationOptions.cs +../class/System.XML/System.Xml.Serialization/CodeIdentifier.cs +../class/System.XML/System.Xml.Serialization/CodeIdentifiers.cs +../class/System.XML/System.Xml.Serialization/IXmlSerializable.cs +../class/System.XML/System.Xml.Serialization/ImportContext.cs +../class/System.XML/System.Xml.Serialization/MapCodeGenerator.cs +../class/System.XML/System.Xml.Serialization/ReflectionHelper.cs +../class/System.XML/System.Xml.Serialization/SchemaImporter.cs +../class/System.XML/System.Xml.Serialization/SchemaTypes.cs +../class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs +../class/System.XML/System.Xml.Serialization/SerializationCodeGeneratorConfiguration.cs +../class/System.XML/System.Xml.Serialization/SerializationSource.cs +../class/System.XML/System.Xml.Serialization/SoapAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapAttributeOverrides.cs +../class/System.XML/System.Xml.Serialization/SoapAttributes.cs +../class/System.XML/System.Xml.Serialization/SoapCodeExporter.cs +../class/System.XML/System.Xml.Serialization/SoapElementAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapEnumAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapIgnoreAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapIncludeAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaImporter.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaExporter.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaMember.cs +../class/System.XML/System.Xml.Serialization/SoapReflectionImporter.cs +../class/System.XML/System.Xml.Serialization/SoapTypeAttribute.cs +../class/System.XML/System.Xml.Serialization/TypeData.cs +../class/System.XML/System.Xml.Serialization/TypeMember.cs +../class/System.XML/System.Xml.Serialization/TypeTranslator.cs +../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventArgs.cs +../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlAnyAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAnyElementAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAnyElementAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlArrayAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlArrayItemAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlArrayItemAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeOverrides.cs +../class/System.XML/System.Xml.Serialization/XmlAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlCodeExporter.cs +../class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs +../class/System.XML/System.Xml.Serialization/XmlDeserializationEvents.cs +../class/System.XML/System.Xml.Serialization/XmlElementAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlElementAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlElementEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlEnumAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlIgnoreAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlIncludeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMembersMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMappingAccess.cs +../class/System.XML/System.Xml.Serialization/XmlNamespaceDeclarationsAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlNodeEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs +../class/System.XML/System.Xml.Serialization/XmlReflectionMember.cs +../class/System.XML/System.Xml.Serialization/XmlRootAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaEnumerator.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaExporter.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaImporter.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaProviderAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSchemas.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationCollectionFixupCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationFixupCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationGeneratedCode.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReadCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriteCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializer.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerAssemblyAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerImplementation.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerNamespaces.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerVersionAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTextAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapElementInfo.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberElement.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberNamespaces.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +../class/System.XML/System.Xml.Serialization/XmlElementEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlNodeEventHandler.cs +../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtension.cs +../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtensionCollection.cs +../class/System.XML/System.Xml.Serialization.Configuration/DateTimeSerializationSection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElement.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElementCollection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionsSection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SerializationSectionGroup.cs +../class/System.XML/System.Xml.Serialization.Configuration/XmlSerializerSection.cs diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs new file mode 100644 index 0000000000..db028e02bd --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs @@ -0,0 +1,5969 @@ +// +// statement.cs: Statement representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003, 2004 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + public abstract class Statement { + public Location loc; + + /// + /// Resolves the statement, true means that all sub-statements + /// did resolve ok. + // + public virtual bool Resolve (BlockContext bc) + { + return true; + } + + /// + /// We already know that the statement is unreachable, but we still + /// need to resolve it to catch errors. + /// + public virtual bool ResolveUnreachable (BlockContext ec, bool warn) + { + // + // This conflicts with csc's way of doing this, but IMHO it's + // the right thing to do. + // + // If something is unreachable, we still check whether it's + // correct. This means that you cannot use unassigned variables + // in unreachable code, for instance. + // + + if (warn) + ec.Report.Warning (162, 2, loc, "Unreachable code detected"); + + ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); + bool ok = Resolve (ec); + ec.KillFlowBranching (); + + return ok; + } + + /// + /// Return value indicates whether all code paths emitted return. + /// + protected abstract void DoEmit (EmitContext ec); + + public virtual void Emit (EmitContext ec) + { + ec.Mark (loc); + DoEmit (ec); + } + + // + // This routine must be overrided in derived classes and make copies + // of all the data that might be modified if resolved + // + protected abstract void CloneTo (CloneContext clonectx, Statement target); + + public Statement Clone (CloneContext clonectx) + { + Statement s = (Statement) this.MemberwiseClone (); + CloneTo (clonectx, s); + return s; + } + + public virtual Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree"); + return null; + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public sealed class EmptyStatement : Statement + { + public EmptyStatement (Location loc) + { + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + public override bool ResolveUnreachable (BlockContext ec, bool warn) + { + return true; + } + + public override void Emit (EmitContext ec) + { + } + + protected override void DoEmit (EmitContext ec) + { + throw new NotSupportedException (); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing needed. + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class If : Statement { + Expression expr; + public Statement TrueStatement; + public Statement FalseStatement; + + bool is_true_ret; + + public If (Expression bool_expr, Statement true_statement, Location l) + : this (bool_expr, true_statement, null, l) + { + } + + public If (Expression bool_expr, + Statement true_statement, + Statement false_statement, + Location l) + { + this.expr = bool_expr; + TrueStatement = true_statement; + FalseStatement = false_statement; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + expr = expr.Resolve (ec); + if (expr == null) { + ok = false; + } else { + // + // Dead code elimination + // + if (expr is Constant) { + bool take = !((Constant) expr).IsDefaultValue; + + if (take) { + if (!TrueStatement.Resolve (ec)) + return false; + + if ((FalseStatement != null) && + !FalseStatement.ResolveUnreachable (ec, true)) + return false; + FalseStatement = null; + } else { + if (!TrueStatement.ResolveUnreachable (ec, true)) + return false; + TrueStatement = null; + + if ((FalseStatement != null) && + !FalseStatement.Resolve (ec)) + return false; + } + + return true; + } + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc); + + ok &= TrueStatement.Resolve (ec); + + is_true_ret = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.CurrentBranching.CreateSibling (); + + if (FalseStatement != null) + ok &= FalseStatement.Resolve (ec); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + Label false_target = ec.DefineLabel (); + Label end; + + // + // If we're a boolean constant, Resolve() already + // eliminated dead code for us. + // + Constant c = expr as Constant; + if (c != null){ + c.EmitSideEffect (ec); + + if (!c.IsDefaultValue) + TrueStatement.Emit (ec); + else if (FalseStatement != null) + FalseStatement.Emit (ec); + + return; + } + + expr.EmitBranchable (ec, false_target, false); + + TrueStatement.Emit (ec); + + if (FalseStatement != null){ + bool branch_emitted = false; + + end = ec.DefineLabel (); + if (!is_true_ret){ + ec.Emit (OpCodes.Br, end); + branch_emitted = true; + } + + ec.MarkLabel (false_target); + FalseStatement.Emit (ec); + + if (branch_emitted) + ec.MarkLabel (end); + } else { + ec.MarkLabel (false_target); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + If target = (If) t; + + target.expr = expr.Clone (clonectx); + target.TrueStatement = TrueStatement.Clone (clonectx); + if (FalseStatement != null) + target.FalseStatement = FalseStatement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Do : Statement { + public Expression expr; + public Statement EmbeddedStatement; + + public Do (Statement statement, BooleanExpression bool_expr, Location l) + { + expr = bool_expr; + EmbeddedStatement = statement; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + + bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!EmbeddedStatement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable) + ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected"); + + expr = expr.Resolve (ec); + if (expr == null) + ok = false; + else if (expr is Constant){ + bool infinite = !((Constant) expr).IsDefaultValue; + if (infinite) + ec.CurrentBranching.CurrentUsageVector.Goto (); + } + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + Label loop = ec.DefineLabel (); + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + ec.MarkLabel (loop); + EmbeddedStatement.Emit (ec); + ec.MarkLabel (ec.LoopBegin); + + // + // Dead code elimination + // + if (expr is Constant){ + bool res = !((Constant) expr).IsDefaultValue; + + expr.EmitSideEffect (ec); + if (res) + ec.Emit (OpCodes.Br, loop); + } else + expr.EmitBranchable (ec, loop, true); + + ec.MarkLabel (ec.LoopEnd); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Do target = (Do) t; + + target.EmbeddedStatement = EmbeddedStatement.Clone (clonectx); + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class While : Statement { + public Expression expr; + public Statement Statement; + bool infinite, empty; + + public While (BooleanExpression bool_expr, Statement statement, Location l) + { + this.expr = bool_expr; + Statement = statement; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + expr = expr.Resolve (ec); + if (expr == null) + ok = false; + + // + // Inform whether we are infinite or not + // + if (expr is Constant){ + bool value = !((Constant) expr).IsDefaultValue; + + if (value == false){ + if (!Statement.ResolveUnreachable (ec, true)) + return false; + empty = true; + return true; + } else + infinite = true; + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + if (!infinite) + ec.CurrentBranching.CreateSibling (); + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!Statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + if (empty) { + expr.EmitSideEffect (ec); + return; + } + + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + // + // Inform whether we are infinite or not + // + if (expr is Constant){ + // expr is 'true', since the 'empty' case above handles the 'false' case + ec.MarkLabel (ec.LoopBegin); + expr.EmitSideEffect (ec); + Statement.Emit (ec); + ec.Emit (OpCodes.Br, ec.LoopBegin); + + // + // Inform that we are infinite (ie, `we return'), only + // if we do not `break' inside the code. + // + ec.MarkLabel (ec.LoopEnd); + } else { + Label while_loop = ec.DefineLabel (); + + ec.Emit (OpCodes.Br, ec.LoopBegin); + ec.MarkLabel (while_loop); + + Statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + ec.Mark (loc); + + expr.EmitBranchable (ec, while_loop, true); + + ec.MarkLabel (ec.LoopEnd); + } + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + public override void Emit (EmitContext ec) + { + DoEmit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + While target = (While) t; + + target.expr = expr.Clone (clonectx); + target.Statement = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class For : Statement { + public Expression Test { get; private set; } + public Statement InitStatement { get; private set; } + public Statement Increment { get; private set; } + public Statement Statement { get; private set; } + bool infinite, empty; + + public For (Statement init_statement, + BooleanExpression test, + Statement increment, + Statement statement, + Location l) + { + InitStatement = init_statement; + Test = test; + Increment = increment; + Statement = statement; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + if (InitStatement != null){ + if (!InitStatement.Resolve (ec)) + ok = false; + } + + if (Test != null){ + Test = Test.Resolve (ec); + if (Test == null) + ok = false; + else if (Test is Constant){ + bool value = !((Constant) Test).IsDefaultValue; + + if (value == false){ + if (!Statement.ResolveUnreachable (ec, true)) + return false; + if ((Increment != null) && + !Increment.ResolveUnreachable (ec, false)) + return false; + empty = true; + return true; + } else + infinite = true; + } + } else + infinite = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + if (!infinite) + ec.CurrentBranching.CreateSibling (); + + bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!Statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + if (Increment != null){ + if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable) { + if (!Increment.ResolveUnreachable (ec, !was_unreachable)) + ok = false; + } else { + if (!Increment.Resolve (ec)) + ok = false; + } + } + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + if (InitStatement != null) + InitStatement.Emit (ec); + + if (empty) { + Test.EmitSideEffect (ec); + return; + } + + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + Label loop = ec.DefineLabel (); + Label test = ec.DefineLabel (); + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + ec.Emit (OpCodes.Br, test); + ec.MarkLabel (loop); + Statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + Increment.Emit (ec); + + ec.MarkLabel (test); + // + // If test is null, there is no test, and we are just + // an infinite loop + // + if (Test != null){ + // + // The Resolve code already catches the case for + // Test == Constant (false) so we know that + // this is true + // + if (Test is Constant) { + Test.EmitSideEffect (ec); + ec.Emit (OpCodes.Br, loop); + } else { + Test.EmitBranchable (ec, loop, true); + } + + } else + ec.Emit (OpCodes.Br, loop); + ec.MarkLabel (ec.LoopEnd); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + For target = (For) t; + + if (InitStatement != null) + target.InitStatement = InitStatement.Clone (clonectx); + if (Test != null) + target.Test = Test.Clone (clonectx); + if (Increment != null) + target.Increment = Increment.Clone (clonectx); + target.Statement = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class StatementExpression : Statement + { + ExpressionStatement expr; + + public StatementExpression (ExpressionStatement expr) + { + this.expr = expr; + loc = expr.Location; + } + + public ExpressionStatement Expr { + get { return this.expr; } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + StatementExpression target = (StatementExpression) t; + target.expr = (ExpressionStatement) expr.Clone (clonectx); + } + + protected override void DoEmit (EmitContext ec) + { + expr.EmitStatement (ec); + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.ResolveStatement (ec); + return expr != null; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Simple version of statement list not requiring a block + // + public class StatementList : Statement + { + List statements; + + public StatementList (Statement first, Statement second) + { + statements = new List () { first, second }; + } + + #region Properties + public IList Statements { + get { + return statements; + } + } + #endregion + + public void Add (Statement statement) + { + statements.Add (statement); + } + + public override bool Resolve (BlockContext ec) + { + foreach (var s in statements) + s.Resolve (ec); + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + foreach (var s in statements) + s.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + StatementList t = (StatementList) target; + + t.statements = new List (statements.Count); + foreach (Statement s in statements) + t.statements.Add (s.Clone (clonectx)); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // A 'return' or a 'yield break' + public abstract class ExitStatement : Statement + { + protected bool unwind_protect; + protected abstract bool DoResolve (BlockContext ec); + + public virtual void Error_FinallyClause (Report Report) + { + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } + + public sealed override bool Resolve (BlockContext ec) + { + if (!DoResolve (ec)) + return false; + + unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this); + if (unwind_protect) + ec.NeedReturnLabel (); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + } + + /// + /// Implements the return statement + /// + public class Return : ExitStatement + { + public Expression Expr { get; protected set; } + + public Return (Expression expr, Location l) + { + Expr = expr; + loc = l; + } + + #region Properties + public Expression Expression { + get { + return Expr; + } + } + #endregion + + protected override bool DoResolve (BlockContext ec) + { + if (Expr == null) { + if (ec.ReturnType.Kind == MemberKind.Void) + return true; + + // + // Return must not be followed by an expression when + // the method return type is Task + // + if (ec.CurrentAnonymousMethod is AsyncInitializer) { + var storey = (AsyncTaskStorey) ec.CurrentAnonymousMethod.Storey; + if (storey.ReturnType == ec.Module.PredefinedTypes.Task.TypeSpec) { + // + // Extra trick not to emit ret/leave inside awaiter body + // + Expr = EmptyExpression.Null; + return true; + } + } + + if (ec.CurrentIterator != null) { + Error_ReturnFromIterator (ec); + } else { + ec.Report.Error (126, loc, + "An object of a type convertible to `{0}' is required for the return statement", + ec.ReturnType.GetSignatureForError ()); + } + + return false; + } + + Expr = Expr.Resolve (ec); + TypeSpec block_return_type = ec.ReturnType; + + AnonymousExpression am = ec.CurrentAnonymousMethod; + if (am == null) { + if (block_return_type.Kind == MemberKind.Void) { + ec.Report.Error (127, loc, + "`{0}': A return keyword must not be followed by any expression when method returns void", + ec.GetSignatureForError ()); + } + } else { + if (am.IsIterator) { + Error_ReturnFromIterator (ec); + return false; + } + + var async_block = am as AsyncInitializer; + if (async_block != null) { + if (Expr != null) { + var storey = (AsyncTaskStorey) am.Storey; + var async_type = storey.ReturnType; + + if (async_type == null && async_block.ReturnTypeInference != null) { + async_block.ReturnTypeInference.AddCommonTypeBound (Expr.Type); + return true; + } + + if (!async_type.IsGenericTask) { + if (this is ContextualReturn) + return true; + + ec.Report.Error (1997, loc, + "`{0}': A return keyword must not be followed by an expression when async method returns Task. Consider using Task", + ec.GetSignatureForError ()); + return false; + } + + // + // The return type is actually Task type argument + // + block_return_type = async_type.TypeArguments[0]; + } + } else { + var l = am as AnonymousMethodBody; + if (l != null && l.ReturnTypeInference != null && Expr != null) { + l.ReturnTypeInference.AddCommonTypeBound (Expr.Type); + return true; + } + } + } + + if (Expr == null) + return false; + + if (Expr.Type != block_return_type) { + Expr = Convert.ImplicitConversionRequired (ec, Expr, block_return_type, loc); + + if (Expr == null) { + if (am != null && block_return_type == ec.ReturnType) { + ec.Report.Error (1662, loc, + "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type", + am.ContainerType, am.GetSignatureForError ()); + } + return false; + } + } + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (Expr != null) { + Expr.Emit (ec); + + var async_body = ec.CurrentAnonymousMethod as AsyncInitializer; + if (async_body != null) { + var async_return = ((AsyncTaskStorey) async_body.Storey).HoistedReturn; + + // It's null for await without async + if (async_return != null) + async_return.EmitAssign (ec); + + return; + } + + if (unwind_protect) + ec.Emit (OpCodes.Stloc, ec.TemporaryReturn ()); + } + + if (unwind_protect) + ec.Emit (OpCodes.Leave, ec.ReturnLabel); + else + ec.Emit (OpCodes.Ret); + } + + void Error_ReturnFromIterator (ResolveContext rc) + { + rc.Report.Error (1622, loc, + "Cannot return a value from iterators. Use the yield return statement to return a value, or yield break to end the iteration"); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Return target = (Return) t; + // It's null for simple return; + if (Expr != null) + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Goto : Statement { + string target; + LabeledStatement label; + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + public Goto (string label, Location l) + { + loc = l; + target = label; + } + + public string Target { + get { return target; } + } + + public void SetResolvedTarget (LabeledStatement label) + { + this.label = label; + label.AddReference (); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing to clone + } + + protected override void DoEmit (EmitContext ec) + { + if (label == null) + throw new InternalErrorException ("goto emitted before target resolved"); + Label l = label.LabelTarget (ec); + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class LabeledStatement : Statement { + string name; + bool defined; + bool referenced; + Label label; + Block block; + + FlowBranching.UsageVector vectors; + + public LabeledStatement (string name, Block block, Location l) + { + this.name = name; + this.block = block; + this.loc = l; + } + + public Label LabelTarget (EmitContext ec) + { + if (defined) + return label; + + label = ec.DefineLabel (); + defined = true; + return label; + } + + public Block Block { + get { + return block; + } + } + + public string Name { + get { return name; } + } + + public bool IsDefined { + get { return defined; } + } + + public bool HasBeenReferenced { + get { return referenced; } + } + + public FlowBranching.UsageVector JumpOrigins { + get { return vectors; } + } + + public void AddUsageVector (FlowBranching.UsageVector vector) + { + vector = vector.Clone (); + vector.Next = vectors; + vectors = vector; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing to clone + } + + public override bool Resolve (BlockContext ec) + { + // this flow-branching will be terminated when the surrounding block ends + ec.StartFlowBranching (this); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (!HasBeenReferenced) + ec.Report.Warning (164, 2, loc, "This label has not been referenced"); + + LabelTarget (ec); + ec.MarkLabel (label); + } + + public void AddReference () + { + referenced = true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + + /// + /// `goto default' statement + /// + public class GotoDefault : Statement { + + public GotoDefault (Location l) + { + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing to clone + } + + public override bool Resolve (BlockContext ec) + { + ec.CurrentBranching.CurrentUsageVector.Goto (); + + if (ec.Switch == null) { + ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement"); + return false; + } + + if (!ec.Switch.GotDefault) { + FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report); + return false; + } + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (OpCodes.Br, ec.Switch.DefaultLabel); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// `goto case' statement + /// + public class GotoCase : Statement { + Expression expr; + SwitchLabel sl; + + public GotoCase (Expression e, Location l) + { + expr = e; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + if (ec.Switch == null){ + ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement"); + return false; + } + + ec.CurrentBranching.CurrentUsageVector.Goto (); + + expr = expr.Resolve (ec); + if (expr == null) + return false; + + Constant c = expr as Constant; + if (c == null) { + ec.Report.Error (150, expr.Location, "A constant value is expected"); + return false; + } + + Constant res; + if (ec.Switch.IsNullable && c is NullLiteral) { + res = c; + } else { + TypeSpec type = ec.Switch.SwitchType; + res = c.TryReduce (ec, type, c.Location); + if (res == null) { + c.Error_ValueCannotBeConverted (ec, loc, type, true); + return false; + } + + if (!Convert.ImplicitStandardConversionExists (c, type)) + ec.Report.Warning (469, 2, loc, + "The `goto case' value is not implicitly convertible to type `{0}'", + TypeManager.CSharpName (type)); + + } + + sl = ec.Switch.ResolveGotoCase (ec, res); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (OpCodes.Br, sl.GetILLabel (ec)); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + GotoCase target = (GotoCase) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Throw : Statement { + Expression expr; + + public Throw (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + if (expr == null) { + ec.CurrentBranching.CurrentUsageVector.Goto (); + return ec.CurrentBranching.CheckRethrow (loc); + } + + expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue); + ec.CurrentBranching.CurrentUsageVector.Goto (); + + if (expr == null) + return false; + + var et = ec.BuiltinTypes.Exception; + if (Convert.ImplicitConversionExists (ec, expr, et)) + expr = Convert.ImplicitConversion (ec, expr, et, loc); + else + ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception"); + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (expr == null) + ec.Emit (OpCodes.Rethrow); + else { + expr.Emit (ec); + + ec.Emit (OpCodes.Throw); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Throw target = (Throw) t; + + if (expr != null) + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Break : Statement { + + public Break (Location l) + { + loc = l; + } + + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + // nothing needed + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Continue : Statement { + + public Continue (Location l) + { + loc = l; + } + + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + // nothing needed. + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public interface ILocalVariable + { + void Emit (EmitContext ec); + void EmitAssign (EmitContext ec); + void EmitAddressOf (EmitContext ec); + } + + public interface INamedBlockVariable + { + Block Block { get; } + Expression CreateReferenceExpression (ResolveContext rc, Location loc); + bool IsDeclared { get; } + Location Location { get; } + } + + public class BlockVariableDeclaration : Statement + { + public class Declarator + { + LocalVariable li; + Expression initializer; + + public Declarator (LocalVariable li, Expression initializer) + { + if (li.Type != null) + throw new ArgumentException ("Expected null variable type"); + + this.li = li; + this.initializer = initializer; + } + + public Declarator (Declarator clone, Expression initializer) + { + this.li = clone.li; + this.initializer = initializer; + } + + #region Properties + + public LocalVariable Variable { + get { + return li; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + #endregion + } + + Expression initializer; + protected FullNamedExpression type_expr; + protected LocalVariable li; + protected List declarators; + + public BlockVariableDeclaration (FullNamedExpression type, LocalVariable li) + { + this.type_expr = type; + this.li = li; + this.loc = type_expr.Location; + } + + protected BlockVariableDeclaration (LocalVariable li) + { + this.li = li; + } + + #region Properties + + public List Declarators { + get { + return declarators; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + } + + public LocalVariable Variable { + get { + return li; + } + } + + #endregion + + public void AddDeclarator (Declarator decl) + { + if (declarators == null) + declarators = new List (); + + declarators.Add (decl); + } + + void CreateEvaluatorVariable (BlockContext bc, LocalVariable li) + { + var container = bc.CurrentMemberDefinition.Parent; + + Field f = new Field (container, new TypeExpression (li.Type, li.Location), Modifiers.PUBLIC | Modifiers.STATIC, + new MemberName (li.Name, li.Location), null); + + container.AddField (f); + f.Define (); + + li.HoistedVariant = new HoistedEvaluatorVariable (f); + li.SetIsUsed (); + } + + public override bool Resolve (BlockContext bc) + { + if (li.Type == null) { + TypeSpec type = null; + var vexpr = type_expr as VarExpr; + + // + // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with + // same name exists or as a keyword when no type was found + // + if (vexpr != null && !vexpr.IsPossibleTypeOrNamespace (bc)) { + if (bc.Module.Compiler.Settings.Version < LanguageVersion.V_3) + bc.Report.FeatureIsNotAvailable (bc.Module.Compiler, loc, "implicitly typed local variable"); + + if (li.IsFixed) { + bc.Report.Error (821, loc, "A fixed statement cannot use an implicitly typed local variable"); + return false; + } + + if (li.IsConstant) { + bc.Report.Error (822, loc, "An implicitly typed local variable cannot be a constant"); + return false; + } + + if (Initializer == null) { + bc.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer"); + return false; + } + + if (declarators != null) { + bc.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators"); + declarators = null; + } + + Initializer = Initializer.Resolve (bc); + if (Initializer != null) { + ((VarExpr) type_expr).InferType (bc, Initializer); + type = type_expr.Type; + } + } + + if (type == null) { + type = type_expr.ResolveAsType (bc); + if (type == null) + return false; + + if (li.IsConstant && !type.IsConstantCompatible) { + Const.Error_InvalidConstantType (type, loc, bc.Report); + } + } + + if (type.IsStatic) + FieldBase.Error_VariableOfStaticClass (loc, li.Name, type, bc.Report); + + li.Type = type; + } + + bool eval_global = bc.Module.Compiler.Settings.StatementMode && bc.CurrentBlock is ToplevelBlock; + if (eval_global) { + CreateEvaluatorVariable (bc, li); + } else { + li.PrepareForFlowAnalysis (bc); + } + + if (initializer != null) { + initializer = ResolveInitializer (bc, li, initializer); + // li.Variable.DefinitelyAssigned + } + + if (declarators != null) { + foreach (var d in declarators) { + d.Variable.Type = li.Type; + if (eval_global) { + CreateEvaluatorVariable (bc, d.Variable); + } else { + d.Variable.PrepareForFlowAnalysis (bc); + } + + if (d.Initializer != null) { + d.Initializer = ResolveInitializer (bc, d.Variable, d.Initializer); + // d.Variable.DefinitelyAssigned + } + } + } + + return true; + } + + protected virtual Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + var a = new SimpleAssign (li.CreateReferenceExpression (bc, li.Location), initializer, li.Location); + return a.ResolveStatement (bc); + } + + protected override void DoEmit (EmitContext ec) + { + if (li.IsConstant) + return; + + li.CreateBuilder (ec); + + if (Initializer != null) + ((ExpressionStatement) Initializer).EmitStatement (ec); + + if (declarators != null) { + foreach (var d in declarators) { + d.Variable.CreateBuilder (ec); + if (d.Initializer != null) + ((ExpressionStatement) d.Initializer).EmitStatement (ec); + } + } + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + BlockVariableDeclaration t = (BlockVariableDeclaration) target; + + if (type_expr != null) + t.type_expr = (FullNamedExpression) type_expr.Clone (clonectx); + + if (initializer != null) + t.initializer = initializer.Clone (clonectx); + + if (declarators != null) { + t.declarators = null; + foreach (var d in declarators) + t.AddDeclarator (new Declarator (d, d.Initializer == null ? null : d.Initializer.Clone (clonectx))); + } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class BlockConstantDeclaration : BlockVariableDeclaration + { + public BlockConstantDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + initializer = initializer.Resolve (bc); + if (initializer == null) + return null; + + var c = initializer as Constant; + if (c == null) { + initializer.Error_ExpressionMustBeConstant (bc, initializer.Location, li.Name); + return null; + } + + c = c.ConvertImplicitly (li.Type); + if (c == null) { + if (TypeSpec.IsReferenceType (li.Type)) + initializer.Error_ConstantCanBeInitializedWithNullOnly (bc, li.Type, initializer.Location, li.Name); + else + initializer.Error_ValueCannotBeConverted (bc, initializer.Location, li.Type, false); + + return null; + } + + li.ConstantValue = c; + return initializer; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // The information about a user-perceived local variable + // + public class LocalVariable : INamedBlockVariable, ILocalVariable + { + [Flags] + public enum Flags + { + Used = 1, + IsThis = 1 << 1, + AddressTaken = 1 << 2, + CompilerGenerated = 1 << 3, + Constant = 1 << 4, + ForeachVariable = 1 << 5, + FixedVariable = 1 << 6, + UsingVariable = 1 << 7, +// DefinitelyAssigned = 1 << 8, + IsLocked = 1 << 9, + + ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable + } + + TypeSpec type; + readonly string name; + readonly Location loc; + readonly Block block; + Flags flags; + Constant const_value; + + public VariableInfo VariableInfo; + HoistedVariable hoisted_variant; + + LocalBuilder builder; + + public LocalVariable (Block block, string name, Location loc) + { + this.block = block; + this.name = name; + this.loc = loc; + } + + public LocalVariable (Block block, string name, Flags flags, Location loc) + : this (block, name, loc) + { + this.flags = flags; + } + + // + // Used by variable declarators + // + public LocalVariable (LocalVariable li, string name, Location loc) + : this (li.block, name, li.flags, loc) + { + } + + #region Properties + + public bool AddressTaken { + get { return (flags & Flags.AddressTaken) != 0; } + set { flags |= Flags.AddressTaken; } + } + + public Block Block { + get { + return block; + } + } + + public Constant ConstantValue { + get { + return const_value; + } + set { + const_value = value; + } + } + + // + // Hoisted local variable variant + // + public HoistedVariable HoistedVariant { + get { + return hoisted_variant; + } + set { + hoisted_variant = value; + } + } + + public bool IsDeclared { + get { + return type != null; + } + } + + public bool IsConstant { + get { + return (flags & Flags.Constant) != 0; + } + } + + public bool IsLocked { + get { + return (flags & Flags.IsLocked) != 0; + } + set { + flags = value ? flags | Flags.IsLocked : flags & ~Flags.IsLocked; + } + } + + public bool IsThis { + get { + return (flags & Flags.IsThis) != 0; + } + } + + public bool IsFixed { + get { + return (flags & Flags.FixedVariable) != 0; + } + } + + public bool IsReadonly { + get { + return (flags & Flags.ReadonlyMask) != 0; + } + } + + public Location Location { + get { + return loc; + } + } + + public string Name { + get { + return name; + } + } + + public TypeSpec Type { + get { + return type; + } + set { + type = value; + } + } + + #endregion + + public void CreateBuilder (EmitContext ec) + { + if ((flags & Flags.Used) == 0) { + if (VariableInfo == null) { + // Missing flow analysis or wrong variable flags + throw new InternalErrorException ("VariableInfo is null and the variable `{0}' is not used", name); + } + + if (VariableInfo.IsEverAssigned) + ec.Report.Warning (219, 3, Location, "The variable `{0}' is assigned but its value is never used", Name); + else + ec.Report.Warning (168, 3, Location, "The variable `{0}' is declared but never used", Name); + } + + if (HoistedVariant != null) + return; + + if (builder != null) { + if ((flags & Flags.CompilerGenerated) != 0) + return; + + // To avoid Used warning duplicates + throw new InternalErrorException ("Already created variable `{0}'", name); + } + + // + // All fixed variabled are pinned, a slot has to be alocated + // + builder = ec.DeclareLocal (Type, IsFixed); + if (SymbolWriter.HasSymbolWriter) + ec.DefineLocalVariable (name, builder); + } + + public static LocalVariable CreateCompilerGenerated (TypeSpec type, Block block, Location loc) + { + LocalVariable li = new LocalVariable (block, "<$$>", Flags.CompilerGenerated | Flags.Used, loc); + li.Type = type; + return li; + } + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + if (IsConstant && const_value != null) + return Constant.CreateConstantFromValue (Type, const_value.GetValue (), loc); + + return new LocalVariableReference (this, loc); + } + + public void Emit (EmitContext ec) + { + // TODO: Need something better for temporary variables + if ((flags & Flags.CompilerGenerated) != 0) + CreateBuilder (ec); + + ec.Emit (OpCodes.Ldloc, builder); + } + + public void EmitAssign (EmitContext ec) + { + // TODO: Need something better for temporary variables + if ((flags & Flags.CompilerGenerated) != 0) + CreateBuilder (ec); + + ec.Emit (OpCodes.Stloc, builder); + } + + public void EmitAddressOf (EmitContext ec) + { + ec.Emit (OpCodes.Ldloca, builder); + } + + public string GetReadOnlyContext () + { + switch (flags & Flags.ReadonlyMask) { + case Flags.FixedVariable: + return "fixed variable"; + case Flags.ForeachVariable: + return "foreach iteration variable"; + case Flags.UsingVariable: + return "using variable"; + } + + throw new InternalErrorException ("Variable is not readonly"); + } + + public bool IsThisAssigned (BlockContext ec, Block block) + { + if (VariableInfo == null) + throw new Exception (); + + if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo)) + return true; + + return VariableInfo.TypeInfo.IsFullyInitialized (ec, VariableInfo, block.StartLocation); + } + + public bool IsAssigned (BlockContext ec) + { + if (VariableInfo == null) + throw new Exception (); + + return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo); + } + + public void PrepareForFlowAnalysis (BlockContext bc) + { + // + // No need for definitely assigned check for these guys + // + if ((flags & (Flags.Constant | Flags.ReadonlyMask | Flags.CompilerGenerated)) != 0) + return; + + VariableInfo = new VariableInfo (this, bc.FlowOffset); + bc.FlowOffset += VariableInfo.Length; + } + + // + // Mark the variables as referenced in the user code + // + public void SetIsUsed () + { + flags |= Flags.Used; + } + + public override string ToString () + { + return string.Format ("LocalInfo ({0},{1},{2},{3})", name, type, VariableInfo, Location); + } + } + + /// + /// Block represents a C# block. + /// + /// + /// + /// This class is used in a number of places: either to represent + /// explicit blocks that the programmer places or implicit blocks. + /// + /// Implicit blocks are used as labels or to introduce variable + /// declarations. + /// + /// Top-level blocks derive from Block, and they are called ToplevelBlock + /// they contain extra information that is not necessary on normal blocks. + /// + public class Block : Statement { + [Flags] + public enum Flags + { + Unchecked = 1, + HasRet = 8, + Unsafe = 16, + IsIterator = 32, + HasCapturedVariable = 64, + HasCapturedThis = 1 << 7, + IsExpressionTree = 1 << 8, + CompilerGenerated = 1 << 9, + IsAsync = 1 << 10 + } + + public Block Parent; + public Location StartLocation; + public Location EndLocation; + + public ExplicitBlock Explicit; + public ParametersBlock ParametersBlock; + + protected Flags flags; + + // + // The statements in this block + // + protected List statements; + + protected List scope_initializers; + + int? resolving_init_idx; + + protected Block original; + +#if DEBUG + static int id; + public int ID = id++; + + static int clone_id_counter; + int clone_id; +#endif + +// int assignable_slots; + bool unreachable_shown; + bool unreachable; + + public Block (Block parent, Location start, Location end) + : this (parent, 0, start, end) + { + } + + public Block (Block parent, Flags flags, Location start, Location end) + { + if (parent != null) { + // the appropriate constructors will fixup these fields + ParametersBlock = parent.ParametersBlock; + Explicit = parent.Explicit; + } + + this.Parent = parent; + this.flags = flags; + this.StartLocation = start; + this.EndLocation = end; + this.loc = start; + statements = new List (4); + + this.original = this; + } + + #region Properties + + public bool HasRet { + get { return (flags & Flags.HasRet) != 0; } + } + + public Block Original { + get { + return original; + } + } + + public bool IsCompilerGenerated { + get { return (flags & Flags.CompilerGenerated) != 0; } + set { flags = value ? flags | Flags.CompilerGenerated : flags & ~Flags.CompilerGenerated; } + } + + public bool Unchecked { + get { return (flags & Flags.Unchecked) != 0; } + set { flags = value ? flags | Flags.Unchecked : flags & ~Flags.Unchecked; } + } + + public bool Unsafe { + get { return (flags & Flags.Unsafe) != 0; } + set { flags |= Flags.Unsafe; } + } + + public List Statements { + get { return this.statements; } + } + #endregion + + public Block CreateSwitchBlock (Location start) + { + // FIXME: Only explicit block should be created + var new_block = new Block (this, start, start); + new_block.IsCompilerGenerated = true; + return new_block; + } + + public void SetEndLocation (Location loc) + { + EndLocation = loc; + } + + public void AddLabel (LabeledStatement target) + { + ParametersBlock.TopBlock.AddLabel (target.Name, target); + } + + public void AddLocalName (LocalVariable li) + { + AddLocalName (li.Name, li); + } + + public virtual void AddLocalName (string name, INamedBlockVariable li) + { + ParametersBlock.TopBlock.AddLocalName (name, li); + } + + public virtual void Error_AlreadyDeclared (string name, INamedBlockVariable variable, string reason) + { + if (reason == null) { + Error_AlreadyDeclared (name, variable); + return; + } + + ParametersBlock.TopBlock.Report.Error (136, variable.Location, + "A local variable named `{0}' cannot be declared in this scope because it would give a different meaning " + + "to `{0}', which is already used in a `{1}' scope to denote something else", + name, reason); + } + + public virtual void Error_AlreadyDeclared (string name, INamedBlockVariable variable) + { + var pi = variable as ParametersBlock.ParameterInfo; + if (pi != null) { + pi.Parameter.Error_DuplicateName (ParametersBlock.TopBlock.Report); + } else { + ParametersBlock.TopBlock.Report.Error (128, variable.Location, + "A local variable named `{0}' is already defined in this scope", name); + } + } + + public virtual void Error_AlreadyDeclaredTypeParameter (string name, Location loc) + { + ParametersBlock.TopBlock.Report.Error (412, loc, + "The type parameter name `{0}' is the same as local variable or parameter name", + name); + } + + // + // It should be used by expressions which require to + // register a statement during resolve process. + // + public void AddScopeStatement (Statement s) + { + if (scope_initializers == null) + scope_initializers = new List (); + + // + // Simple recursive helper, when resolve scope initializer another + // new scope initializer can be added, this ensures it's initialized + // before existing one. For now this can happen with expression trees + // in base ctor initializer only + // + if (resolving_init_idx.HasValue) { + scope_initializers.Insert (resolving_init_idx.Value, s); + ++resolving_init_idx; + } else { + scope_initializers.Add (s); + } + } + + public void AddStatement (Statement s) + { + statements.Add (s); + } + + public int AssignableSlots { + get { + // FIXME: HACK, we don't know the block available variables count now, so set this high enough + return 4096; +// return assignable_slots; + } + } + + public LabeledStatement LookupLabel (string name) + { + return ParametersBlock.TopBlock.GetLabel (name, this); + } + + public override bool Resolve (BlockContext ec) + { + Block prev_block = ec.CurrentBlock; + bool ok = true; + + ec.CurrentBlock = this; + ec.StartFlowBranching (this); + + // + // Compiler generated scope statements + // + if (scope_initializers != null) { + for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) { + scope_initializers[resolving_init_idx.Value].Resolve (ec); + } + + resolving_init_idx = null; + } + + // + // This flag is used to notate nested statements as unreachable from the beginning of this block. + // For the purposes of this resolution, it doesn't matter that the whole block is unreachable + // from the beginning of the function. The outer Resolve() that detected the unreachability is + // responsible for handling the situation. + // + int statement_count = statements.Count; + for (int ix = 0; ix < statement_count; ix++){ + Statement s = statements [ix]; + + // + // Warn if we detect unreachable code. + // + if (unreachable) { + if (s is EmptyStatement) + continue; + + if (!unreachable_shown && !(s is LabeledStatement)) { + ec.Report.Warning (162, 2, s.loc, "Unreachable code detected"); + unreachable_shown = true; + } + + Block c_block = s as Block; + if (c_block != null) + c_block.unreachable = c_block.unreachable_shown = true; + } + + // + // Note that we're not using ResolveUnreachable() for unreachable + // statements here. ResolveUnreachable() creates a temporary + // flow branching and kills it afterwards. This leads to problems + // if you have two unreachable statements where the first one + // assigns a variable and the second one tries to access it. + // + + if (!s.Resolve (ec)) { + ok = false; + if (ec.IsInProbingMode) + break; + + statements [ix] = new EmptyStatement (s.loc); + continue; + } + + if (unreachable && !(s is LabeledStatement) && !(s is Block)) + statements [ix] = new EmptyStatement (s.loc); + + unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + if (unreachable && s is LabeledStatement) + throw new InternalErrorException ("should not happen"); + } + + while (ec.CurrentBranching is FlowBranchingLabeled) + ec.EndFlowBranching (); + + bool flow_unreachable = ec.EndFlowBranching (); + + ec.CurrentBlock = prev_block; + + if (flow_unreachable) + flags |= Flags.HasRet; + + // If we're a non-static `struct' constructor which doesn't have an + // initializer, then we must initialize all of the struct's fields. + if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable) + ok = false; + + return ok; + } + + public override bool ResolveUnreachable (BlockContext ec, bool warn) + { + unreachable_shown = true; + unreachable = true; + + if (warn) + ec.Report.Warning (162, 2, loc, "Unreachable code detected"); + + ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); + bool ok = Resolve (ec); + ec.KillFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + for (int ix = 0; ix < statements.Count; ix++){ + statements [ix].Emit (ec); + } + } + + public override void Emit (EmitContext ec) + { + if (scope_initializers != null) + EmitScopeInitializers (ec); + + ec.Mark (StartLocation); + DoEmit (ec); + + if (SymbolWriter.HasSymbolWriter) + EmitSymbolInfo (ec); + } + + protected void EmitScopeInitializers (EmitContext ec) + { + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + using (ec.With (EmitContext.Options.OmitDebugInfo, true)) { + foreach (Statement s in scope_initializers) + s.Emit (ec); + } + + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + protected virtual void EmitSymbolInfo (EmitContext ec) + { + } + +#if DEBUG + public override string ToString () + { + return String.Format ("{0} ({1}:{2})", GetType (), ID, StartLocation); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Block target = (Block) t; +#if DEBUG + target.clone_id = clone_id_counter++; +#endif + + clonectx.AddBlockMap (this, target); + if (original != this) + clonectx.AddBlockMap (original, target); + + target.ParametersBlock = (ParametersBlock) (ParametersBlock == this ? target : clonectx.RemapBlockCopy (ParametersBlock)); + target.Explicit = (ExplicitBlock) (Explicit == this ? target : clonectx.LookupBlock (Explicit)); + + if (Parent != null) + target.Parent = clonectx.RemapBlockCopy (Parent); + + target.statements = new List (statements.Count); + foreach (Statement s in statements) + target.statements.Add (s.Clone (clonectx)); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ExplicitBlock : Block + { + protected AnonymousMethodStorey am_storey; + + public ExplicitBlock (Block parent, Location start, Location end) + : this (parent, (Flags) 0, start, end) + { + } + + public ExplicitBlock (Block parent, Flags flags, Location start, Location end) + : base (parent, flags, start, end) + { + this.Explicit = this; + } + + #region Properties + + public AnonymousMethodStorey AnonymousMethodStorey { + get { + return am_storey; + } + } + + public bool HasCapturedThis { + set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; } + get { + return (flags & Flags.HasCapturedThis) != 0; + } + } + + public bool HasCapturedVariable { + set { flags = value ? flags | Flags.HasCapturedVariable : flags & ~Flags.HasCapturedVariable; } + get { + return (flags & Flags.HasCapturedVariable) != 0; + } + } + + #endregion + + // + // Creates anonymous method storey in current block + // + public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec) + { + // + // An iterator has only 1 storey block + // + if (ec.CurrentIterator != null) + return ec.CurrentIterator.Storey; + + // + // When referencing a variable in iterator storey from children anonymous method + // + if (ParametersBlock.am_storey is IteratorStorey) { + return ParametersBlock.am_storey; + } + + if (am_storey == null) { + MemberBase mc = ec.MemberContext as MemberBase; + + // + // Creates anonymous method storey for this block + // + am_storey = new AnonymousMethodStorey (this, ec.CurrentMemberDefinition.Parent.PartialContainer, mc, ec.CurrentTypeParameters, "AnonStorey"); + } + + return am_storey; + } + + public override void Emit (EmitContext ec) + { + if (am_storey != null) { + DefineAnonymousStorey (ec); + am_storey.EmitStoreyInstantiation (ec, this); + } + + bool emit_debug_info = SymbolWriter.HasSymbolWriter && Parent != null && !(am_storey is IteratorStorey); + if (emit_debug_info) + ec.BeginScope (); + + base.Emit (ec); + + if (emit_debug_info) + ec.EndScope (); + } + + void DefineAnonymousStorey (EmitContext ec) + { + // + // Creates anonymous method storey + // + if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null) { + // + // Creates parent storey reference when hoisted this is accessible + // + if (am_storey.OriginalSourceBlock.Explicit.HasCapturedThis) { + ExplicitBlock parent = am_storey.OriginalSourceBlock.Explicit.Parent.Explicit; + + // + // Hoisted this exists in top-level parent storey only + // + while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey) + parent = parent.Parent.Explicit; + + am_storey.AddParentStoreyReference (ec, parent.am_storey); + } + + am_storey.SetNestedStoryParent (ec.CurrentAnonymousMethod.Storey); + + // TODO MemberCache: Review + am_storey.Mutator = ec.CurrentAnonymousMethod.Storey.Mutator; + } + + am_storey.CreateType (); + am_storey.DefineType (); + am_storey.ResolveTypeParameters (); + + var ref_blocks = am_storey.ReferencesFromChildrenBlock; + if (ref_blocks != null) { + foreach (ExplicitBlock ref_block in ref_blocks) { + for (ExplicitBlock b = ref_block.Explicit; b.am_storey != am_storey; b = b.Parent.Explicit) { + if (b.am_storey != null) { + b.am_storey.AddParentStoreyReference (ec, am_storey); + + // Stop propagation inside same top block + if (b.ParametersBlock.Original == ParametersBlock.Original) + break; + + b = b.ParametersBlock; + } + + b.HasCapturedVariable = true; + } + } + } + + am_storey.Define (); + am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey); + } + + public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock) + { + tryBlock.statements = statements; + statements = new List (1); + statements.Add (tf); + } + } + + // + // ParametersBlock was introduced to support anonymous methods + // and lambda expressions + // + public class ParametersBlock : ExplicitBlock + { + public class ParameterInfo : INamedBlockVariable + { + readonly ParametersBlock block; + readonly int index; + public VariableInfo VariableInfo; + bool is_locked; + + public ParameterInfo (ParametersBlock block, int index) + { + this.block = block; + this.index = index; + } + + #region Properties + + public Block Block { + get { + return block; + } + } + + public bool IsDeclared { + get { + return true; + } + } + + public bool IsLocked { + get { + return is_locked; + } + set { + is_locked = value; + } + } + + public Location Location { + get { + return Parameter.Location; + } + } + + public Parameter Parameter { + get { + return block.Parameters [index]; + } + } + + public TypeSpec ParameterType { + get { + return Parameter.Type; + } + } + + #endregion + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + return new ParameterReference (this, loc); + } + } + + // + // Block is converted into an expression + // + sealed class BlockScopeExpression : Expression + { + Expression child; + readonly ParametersBlock block; + + public BlockScopeExpression (Expression child, ParametersBlock block) + { + this.child = child; + this.block = block; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (child == null) + return null; + + child = child.Resolve (ec); + if (child == null) + return null; + + eclass = child.eclass; + type = child.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + block.EmitScopeInitializers (ec); + child.Emit (ec); + } + } + + protected ParametersCompiled parameters; + protected ParameterInfo[] parameter_info; + bool resolved; + protected bool unreachable; + protected ToplevelBlock top_block; + + public ParametersBlock (Block parent, ParametersCompiled parameters, Location start) + : base (parent, 0, start, start) + { + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + this.parameters = parameters; + ParametersBlock = this; + + this.top_block = parent.ParametersBlock.top_block; + ProcessParameters (); + } + + protected ParametersBlock (ParametersCompiled parameters, Location start) + : base (null, 0, start, start) + { + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + this.parameters = parameters; + ParametersBlock = this; + } + + // + // It's supposed to be used by method body implementation of anonymous methods + // + protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters) + : base (null, 0, source.StartLocation, source.EndLocation) + { + this.parameters = parameters; + this.statements = source.statements; + this.scope_initializers = source.scope_initializers; + + this.resolved = true; + this.unreachable = source.unreachable; + this.am_storey = source.am_storey; + + ParametersBlock = this; + + // + // Overwrite original for comparison purposes when linking cross references + // between anonymous methods + // + original = source; + } + + #region Properties + + public bool IsAsync + { + get { + return (flags & Flags.IsAsync) != 0; + } + set { + flags = value ? flags | Flags.IsAsync : flags & ~Flags.IsAsync; + } + } + + // + // Block has been converted to expression tree + // + public bool IsExpressionTree { + get { + return (flags & Flags.IsExpressionTree) != 0; + } + } + + // + // The parameters for the block. + // + public ParametersCompiled Parameters { + get { + return parameters; + } + } + + public ToplevelBlock TopBlock { + get { + return top_block; + } + } + + public bool Resolved { + get { + return resolved; + } + } + + #endregion + + // + // Check whether all `out' parameters have been assigned. + // + public void CheckOutParameters (FlowBranching.UsageVector vector, Location loc) + { + if (vector.IsUnreachable) + return; + + int n = parameter_info == null ? 0 : parameter_info.Length; + + for (int i = 0; i < n; i++) { + VariableInfo var = parameter_info[i].VariableInfo; + + if (var == null) + continue; + + if (vector.IsAssigned (var, false)) + continue; + + TopBlock.Report.Error (177, loc, "The out parameter `{0}' must be assigned to before control leaves the current method", + var.Name); + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (statements.Count == 1) { + Expression expr = ((Statement) statements[0]).CreateExpressionTree (ec); + if (scope_initializers != null) + expr = new BlockScopeExpression (expr, this); + + return expr; + } + + return base.CreateExpressionTree (ec); + } + + public ParameterInfo GetParameterInfo (Parameter p) + { + for (int i = 0; i < parameters.Count; ++i) { + if (parameters[i] == p) + return parameter_info[i]; + } + + throw new ArgumentException ("Invalid parameter"); + } + + public Expression GetParameterReference (int index, Location loc) + { + return new ParameterReference (parameter_info[index], loc); + } + + public Statement PerformClone () + { + CloneContext clonectx = new CloneContext (); + return Clone (clonectx); + } + + protected void ProcessParameters () + { + if (parameters.Count == 0) + return; + + parameter_info = new ParameterInfo[parameters.Count]; + for (int i = 0; i < parameter_info.Length; ++i) { + var p = parameters.FixedParameters[i]; + if (p == null) + continue; + + // TODO: Should use Parameter only and more block there + parameter_info[i] = new ParameterInfo (this, i); + if (p.Name != null) + AddLocalName (p.Name, parameter_info[i]); + } + } + + public bool Resolve (FlowBranching parent, BlockContext rc, IMethodData md) + { + if (resolved) + return true; + + resolved = true; + + if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) + flags |= Flags.IsExpressionTree; + + try { + ResolveMeta (rc); + + using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) { + FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent); + + if (!Resolve (rc)) + return false; + + unreachable = top_level.End (); + } + } catch (Exception e) { + if (e is CompletionResult || rc.Report.IsDisabled) + throw; + + if (rc.CurrentBlock != null) { + rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message); + } else { + rc.Report.Error (587, "Internal compiler error: {0}", e.Message); + } + + if (rc.Module.Compiler.Settings.DebugFlags > 0) + throw; + } + + if (rc.ReturnType.Kind != MemberKind.Void && !unreachable) { + if (rc.CurrentAnonymousMethod == null) { + // FIXME: Missing FlowAnalysis for generated iterator MoveNext method + if (md is StateMachineMethod) { + unreachable = true; + } else { + rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ()); + return false; + } + } else { + // + // If an asynchronous body of F is either an expression classified as nothing, or a + // statement block where no return statements have expressions, the inferred return type is Task + // + if (IsAsync) { + var am = rc.CurrentAnonymousMethod as AnonymousMethodBody; + if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) { + am.ReturnTypeInference = null; + am.ReturnType = rc.Module.PredefinedTypes.Task.TypeSpec; + return true; + } + } + + rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'", + rc.CurrentAnonymousMethod.GetSignatureForError ()); + return false; + } + } + + return true; + } + + void ResolveMeta (BlockContext ec) + { + int orig_count = parameters.Count; + + for (int i = 0; i < orig_count; ++i) { + Parameter.Modifier mod = parameters.FixedParameters[i].ModFlags; + + if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) + continue; + + VariableInfo vi = new VariableInfo (parameters, i, ec.FlowOffset); + parameter_info[i].VariableInfo = vi; + ec.FlowOffset += vi.Length; + } + } + + public void WrapIntoIterator (IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) + { + ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); + pb.EndLocation = EndLocation; + pb.statements = statements; + + var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable); + am_storey = new IteratorStorey (iterator); + + statements = new List (1); + AddStatement (new Return (iterator, iterator.Location)); + } + + public void WrapIntoAsyncTask (TypeContainer host, TypeSpec returnType) + { + ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); + pb.EndLocation = EndLocation; + pb.statements = statements; + + var block_type = host.Module.Compiler.BuiltinTypes.Void; + var initializer = new AsyncInitializer (pb, host, block_type); + initializer.Type = block_type; + + am_storey = new AsyncTaskStorey (initializer, returnType); + + statements = new List (1); + AddStatement (new StatementExpression (initializer)); + } + } + + // + // + // + public class ToplevelBlock : ParametersBlock + { + LocalVariable this_variable; + CompilerContext compiler; + Dictionary names; + Dictionary labels; + + public HoistedVariable HoistedThisVariable; + + public Report Report { + get { return compiler.Report; } + } + + public ToplevelBlock (CompilerContext ctx, Location loc) + : this (ctx, ParametersCompiled.EmptyReadOnlyParameters, loc) + { + } + + public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) + : base (parameters, start) + { + this.compiler = ctx; + top_block = this; + + ProcessParameters (); + } + + // + // Recreates a top level block from parameters block. Used for + // compiler generated methods where the original block comes from + // explicit child block. This works for already resolved blocks + // only to ensure we resolve them in the correct flow order + // + public ToplevelBlock (ParametersBlock source, ParametersCompiled parameters) + : base (source, parameters) + { + this.compiler = source.TopBlock.compiler; + top_block = this; + } + + public bool IsIterator + { + get { + return (flags & Flags.IsIterator) != 0; + } + set { + flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator; + } + } + + public override void AddLocalName (string name, INamedBlockVariable li) + { + if (names == null) + names = new Dictionary (); + + object value; + if (!names.TryGetValue (name, out value)) { + names.Add (name, li); + return; + } + + INamedBlockVariable existing = value as INamedBlockVariable; + List existing_list; + if (existing != null) { + existing_list = new List (); + existing_list.Add (existing); + names[name] = existing_list; + } else { + existing_list = (List) value; + } + + // + // A collision checking between local names + // + for (int i = 0; i < existing_list.Count; ++i) { + existing = existing_list[i]; + Block b = existing.Block; + + // Collision at same level + if (li.Block == b) { + li.Block.Error_AlreadyDeclared (name, li); + break; + } + + // Collision with parent + b = li.Block; + while ((b = b.Parent) != null) { + if (existing.Block == b) { + li.Block.Error_AlreadyDeclared (name, li, "parent or current"); + i = existing_list.Count; + break; + } + } + + // Collision with with children + b = existing.Block; + while ((b = b.Parent) != null) { + if (li.Block == b) { + li.Block.Error_AlreadyDeclared (name, li, "child"); + i = existing_list.Count; + break; + } + } + } + + existing_list.Add (li); + } + + public void AddLabel (string name, LabeledStatement label) + { + if (labels == null) + labels = new Dictionary (); + + object value; + if (!labels.TryGetValue (name, out value)) { + labels.Add (name, label); + return; + } + + LabeledStatement existing = value as LabeledStatement; + List existing_list; + if (existing != null) { + existing_list = new List (); + existing_list.Add (existing); + labels[name] = existing_list; + } else { + existing_list = (List) value; + } + + // + // A collision checking between labels + // + for (int i = 0; i < existing_list.Count; ++i) { + existing = existing_list[i]; + Block b = existing.Block; + + // Collision at same level + if (label.Block == b) { + Report.SymbolRelatedToPreviousError (existing.loc, name); + Report.Error (140, label.loc, "The label `{0}' is a duplicate", name); + break; + } + + // Collision with parent + b = label.Block; + while ((b = b.Parent) != null) { + if (existing.Block == b) { + Report.Error (158, label.loc, + "The label `{0}' shadows another label by the same name in a contained scope", name); + i = existing_list.Count; + break; + } + } + + // Collision with with children + b = existing.Block; + while ((b = b.Parent) != null) { + if (label.Block == b) { + Report.Error (158, label.loc, + "The label `{0}' shadows another label by the same name in a contained scope", name); + i = existing_list.Count; + break; + } + } + } + + existing_list.Add (label); + } + + // + // Creates an arguments set from all parameters, useful for method proxy calls + // + public Arguments GetAllParametersArguments () + { + int count = parameters.Count; + Arguments args = new Arguments (count); + for (int i = 0; i < count; ++i) { + var arg_expr = GetParameterReference (i, parameter_info[i].Location); + args.Add (new Argument (arg_expr)); + } + + return args; + } + + // + // Lookup inside a block, the returned value can represent 3 states + // + // true+variable: A local name was found and it's valid + // false+variable: A local name was found in a child block only + // false+null: No local name was found + // + public bool GetLocalName (string name, Block block, ref INamedBlockVariable variable) + { + if (names == null) + return false; + + object value; + if (!names.TryGetValue (name, out value)) + return false; + + variable = value as INamedBlockVariable; + Block b = block; + if (variable != null) { + do { + if (variable.Block == b.Original) + return true; + + b = b.Parent; + } while (b != null); + + b = variable.Block; + do { + if (block == b) + return false; + + b = b.Parent; + } while (b != null); + } else { + List list = (List) value; + for (int i = 0; i < list.Count; ++i) { + variable = list[i]; + do { + if (variable.Block == b.Original) + return true; + + b = b.Parent; + } while (b != null); + + b = variable.Block; + do { + if (block == b) + return false; + + b = b.Parent; + } while (b != null); + + b = block; + } + } + + variable = null; + return false; + } + + public LabeledStatement GetLabel (string name, Block block) + { + if (labels == null) + return null; + + object value; + if (!labels.TryGetValue (name, out value)) { + return null; + } + + var label = value as LabeledStatement; + Block b = block; + if (label != null) { + if (label.Block == b.Original) + return label; + + // TODO: Temporary workaround for the switch block implicit label block + if (label.Block.IsCompilerGenerated && label.Block.Parent == b.Original) + return label; + } else { + List list = (List) value; + for (int i = 0; i < list.Count; ++i) { + label = list[i]; + if (label.Block == b.Original) + return label; + + // TODO: Temporary workaround for the switch block implicit label block + if (label.Block.IsCompilerGenerated && label.Block.Parent == b.Original) + return label; + } + } + + return null; + } + + // + // Returns the "this" instance variable of this block. + // See AddThisVariable() for more information. + // + public LocalVariable ThisVariable { + get { return this_variable; } + } + + // + // This is used by non-static `struct' constructors which do not have an + // initializer - in this case, the constructor must initialize all of the + // struct's fields. To do this, we add a "this" variable and use the flow + // analysis code to ensure that it's been fully initialized before control + // leaves the constructor. + // + public LocalVariable AddThisVariable (BlockContext bc, TypeContainer ds, Location l) + { + if (this_variable == null) { + this_variable = new LocalVariable (this, "this", LocalVariable.Flags.IsThis | LocalVariable.Flags.Used, l); + this_variable.Type = ds.CurrentType; + this_variable.PrepareForFlowAnalysis (bc); + } + + return this_variable; + } + + public bool IsThisAssigned (BlockContext ec) + { + return this_variable == null || this_variable.IsThisAssigned (ec, this); + } + + public override void Emit (EmitContext ec) + { + if (Report.Errors > 0) + return; + +#if PRODUCTION + try { +#endif + if (ec.HasReturnLabel) + ec.ReturnLabel = ec.DefineLabel (); + + base.Emit (ec); + + ec.Mark (EndLocation); + + if (ec.HasReturnLabel) + ec.MarkLabel (ec.ReturnLabel); + + if (ec.return_value != null) { + ec.Emit (OpCodes.Ldloc, ec.return_value); + ec.Emit (OpCodes.Ret); + } else { + // + // If `HasReturnLabel' is set, then we already emitted a + // jump to the end of the method, so we must emit a `ret' + // there. + // + // Unfortunately, System.Reflection.Emit automatically emits + // a leave to the end of a finally block. This is a problem + // if no code is following the try/finally block since we may + // jump to a point after the end of the method. + // As a workaround, we're always creating a return label in + // this case. + // + + if (ec.HasReturnLabel || !unreachable) { + if (ec.ReturnType.Kind != MemberKind.Void) + ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ()); + ec.Emit (OpCodes.Ret); + } + } + +#if PRODUCTION + } catch (Exception e){ + Console.WriteLine ("Exception caught by the compiler while emitting:"); + Console.WriteLine (" Block that caused the problem begin at: " + block.loc); + + Console.WriteLine (e.GetType ().FullName + ": " + e.Message); + throw; + } +#endif + } + + protected override void EmitSymbolInfo (EmitContext ec) + { + AnonymousExpression ae = ec.CurrentAnonymousMethod; + if ((ae != null) && (ae.Storey != null)) + SymbolWriter.DefineScopeVariable (ae.Storey.ID); + + base.EmitSymbolInfo (ec); + } + } + + public class SwitchLabel { + Expression label; + Constant converted; + readonly Location loc; + + Label? il_label; + + // + // if expr == null, then it is the default case. + // + public SwitchLabel (Expression expr, Location l) + { + label = expr; + loc = l; + } + + public bool IsDefault { + get { + return label == null; + } + } + + public Expression Label { + get { + return label; + } + } + + public Location Location { + get { + return loc; + } + } + + public Constant Converted { + get { + return converted; + } + set { + converted = value; + } + } + + public Label GetILLabel (EmitContext ec) + { + if (il_label == null){ + il_label = ec.DefineLabel (); + } + + return il_label.Value; + } + + // + // Resolves the expression, reduces it to a literal if possible + // and then converts it to the requested type. + // + public bool ResolveAndReduce (ResolveContext ec, TypeSpec required_type, bool allow_nullable) + { + Expression e = label.Resolve (ec); + + if (e == null) + return false; + + Constant c = e as Constant; + if (c == null){ + ec.Report.Error (150, loc, "A constant value is expected"); + return false; + } + + if (allow_nullable && c is NullLiteral) { + converted = c; + return true; + } + + converted = c.ImplicitConversionRequired (ec, required_type, loc); + return converted != null; + } + + public void Error_AlreadyOccurs (ResolveContext ec, TypeSpec switch_type, SwitchLabel collision_with) + { + string label; + if (converted == null) + label = "default"; + else + label = converted.GetValueAsLiteral (); + + ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null); + ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label); + } + + public SwitchLabel Clone (CloneContext clonectx) + { + if (label == null) + return this; + + return new SwitchLabel (label.Clone (clonectx), loc); + } + } + + public class SwitchSection { + public readonly List Labels; + public readonly Block Block; + + public SwitchSection (List labels, Block block) + { + Labels = labels; + Block = block; + } + + public SwitchSection Clone (CloneContext clonectx) + { + var cloned_labels = new List (); + + foreach (SwitchLabel sl in Labels) + cloned_labels.Add (sl.Clone (clonectx)); + + return new SwitchSection (cloned_labels, clonectx.LookupBlock (Block)); + } + } + + public class Switch : Statement + { + // structure used to hold blocks of keys while calculating table switch + sealed class LabelsRange : IComparable + { + public readonly long min; + public long max; + public readonly List label_values; + + public LabelsRange (long value) + { + min = max = value; + label_values = new List (); + label_values.Add (value); + } + + public LabelsRange (long min, long max, ICollection values) + { + this.min = min; + this.max = max; + this.label_values = new List (values); + } + + public long Range { + get { + return max - min + 1; + } + } + + public bool AddValue (long value) + { + var gap = value - min + 1; + // Ensure the range has > 50% occupancy + if (gap > 2 * (label_values.Count + 1) || gap <= 0) + return false; + + max = value; + label_values.Add (value); + return true; + } + + public int CompareTo (LabelsRange other) + { + int nLength = label_values.Count; + int nLengthOther = other.label_values.Count; + if (nLengthOther == nLength) + return (int) (other.min - min); + + return nLength - nLengthOther; + } + } + + public List Sections; + public Expression Expr; + + // + // Mapping of all labels to their SwitchLabels + // + Dictionary labels; + Dictionary string_labels; + + /// + /// The governing switch type + /// + public TypeSpec SwitchType; + + // + // Computed + // + Label default_target; + Label null_target; + Expression new_expr; + bool is_constant; + + SwitchSection constant_section; + SwitchSection default_section; + SwitchLabel null_section; + + ExpressionStatement string_dictionary; + FieldExpr switch_cache_field; + static int unique_counter; + ExplicitBlock block; + + // + // Nullable Types support + // + Nullable.Unwrap unwrap; + + public Switch (Expression e, ExplicitBlock block, List sects, Location l) + { + Expr = e; + this.block = block; + Sections = sects; + loc = l; + } + + public ExplicitBlock Block { + get { + return block; + } + } + + public Label DefaultLabel { + get { + return default_target; + } + } + + public bool GotDefault { + get { + return default_section != null; + } + } + + public bool IsNullable { + get { + return unwrap != null; + } + } + + // + // Determines the governing type for a switch. The returned + // expression might be the expression from the switch, or an + // expression that includes any potential conversions to + // + Expression SwitchGoverningType (ResolveContext ec, Expression expr) + { + switch (expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Bool: + return expr; + } + + if (expr.Type.IsEnum) + return expr; + + // + // Try to find a *user* defined implicit conversion. + // + // If there is no implicit conversion, or if there are multiple + // conversions, we have to report an error + // + Expression converted = null; + foreach (TypeSpec tt in ec.BuiltinTypes.SwitchUserTypes) { + Expression e; + + e = Convert.ImplicitUserConversion (ec, expr, tt, loc); + if (e == null) + continue; + + // + // Ignore over-worked ImplicitUserConversions that do + // an implicit conversion in addition to the user conversion. + // + if (!(e is UserCast)) + continue; + + if (converted != null){ + ec.Report.ExtraInformation (loc, "(Ambiguous implicit user defined conversion in previous "); + return null; + } + + converted = e; + } + return converted; + } + + public static TypeSpec[] CreateSwitchUserTypes (BuiltinTypes types) + { + // LAMESPEC: For some reason it does not contain bool which looks like csc bug + return new[] { + types.SByte, + types.Byte, + types.Short, + types.UShort, + types.Int, + types.UInt, + types.Long, + types.ULong, + types.Char, + types.String + }; + } + + // + // Performs the basic sanity checks on the switch statement + // (looks for duplicate keys and non-constant expressions). + // + // It also returns a hashtable with the keys that we will later + // use to compute the switch tables + // + bool CheckSwitch (ResolveContext ec) + { + bool error = false; + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String) + string_labels = new Dictionary (Sections.Count + 1); + else + labels = new Dictionary (Sections.Count + 1); + + foreach (SwitchSection ss in Sections){ + foreach (SwitchLabel sl in ss.Labels){ + if (sl.IsDefault){ + if (default_section != null){ + sl.Error_AlreadyOccurs (ec, SwitchType, default_section.Labels [0]); + error = true; + } + default_section = ss; + continue; + } + + if (!sl.ResolveAndReduce (ec, SwitchType, IsNullable)) { + error = true; + continue; + } + + try { + if (string_labels != null) { + string s = sl.Converted.GetValue () as string; + if (s == null) + null_section = sl; + else + string_labels.Add (s, sl); + } else { + if (sl.Converted is NullLiteral) { + null_section = sl; + } else { + labels.Add (sl.Converted.GetValueAsLong (), sl); + } + } + } catch (ArgumentException) { + if (string_labels != null) + sl.Error_AlreadyOccurs (ec, SwitchType, string_labels[(string) sl.Converted.GetValue ()]); + else + sl.Error_AlreadyOccurs (ec, SwitchType, labels[sl.Converted.GetValueAsLong ()]); + + error = true; + } + } + } + return !error; + } + + // + // This method emits code for a lookup-based switch statement (non-string) + // Basically it groups the cases into blocks that are at least half full, + // and then spits out individual lookup opcodes for each block. + // It emits the longest blocks first, and short blocks are just + // handled with direct compares. + // + void EmitTableSwitch (EmitContext ec, Expression val) + { + Label lbl_default = default_target; + + if (labels.Count > 0) { + List ranges; + if (string_labels != null) { + // We have done all hard work for string already + // setup single range only + ranges = new List (1); + ranges.Add (new LabelsRange (0, labels.Count - 1, labels.Keys)); + } else { + var element_keys = new long[labels.Count]; + labels.Keys.CopyTo (element_keys, 0); + Array.Sort (element_keys); + + // + // Build possible ranges of switch labes to reduce number + // of comparisons + // + ranges = new List (element_keys.Length); + var range = new LabelsRange (element_keys[0]); + ranges.Add (range); + for (int i = 1; i < element_keys.Length; ++i) { + var l = element_keys[i]; + if (range.AddValue (l)) + continue; + + range = new LabelsRange (l); + ranges.Add (range); + } + + // sort the blocks so we can tackle the largest ones first + ranges.Sort (); + } + + TypeSpec compare_type = TypeManager.IsEnumType (SwitchType) ? EnumSpec.GetUnderlyingType (SwitchType) : SwitchType; + + for (int range_index = ranges.Count - 1; range_index >= 0; --range_index) { + LabelsRange kb = ranges[range_index]; + lbl_default = (range_index == 0) ? default_target : ec.DefineLabel (); + + // Optimize small ranges using simple equality check + if (kb.Range <= 2) { + foreach (var key in kb.label_values) { + SwitchLabel sl = labels[key]; + if (sl.Converted.IsDefaultValue) { + val.EmitBranchable (ec, sl.GetILLabel (ec), false); + } else { + val.Emit (ec); + sl.Converted.Emit (ec); + ec.Emit (OpCodes.Beq, sl.GetILLabel (ec)); + } + } + } else { + // TODO: if all the keys in the block are the same and there are + // no gaps/defaults then just use a range-check. + if (compare_type.BuiltinType == BuiltinTypeSpec.Type.Long || compare_type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + // TODO: optimize constant/I4 cases + + // check block range (could be > 2^31) + val.Emit (ec); + ec.EmitLong (kb.min); + ec.Emit (OpCodes.Blt, lbl_default); + + val.Emit (ec); + ec.EmitLong (kb.max); + ec.Emit (OpCodes.Bgt, lbl_default); + + // normalize range + val.Emit (ec); + if (kb.min != 0) { + ec.EmitLong (kb.min); + ec.Emit (OpCodes.Sub); + } + + ec.Emit (OpCodes.Conv_I4); // assumes < 2^31 labels! + } else { + // normalize range + val.Emit (ec); + int first = (int) kb.min; + if (first > 0) { + ec.EmitInt (first); + ec.Emit (OpCodes.Sub); + } else if (first < 0) { + ec.EmitInt (-first); + ec.Emit (OpCodes.Add); + } + } + + // first, build the list of labels for the switch + int iKey = 0; + long cJumps = kb.Range; + Label[] switch_labels = new Label[cJumps]; + for (int iJump = 0; iJump < cJumps; iJump++) { + var key = kb.label_values[iKey]; + if (key == kb.min + iJump) { + switch_labels[iJump] = labels[key].GetILLabel (ec); + iKey++; + } else { + switch_labels[iJump] = lbl_default; + } + } + + // emit the switch opcode + ec.Emit (OpCodes.Switch, switch_labels); + } + + // mark the default for this block + if (range_index != 0) + ec.MarkLabel (lbl_default); + } + + // the last default just goes to the end + if (ranges.Count > 0) + ec.Emit (OpCodes.Br, lbl_default); + } + + // now emit the code for the sections + bool found_default = false; + + foreach (SwitchSection ss in Sections) { + foreach (SwitchLabel sl in ss.Labels) { + if (sl.IsDefault) { + ec.MarkLabel (lbl_default); + found_default = true; + if (null_section == null) + ec.MarkLabel (null_target); + } else if (sl.Converted.IsNull) { + ec.MarkLabel (null_target); + } + + ec.MarkLabel (sl.GetILLabel (ec)); + } + + ss.Block.Emit (ec); + } + + if (!found_default) { + ec.MarkLabel (lbl_default); + if (null_section == null) { + ec.MarkLabel (null_target); + } + } + } + + SwitchLabel FindLabel (Constant value) + { + SwitchLabel sl = null; + + if (string_labels != null) { + string s = value.GetValue () as string; + if (s == null) { + if (null_section != null) + sl = null_section; + else if (default_section != null) + sl = default_section.Labels[0]; + } else { + string_labels.TryGetValue (s, out sl); + } + } else { + if (value is NullLiteral) { + sl = null_section; + } else { + labels.TryGetValue (value.GetValueAsLong (), out sl); + } + } + + return sl; + } + + SwitchSection FindSection (SwitchLabel label) + { + foreach (SwitchSection ss in Sections){ + foreach (SwitchLabel sl in ss.Labels){ + if (label == sl) + return ss; + } + } + + return null; + } + + public static void Reset () + { + unique_counter = 0; + } + + public override bool Resolve (BlockContext ec) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return false; + + new_expr = SwitchGoverningType (ec, Expr); + + if (new_expr == null && Expr.Type.IsNullableType) { + unwrap = Nullable.Unwrap.Create (Expr, false); + if (unwrap == null) + return false; + + new_expr = SwitchGoverningType (ec, unwrap); + } + + if (new_expr == null){ + ec.Report.Error (151, loc, + "A switch expression of type `{0}' cannot be converted to an integral type, bool, char, string, enum or nullable type", + TypeManager.CSharpName (Expr.Type)); + return false; + } + + // Validate switch. + SwitchType = new_expr.Type; + + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.Bool && ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { + ec.Report.FeatureIsNotAvailable (ec.Module.Compiler, loc, "switch expression of boolean type"); + return false; + } + + if (!CheckSwitch (ec)) + return false; + + Switch old_switch = ec.Switch; + ec.Switch = this; + ec.Switch.SwitchType = SwitchType; + + ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc); + + var constant = new_expr as Constant; + if (constant != null) { + is_constant = true; + SwitchLabel label = FindLabel (constant); + if (label != null) + constant_section = FindSection (label); + + if (constant_section == null) + constant_section = default_section; + } + + bool first = true; + bool ok = true; + foreach (SwitchSection ss in Sections){ + if (!first) + ec.CurrentBranching.CreateSibling ( + null, FlowBranching.SiblingType.SwitchSection); + else + first = false; + + if (is_constant && (ss != constant_section)) { + // If we're a constant switch, we're only emitting + // one single section - mark all the others as + // unreachable. + ec.CurrentBranching.CurrentUsageVector.Goto (); + if (!ss.Block.ResolveUnreachable (ec, true)) { + ok = false; + } + } else { + if (!ss.Block.Resolve (ec)) + ok = false; + } + } + + if (default_section == null) + ec.CurrentBranching.CreateSibling ( + null, FlowBranching.SiblingType.SwitchSection); + + ec.EndFlowBranching (); + ec.Switch = old_switch; + + if (!ok) + return false; + + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String && !is_constant) { + // TODO: Optimize single case, and single+default case + ResolveStringSwitchMap (ec); + } + + return true; + } + + public SwitchLabel ResolveGotoCase (ResolveContext rc, Constant value) + { + var sl = FindLabel (value); + + if (sl == null) { + FlowBranchingBlock.Error_UnknownLabel (loc, "case " + value.GetValueAsLiteral (), rc.Report); + } + + return sl; + } + + void ResolveStringSwitchMap (ResolveContext ec) + { + FullNamedExpression string_dictionary_type; + if (ec.Module.PredefinedTypes.Dictionary.Define ()) { + string_dictionary_type = new TypeExpression ( + ec.Module.PredefinedTypes.Dictionary.TypeSpec.MakeGenericType (ec, + new [] { ec.BuiltinTypes.String, ec.BuiltinTypes.Int }), + loc); + } else if (ec.Module.PredefinedTypes.Hashtable.Define ()) { + string_dictionary_type = new TypeExpression (ec.Module.PredefinedTypes.Hashtable.TypeSpec, loc); + } else { + ec.Module.PredefinedTypes.Dictionary.Resolve (); + return; + } + + var ctype = ec.CurrentMemberDefinition.Parent.PartialContainer; + Field field = new Field (ctype, string_dictionary_type, + Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, + new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null); + if (!field.Define ()) + return; + ctype.AddField (field); + + var init = new List (); + int counter = 0; + labels = new Dictionary (string_labels.Count); + string value = null; + foreach (SwitchSection section in Sections) { + bool contains_label = false; + foreach (SwitchLabel sl in section.Labels) { + if (sl.IsDefault || sl.Converted.IsNull) + continue; + + if (!contains_label) { + labels.Add (counter, sl); + contains_label = true; + } + + value = (string) sl.Converted.GetValue (); + var init_args = new List (2); + init_args.Add (new StringLiteral (ec.BuiltinTypes, value, sl.Location)); + + sl.Converted = new IntConstant (ec.BuiltinTypes, counter, loc); + init_args.Add (sl.Converted); + + init.Add (new CollectionElementInitializer (init_args, loc)); + } + + // + // Don't add empty sections + // + if (contains_label) + ++counter; + } + + Arguments args = new Arguments (1); + args.Add (new Argument (new IntConstant (ec.BuiltinTypes, init.Count, loc))); + Expression initializer = new NewInitialize (string_dictionary_type, args, + new CollectionOrObjectInitializers (init, loc), loc); + + switch_cache_field = new FieldExpr (field, loc); + string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec)); + } + + void DoEmitStringSwitch (LocalTemporary value, EmitContext ec) + { + Label l_initialized = ec.DefineLabel (); + + // + // Skip initialization when value is null + // + value.EmitBranchable (ec, null_target, false); + + // + // Check if string dictionary is initialized and initialize + // + switch_cache_field.EmitBranchable (ec, l_initialized, true); + string_dictionary.EmitStatement (ec); + ec.MarkLabel (l_initialized); + + LocalTemporary string_switch_variable = new LocalTemporary (ec.BuiltinTypes.Int); + + ResolveContext rc = new ResolveContext (ec.MemberContext); + + if (switch_cache_field.Type.IsGeneric) { + Arguments get_value_args = new Arguments (2); + get_value_args.Add (new Argument (value)); + get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out)); + Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (rc); + if (get_item == null) + return; + + // + // A value was not found, go to default case + // + get_item.EmitBranchable (ec, default_target, false); + } else { + Arguments get_value_args = new Arguments (1); + get_value_args.Add (new Argument (value)); + + Expression get_item = new ElementAccess (switch_cache_field, get_value_args, loc).Resolve (rc); + if (get_item == null) + return; + + LocalTemporary get_item_object = new LocalTemporary (ec.BuiltinTypes.Object); + get_item_object.EmitAssign (ec, get_item, true, false); + ec.Emit (OpCodes.Brfalse, default_target); + + ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable, + new Cast (new TypeExpression (ec.BuiltinTypes.Int, loc), get_item_object, loc)).Resolve (rc); + + get_item_int.EmitStatement (ec); + get_item_object.Release (ec); + } + + EmitTableSwitch (ec, string_switch_variable); + string_switch_variable.Release (ec); + } + + protected override void DoEmit (EmitContext ec) + { + // + // Needed to emit anonymous storey initialization + // Otherwise it does not contain any statements for now + // + block.Emit (ec); + + default_target = ec.DefineLabel (); + null_target = ec.DefineLabel (); + + // Store variable for comparission purposes + // TODO: Don't duplicate non-captured VariableReference + LocalTemporary value; + if (IsNullable) { + value = new LocalTemporary (SwitchType); + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, null_target); + new_expr.Emit (ec); + value.Store (ec); + } else if (!is_constant) { + value = new LocalTemporary (SwitchType); + new_expr.Emit (ec); + value.Store (ec); + } else + value = null; + + // + // Setup the codegen context + // + Label old_end = ec.LoopEnd; + Switch old_switch = ec.Switch; + + ec.LoopEnd = ec.DefineLabel (); + ec.Switch = this; + + // Emit Code. + if (is_constant) { + if (constant_section != null) + constant_section.Block.Emit (ec); + } else if (string_dictionary != null) { + DoEmitStringSwitch (value, ec); + } else { + EmitTableSwitch (ec, value); + } + + if (value != null) + value.Release (ec); + + // Restore context state. + ec.MarkLabel (ec.LoopEnd); + + // + // Restore the previous context + // + ec.LoopEnd = old_end; + ec.Switch = old_switch; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Switch target = (Switch) t; + + target.Expr = Expr.Clone (clonectx); + target.Sections = new List (); + foreach (SwitchSection ss in Sections){ + target.Sections.Add (ss.Clone (clonectx)); + } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // A place where execution can restart in an iterator + public abstract class ResumableStatement : Statement + { + bool prepared; + protected Label resume_point; + + public Label PrepareForEmit (EmitContext ec) + { + if (!prepared) { + prepared = true; + resume_point = ec.DefineLabel (); + } + return resume_point; + } + + public virtual Label PrepareForDispose (EmitContext ec, Label end) + { + return end; + } + + public virtual void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher) + { + } + } + + // Base class for statements that are implemented in terms of try...finally + public abstract class ExceptionStatement : ResumableStatement + { + bool code_follows; + Iterator iter; + List resume_points; + int first_resume_pc; + protected Statement stmt; + Label dispose_try_block; + bool prepared_for_dispose, emitted_dispose; + + protected ExceptionStatement (Statement stmt, Location loc) + { + this.stmt = stmt; + this.loc = loc; + } + + #region Properties + + public Statement Statement { + get { + return stmt; + } + } + + #endregion + + protected abstract void EmitPreTryBody (EmitContext ec); + protected abstract void EmitTryBody (EmitContext ec); + protected abstract void EmitFinallyBody (EmitContext ec); + + protected sealed override void DoEmit (EmitContext ec) + { + EmitPreTryBody (ec); + + if (resume_points != null) { + ec.EmitInt ((int) IteratorStorey.State.Running); + ec.Emit (OpCodes.Stloc, iter.CurrentPC); + } + + ec.BeginExceptionBlock (); + + if (resume_points != null) { + ec.MarkLabel (resume_point); + + // For normal control flow, we want to fall-through the Switch + // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above + ec.Emit (OpCodes.Ldloc, iter.CurrentPC); + ec.EmitInt (first_resume_pc); + ec.Emit (OpCodes.Sub); + + Label [] labels = new Label [resume_points.Count]; + for (int i = 0; i < resume_points.Count; ++i) + labels [i] = resume_points [i].PrepareForEmit (ec); + ec.Emit (OpCodes.Switch, labels); + } + + EmitTryBody (ec); + + ec.BeginFinallyBlock (); + + Label start_finally = ec.DefineLabel (); + if (resume_points != null) { + ec.Emit (OpCodes.Ldloc, iter.SkipFinally); + ec.Emit (OpCodes.Brfalse_S, start_finally); + ec.Emit (OpCodes.Endfinally); + } + + ec.MarkLabel (start_finally); + EmitFinallyBody (ec); + + ec.EndExceptionBlock (); + } + + public void SomeCodeFollows () + { + code_follows = true; + } + + public override bool Resolve (BlockContext ec) + { + // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause + // So, ensure there's some IL code after this statement. + if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) + ec.NeedReturnLabel (); + + iter = ec.CurrentIterator; + return true; + } + + public void AddResumePoint (ResumableStatement stmt, int pc) + { + if (resume_points == null) { + resume_points = new List (); + first_resume_pc = pc; + } + + if (pc != first_resume_pc + resume_points.Count) + throw new InternalErrorException ("missed an intervening AddResumePoint?"); + + resume_points.Add (stmt); + } + + public override Label PrepareForDispose (EmitContext ec, Label end) + { + if (!prepared_for_dispose) { + prepared_for_dispose = true; + dispose_try_block = ec.DefineLabel (); + } + return dispose_try_block; + } + + public override void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher) + { + if (emitted_dispose) + return; + + emitted_dispose = true; + + Label end_of_try = ec.DefineLabel (); + + // Ensure that the only way we can get into this code is through a dispatcher + if (have_dispatcher) + ec.Emit (OpCodes.Br, end); + + ec.BeginExceptionBlock (); + + ec.MarkLabel (dispose_try_block); + + Label [] labels = null; + for (int i = 0; i < resume_points.Count; ++i) { + ResumableStatement s = resume_points [i]; + Label ret = s.PrepareForDispose (ec, end_of_try); + if (ret.Equals (end_of_try) && labels == null) + continue; + if (labels == null) { + labels = new Label [resume_points.Count]; + for (int j = 0; j < i; ++j) + labels [j] = end_of_try; + } + labels [i] = ret; + } + + if (labels != null) { + int j; + for (j = 1; j < labels.Length; ++j) + if (!labels [0].Equals (labels [j])) + break; + bool emit_dispatcher = j < labels.Length; + + if (emit_dispatcher) { + //SymbolWriter.StartIteratorDispatcher (ec.ig); + ec.Emit (OpCodes.Ldloc, pc); + ec.EmitInt (first_resume_pc); + ec.Emit (OpCodes.Sub); + ec.Emit (OpCodes.Switch, labels); + //SymbolWriter.EndIteratorDispatcher (ec.ig); + } + + foreach (ResumableStatement s in resume_points) + s.EmitForDispose (ec, pc, end_of_try, emit_dispatcher); + } + + ec.MarkLabel (end_of_try); + + ec.BeginFinallyBlock (); + + EmitFinallyBody (ec); + + ec.EndExceptionBlock (); + } + } + + public class Lock : ExceptionStatement + { + Expression expr; + TemporaryVariableReference expr_copy; + TemporaryVariableReference lock_taken; + + public Lock (Expression expr, Statement stmt, Location loc) + : base (stmt, loc) + { + this.expr = expr; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return false; + + if (!TypeSpec.IsReferenceType (expr.Type)) { + ec.Report.Error (185, loc, + "`{0}' is not a reference type as required by the lock statement", + expr.Type.GetSignatureForError ()); + } + + if (expr.Type.IsGenericParameter) { + expr = Convert.ImplicitTypeParameterConversion (expr, (TypeParameterSpec)expr.Type, ec.BuiltinTypes.Object); + } + + VariableReference lv = expr as VariableReference; + bool locked; + if (lv != null) { + locked = lv.IsLockedByStatement; + lv.IsLockedByStatement = true; + } else { + lv = null; + locked = false; + } + + using (ec.Set (ResolveContext.Options.LockScope)) { + ec.StartFlowBranching (this); + Statement.Resolve (ec); + ec.EndFlowBranching (); + } + + if (lv != null) { + lv.IsLockedByStatement = locked; + } + + base.Resolve (ec); + + // + // Have to keep original lock value around to unlock same location + // in the case the original has changed or is null + // + expr_copy = TemporaryVariableReference.Create (ec.BuiltinTypes.Object, ec.CurrentBlock.Parent, loc); + expr_copy.Resolve (ec); + + // + // Ensure Monitor methods are available + // + if (ResolvePredefinedMethods (ec) > 1) { + lock_taken = TemporaryVariableReference.Create (ec.BuiltinTypes.Bool, ec.CurrentBlock.Parent, loc); + lock_taken.Resolve (ec); + } + + return true; + } + + protected override void EmitPreTryBody (EmitContext ec) + { + expr_copy.EmitAssign (ec, expr); + + if (lock_taken != null) { + // + // Initialize ref variable + // + lock_taken.EmitAssign (ec, new BoolLiteral (ec.BuiltinTypes, false, loc)); + } else { + // + // Monitor.Enter (expr_copy) + // + expr_copy.Emit (ec); + ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter.Get ()); + } + } + + protected override void EmitTryBody (EmitContext ec) + { + // + // Monitor.Enter (expr_copy, ref lock_taken) + // + if (lock_taken != null) { + expr_copy.Emit (ec); + lock_taken.LocalInfo.CreateBuilder (ec); + lock_taken.AddressOf (ec, AddressOp.Load); + ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter_v4.Get ()); + } + + Statement.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + // + // if (lock_taken) Monitor.Exit (expr_copy) + // + Label skip = ec.DefineLabel (); + + if (lock_taken != null) { + lock_taken.Emit (ec); + ec.Emit (OpCodes.Brfalse_S, skip); + } + + expr_copy.Emit (ec); + var m = ec.Module.PredefinedMembers.MonitorExit.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + + ec.MarkLabel (skip); + } + + int ResolvePredefinedMethods (ResolveContext rc) + { + // Try 4.0 Monitor.Enter (object, ref bool) overload first + var m = rc.Module.PredefinedMembers.MonitorEnter_v4.Get (); + if (m != null) + return 4; + + m = rc.Module.PredefinedMembers.MonitorEnter.Get (); + if (m != null) + return 1; + + rc.Module.PredefinedMembers.MonitorEnter_v4.Resolve (loc); + return 0; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Lock target = (Lock) t; + + target.expr = expr.Clone (clonectx); + target.stmt = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public class Unchecked : Statement { + public Block Block; + + public Unchecked (Block b, Location loc) + { + Block = b; + b.Unchecked = true; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Unchecked target = (Unchecked) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Checked : Statement { + public Block Block; + + public Checked (Block b, Location loc) + { + Block = b; + b.Unchecked = false; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Checked target = (Checked) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Unsafe : Statement { + public Block Block; + + public Unsafe (Block b, Location loc) + { + Block = b; + Block.Unsafe = true; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + if (ec.CurrentIterator != null) + ec.Report.Error (1629, loc, "Unsafe code may not appear in iterators"); + + using (ec.Set (ResolveContext.Options.UnsafeScope)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Unsafe target = (Unsafe) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Fixed statement + // + public class Fixed : Statement + { + abstract class Emitter : ShimExpression + { + protected LocalVariable vi; + + protected Emitter (Expression expr, LocalVariable li) + : base (expr) + { + vi = li; + } + + public abstract void EmitExit (EmitContext ec); + } + + class ExpressionEmitter : Emitter { + public ExpressionEmitter (Expression converted, LocalVariable li) : + base (converted, li) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotImplementedException (); + } + + public override void Emit (EmitContext ec) { + // + // Store pointer in pinned location + // + expr.Emit (ec); + vi.EmitAssign (ec); + } + + public override void EmitExit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Conv_U); + vi.EmitAssign (ec); + } + } + + class StringEmitter : Emitter + { + LocalVariable pinned_string; + + public StringEmitter (Expression expr, LocalVariable li, Location loc) + : base (expr, li) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + pinned_string = new LocalVariable (vi.Block, "$pinned", + LocalVariable.Flags.FixedVariable | LocalVariable.Flags.CompilerGenerated | LocalVariable.Flags.Used, + vi.Location); + pinned_string.Type = rc.BuiltinTypes.String; + + eclass = ExprClass.Variable; + type = rc.BuiltinTypes.Int; + return this; + } + + public override void Emit (EmitContext ec) + { + pinned_string.CreateBuilder (ec); + + expr.Emit (ec); + pinned_string.EmitAssign (ec); + + // TODO: Should use Binary::Add + pinned_string.Emit (ec); + ec.Emit (OpCodes.Conv_I); + + var m = ec.Module.PredefinedMembers.RuntimeHelpersOffsetToStringData.Resolve (loc); + if (m == null) + return; + + PropertyExpr pe = new PropertyExpr (m, pinned_string.Location); + //pe.InstanceExpression = pinned_string; + pe.Resolve (new ResolveContext (ec.MemberContext)).Emit (ec); + + ec.Emit (OpCodes.Add); + vi.EmitAssign (ec); + } + + public override void EmitExit (EmitContext ec) + { + ec.Emit (OpCodes.Ldnull); + pinned_string.EmitAssign (ec); + } + } + + + public class VariableDeclaration : BlockVariableDeclaration + { + public VariableDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + if (!Variable.Type.IsPointer && li == Variable) { + bc.Report.Error (209, TypeExpression.Location, + "The type of locals declared in a fixed statement must be a pointer type"); + return null; + } + + // + // The rules for the possible declarators are pretty wise, + // but the production on the grammar is more concise. + // + // So we have to enforce these rules here. + // + // We do not resolve before doing the case 1 test, + // because the grammar is explicit in that the token & + // is present, so we need to test for this particular case. + // + + if (initializer is Cast) { + bc.Report.Error (254, initializer.Location, "The right hand side of a fixed statement assignment may not be a cast expression"); + return null; + } + + initializer = initializer.Resolve (bc); + + if (initializer == null) + return null; + + // + // Case 1: Array + // + if (initializer.Type.IsArray) { + TypeSpec array_type = TypeManager.GetElementType (initializer.Type); + + // + // Provided that array_type is unmanaged, + // + if (!TypeManager.VerifyUnmanaged (bc.Module, array_type, loc)) + return null; + + // + // and T* is implicitly convertible to the + // pointer type given in the fixed statement. + // + ArrayPtr array_ptr = new ArrayPtr (initializer, array_type, loc); + + Expression converted = Convert.ImplicitConversionRequired (bc, array_ptr.Resolve (bc), li.Type, loc); + if (converted == null) + return null; + + // + // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0]) + // + converted = new Conditional (new BooleanExpression (new Binary (Binary.Operator.LogicalOr, + new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc), loc), + new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc), loc), loc)), + new NullLiteral (loc), + converted, loc); + + converted = converted.Resolve (bc); + + return new ExpressionEmitter (converted, li); + } + + // + // Case 2: string + // + if (initializer.Type.BuiltinType == BuiltinTypeSpec.Type.String) { + return new StringEmitter (initializer, li, loc).Resolve (bc); + } + + // Case 3: fixed buffer + if (initializer is FixedBufferPtr) { + return new ExpressionEmitter (initializer, li); + } + + // + // Case 4: & object. + // + bool already_fixed = true; + Unary u = initializer as Unary; + if (u != null && u.Oper == Unary.Operator.AddressOf) { + IVariableReference vr = u.Expr as IVariableReference; + if (vr == null || !vr.IsFixed) { + already_fixed = false; + } + } + + if (already_fixed) { + bc.Report.Error (213, loc, "You cannot use the fixed statement to take the address of an already fixed expression"); + } + + initializer = Convert.ImplicitConversionRequired (bc, initializer, li.Type, loc); + return new ExpressionEmitter (initializer, li); + } + } + + + VariableDeclaration decl; + Statement statement; + bool has_ret; + + public Fixed (VariableDeclaration decl, Statement stmt, Location l) + { + this.decl = decl; + statement = stmt; + loc = l; + } + + #region Properties + + public Statement Statement { + get { + return statement; + } + } + + public BlockVariableDeclaration Variables { + get { + return decl; + } + } + + #endregion + + public override bool Resolve (BlockContext ec) + { + using (ec.Set (ResolveContext.Options.FixedInitializerScope)) { + if (!decl.Resolve (ec)) + return false; + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc); + bool ok = statement.Resolve (ec); + bool flow_unreachable = ec.EndFlowBranching (); + has_ret = flow_unreachable; + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + decl.Variable.CreateBuilder (ec); + decl.Initializer.Emit (ec); + if (decl.Declarators != null) { + foreach (var d in decl.Declarators) { + d.Variable.CreateBuilder (ec); + d.Initializer.Emit (ec); + } + } + + statement.Emit (ec); + + if (has_ret) + return; + + // + // Clear the pinned variable + // + ((Emitter) decl.Initializer).EmitExit (ec); + if (decl.Declarators != null) { + foreach (var d in decl.Declarators) { + ((Emitter)d.Initializer).EmitExit (ec); + } + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Fixed target = (Fixed) t; + + target.decl = (VariableDeclaration) decl.Clone (clonectx); + target.statement = statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Catch : Statement + { + Block block; + LocalVariable li; + FullNamedExpression type_expr; + CompilerAssign assign; + TypeSpec type; + + public Catch (Block block, Location loc) + { + this.block = block; + this.loc = loc; + } + + #region Properties + + public Block Block { + get { + return block; + } + } + + public TypeSpec CatchType { + get { + return type; + } + } + + public bool IsGeneral { + get { + return type_expr == null; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + set { + type_expr = value; + } + } + + public LocalVariable Variable { + get { + return li; + } + set { + li = value; + } + } + + #endregion + + protected override void DoEmit (EmitContext ec) + { + if (IsGeneral) + ec.BeginCatchBlock (ec.BuiltinTypes.Object); + else + ec.BeginCatchBlock (CatchType); + + if (li != null) { + li.CreateBuilder (ec); + + // + // Special case hoisted catch variable, we have to use a temporary variable + // to pass via anonymous storey initialization with the value still on top + // of the stack + // + if (li.HoistedVariant != null) { + LocalTemporary lt = new LocalTemporary (li.Type); + SymbolWriter.OpenCompilerGeneratedBlock (ec); + lt.Store (ec); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + + // switch to assigning from the temporary variable and not from top of the stack + assign.UpdateSource (lt); + } + } else { + SymbolWriter.OpenCompilerGeneratedBlock (ec); + ec.Emit (OpCodes.Pop); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + Block.Emit (ec); + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.CatchScope, true)) { + if (type_expr != null) { + type = type_expr.ResolveAsType (ec); + if (type == null) + return false; + + if (type.BuiltinType != BuiltinTypeSpec.Type.Exception && !TypeSpec.IsBaseClass (type, ec.BuiltinTypes.Exception, false)) { + ec.Report.Error (155, loc, "The type caught or thrown must be derived from System.Exception"); + } else if (li != null) { + li.Type = type; + li.PrepareForFlowAnalysis (ec); + + // source variable is at the top of the stack + Expression source = new EmptyExpression (li.Type); + if (li.Type.IsGenericParameter) + source = new UnboxCast (source, li.Type); + + assign = new CompilerAssign (new LocalVariableReference (li, loc), source, loc); + Block.AddScopeStatement (new StatementExpression (assign)); + } + } + + return Block.Resolve (ec); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Catch target = (Catch) t; + + if (type_expr != null) + target.type_expr = (FullNamedExpression) type_expr.Clone (clonectx); + + target.block = clonectx.LookupBlock (block); + } + } + + public class TryFinally : ExceptionStatement { + Block fini; + + public Statement Stmt { + get { return this.stmt; } + } + + public Block Fini { + get { return this.fini; } + } + + public TryFinally (Statement stmt, Block fini, Location loc) + : base (stmt, loc) + { + this.fini = fini; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (this); + + if (!stmt.Resolve (ec)) + ok = false; + + if (ok) + ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally); + using (ec.With (ResolveContext.Options.FinallyScope, true)) { + if (!fini.Resolve (ec)) + ok = false; + } + + ec.EndFlowBranching (); + + ok &= base.Resolve (ec); + + return ok; + } + + protected override void EmitPreTryBody (EmitContext ec) + { + } + + protected override void EmitTryBody (EmitContext ec) + { + stmt.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + fini.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + TryFinally target = (TryFinally) t; + + target.stmt = (Statement) stmt.Clone (clonectx); + if (fini != null) + target.fini = clonectx.LookupBlock (fini); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class TryCatch : Statement { + public Block Block; + public List Specific; + public Catch General; + bool inside_try_finally, code_follows; + + public TryCatch (Block block, List catch_clauses, Location l, bool inside_try_finally) + { + this.Block = block; + this.Specific = catch_clauses; + this.inside_try_finally = inside_try_finally; + + Catch c = catch_clauses [0]; + if (c.IsGeneral) { + this.General = c; + catch_clauses.RemoveAt (0); + } + + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (this); + + if (!Block.Resolve (ec)) + ok = false; + + TypeSpec[] prev_catches = new TypeSpec [Specific.Count]; + int last_index = 0; + foreach (Catch c in Specific){ + ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch); + + if (!c.Resolve (ec)) { + ok = false; + continue; + } + + TypeSpec resolved_type = c.CatchType; + for (int ii = 0; ii < last_index; ++ii) { + if (resolved_type == prev_catches[ii] || TypeSpec.IsBaseClass (resolved_type, prev_catches[ii], true)) { + ec.Report.Error (160, c.loc, + "A previous catch clause already catches all exceptions of this or a super type `{0}'", + TypeManager.CSharpName (prev_catches [ii])); + ok = false; + } + } + + prev_catches [last_index++] = resolved_type; + } + + if (General != null) { + foreach (Catch c in Specific) { + if (c.CatchType.BuiltinType != BuiltinTypeSpec.Type.Exception) + continue; + + if (!ec.Module.DeclaringAssembly.WrapNonExceptionThrows) + continue; + + if (!ec.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined) + continue; + + ec.Report.Warning (1058, 1, c.loc, + "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'"); + } + + ec.CurrentBranching.CreateSibling (General.Block, FlowBranching.SiblingType.Catch); + + if (!General.Resolve (ec)) + ok = false; + } + + ec.EndFlowBranching (); + + // System.Reflection.Emit automatically emits a 'leave' at the end of a try/catch clause + // So, ensure there's some IL code after this statement + if (!inside_try_finally && !code_follows && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) + ec.NeedReturnLabel (); + + return ok; + } + + public void SomeCodeFollows () + { + code_follows = true; + } + + protected override void DoEmit (EmitContext ec) + { + if (!inside_try_finally) + ec.BeginExceptionBlock (); + + Block.Emit (ec); + + foreach (Catch c in Specific) + c.Emit (ec); + + if (General != null) + General.Emit (ec); + + if (!inside_try_finally) + ec.EndExceptionBlock (); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + TryCatch target = (TryCatch) t; + + target.Block = clonectx.LookupBlock (Block); + if (General != null) + target.General = (Catch) General.Clone (clonectx); + if (Specific != null){ + target.Specific = new List (); + foreach (Catch c in Specific) + target.Specific.Add ((Catch) c.Clone (clonectx)); + } + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Using : ExceptionStatement + { + public class VariableDeclaration : BlockVariableDeclaration + { + Statement dispose_call; + + public VariableDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + public VariableDeclaration (LocalVariable li, Location loc) + : base (li) + { + this.loc = loc; + } + + public VariableDeclaration (Expression expr) + : base (null) + { + loc = expr.Location; + Initializer = expr; + } + + #region Properties + + public bool IsNested { get; private set; } + + #endregion + + public void EmitDispose (EmitContext ec) + { + dispose_call.Emit (ec); + } + + public override bool Resolve (BlockContext bc) + { + if (IsNested) + return true; + + return base.Resolve (bc); + } + + public Expression ResolveExpression (BlockContext bc) + { + var e = Initializer.Resolve (bc); + if (e == null) + return null; + + li = LocalVariable.CreateCompilerGenerated (e.Type, bc.CurrentBlock, loc); + Initializer = ResolveInitializer (bc, Variable, e); + return e; + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + if (li.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + initializer = initializer.Resolve (bc); + if (initializer == null) + return null; + + // Once there is dynamic used defer conversion to runtime even if we know it will never succeed + Arguments args = new Arguments (1); + args.Add (new Argument (initializer)); + initializer = new DynamicConversion (bc.BuiltinTypes.IDisposable, 0, args, initializer.Location).Resolve (bc); + if (initializer == null) + return null; + + var var = LocalVariable.CreateCompilerGenerated (initializer.Type, bc.CurrentBlock, loc); + dispose_call = CreateDisposeCall (bc, var); + dispose_call.Resolve (bc); + + return base.ResolveInitializer (bc, li, new SimpleAssign (var.CreateReferenceExpression (bc, loc), initializer, loc)); + } + + if (li == Variable) { + CheckIDiposableConversion (bc, li, initializer); + dispose_call = CreateDisposeCall (bc, li); + dispose_call.Resolve (bc); + } + + return base.ResolveInitializer (bc, li, initializer); + } + + protected virtual void CheckIDiposableConversion (BlockContext bc, LocalVariable li, Expression initializer) + { + var type = li.Type; + + if (type.BuiltinType != BuiltinTypeSpec.Type.IDisposable && !type.ImplementsInterface (bc.BuiltinTypes.IDisposable, false)) { + if (type.IsNullableType) { + // it's handled in CreateDisposeCall + return; + } + + bc.Report.SymbolRelatedToPreviousError (type); + var loc = type_expr == null ? initializer.Location : type_expr.Location; + bc.Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'", + type.GetSignatureForError ()); + + return; + } + } + + protected virtual Statement CreateDisposeCall (BlockContext bc, LocalVariable lv) + { + var lvr = lv.CreateReferenceExpression (bc, lv.Location); + var type = lv.Type; + var loc = lv.Location; + + var idt = bc.BuiltinTypes.IDisposable; + var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc); + + var dispose_mg = MethodGroupExpr.CreatePredefined (m, idt, loc); + dispose_mg.InstanceExpression = type.IsNullableType ? + new Cast (new TypeExpression (idt, loc), lvr, loc).Resolve (bc) : + lvr; + + Statement dispose = new StatementExpression (new Invocation (dispose_mg, null)); + + // Add conditional call when disposing possible null variable + if (!type.IsStruct || type.IsNullableType) + dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc), loc), dispose, loc); + + return dispose; + } + + public Statement RewriteForDeclarators (BlockContext bc, Statement stmt) + { + for (int i = declarators.Count - 1; i >= 0; --i) { + var d = declarators [i]; + var vd = new VariableDeclaration (d.Variable, type_expr.Location); + vd.Initializer = d.Initializer; + vd.IsNested = true; + vd.dispose_call = CreateDisposeCall (bc, d.Variable); + vd.dispose_call.Resolve (bc); + + stmt = new Using (vd, stmt, d.Variable.Location); + } + + declarators = null; + return stmt; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + VariableDeclaration decl; + + public Using (VariableDeclaration decl, Statement stmt, Location loc) + : base (stmt, loc) + { + this.decl = decl; + } + + public Using (Expression expr, Statement stmt, Location loc) + : base (stmt, loc) + { + this.decl = new VariableDeclaration (expr); + } + + #region Properties + + public Expression Expression { + get { + return decl.Variable == null ? decl.Initializer : null; + } + } + + public BlockVariableDeclaration Variables { + get { + return decl; + } + } + + #endregion + + protected override void EmitPreTryBody (EmitContext ec) + { + decl.Emit (ec); + } + + protected override void EmitTryBody (EmitContext ec) + { + stmt.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + decl.EmitDispose (ec); + } + + public override bool Resolve (BlockContext ec) + { + VariableReference vr; + bool vr_locked = false; + + using (ec.Set (ResolveContext.Options.UsingInitializerScope)) { + if (decl.Variable == null) { + vr = decl.ResolveExpression (ec) as VariableReference; + if (vr != null) { + vr_locked = vr.IsLockedByStatement; + vr.IsLockedByStatement = true; + } + } else { + if (!decl.Resolve (ec)) + return false; + + if (decl.Declarators != null) { + stmt = decl.RewriteForDeclarators (ec, stmt); + } + + vr = null; + } + } + + ec.StartFlowBranching (this); + + stmt.Resolve (ec); + + ec.EndFlowBranching (); + + if (vr != null) + vr.IsLockedByStatement = vr_locked; + + base.Resolve (ec); + + return true; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Using target = (Using) t; + + target.decl = (VariableDeclaration) decl.Clone (clonectx); + target.stmt = stmt.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implementation of the foreach C# statement + /// + public class Foreach : Statement { + + sealed class ArrayForeach : Statement + { + readonly Foreach for_each; + readonly Statement statement; + + Expression conv; + TemporaryVariableReference[] lengths; + Expression [] length_exprs; + StatementExpression[] counter; + TemporaryVariableReference[] variables; + + TemporaryVariableReference copy; + Expression access; + LocalVariableReference variable; + + public ArrayForeach (Foreach @foreach, int rank) + { + for_each = @foreach; + statement = for_each.statement; + loc = @foreach.loc; + variable = new LocalVariableReference (for_each.variable, loc); + + counter = new StatementExpression[rank]; + variables = new TemporaryVariableReference[rank]; + length_exprs = new Expression [rank]; + + // + // Only use temporary length variables when dealing with + // multi-dimensional arrays + // + if (rank > 1) + lengths = new TemporaryVariableReference [rank]; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + public override bool Resolve (BlockContext ec) + { + Block variables_block = variable.local_info.Block; + copy = TemporaryVariableReference.Create (for_each.expr.Type, variables_block, loc); + copy.Resolve (ec); + + int rank = length_exprs.Length; + Arguments list = new Arguments (rank); + for (int i = 0; i < rank; i++) { + var v = TemporaryVariableReference.Create (ec.BuiltinTypes.Int, variables_block, loc); + variables[i] = v; + counter[i] = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, v, loc)); + counter[i].Resolve (ec); + + if (rank == 1) { + length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec); + } else { + lengths[i] = TemporaryVariableReference.Create (ec.BuiltinTypes.Int, variables_block, loc); + lengths[i].Resolve (ec); + + Arguments args = new Arguments (1); + args.Add (new Argument (new IntConstant (ec.BuiltinTypes, i, loc))); + length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec); + } + + list.Add (new Argument (v)); + } + + access = new ElementAccess (copy, list, loc).Resolve (ec); + if (access == null) + return false; + + TypeSpec var_type; + if (for_each.type is VarExpr) { + // Infer implicitly typed local variable from foreach array type + var_type = access.Type; + } else { + var_type = for_each.type.ResolveAsType (ec); + } + + if (var_type == null) + return false; + + conv = Convert.ExplicitConversion (ec, access, var_type, loc); + if (conv == null) + return false; + + bool ok = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + ec.CurrentBranching.CreateSibling (); + + variable.local_info.Type = conv.Type; + variable.Resolve (ec); + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + copy.EmitAssign (ec, for_each.expr); + + int rank = length_exprs.Length; + Label[] test = new Label [rank]; + Label[] loop = new Label [rank]; + + for (int i = 0; i < rank; i++) { + test [i] = ec.DefineLabel (); + loop [i] = ec.DefineLabel (); + + if (lengths != null) + lengths [i].EmitAssign (ec, length_exprs [i]); + } + + IntConstant zero = new IntConstant (ec.BuiltinTypes, 0, loc); + for (int i = 0; i < rank; i++) { + variables [i].EmitAssign (ec, zero); + + ec.Emit (OpCodes.Br, test [i]); + ec.MarkLabel (loop [i]); + } + + variable.local_info.CreateBuilder (ec); + variable.EmitAssign (ec, conv, false, false); + + statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + + for (int i = rank - 1; i >= 0; i--){ + counter [i].Emit (ec); + + ec.MarkLabel (test [i]); + variables [i].Emit (ec); + + if (lengths != null) + lengths [i].Emit (ec); + else + length_exprs [i].Emit (ec); + + ec.Emit (OpCodes.Blt, loop [i]); + } + + ec.MarkLabel (ec.LoopEnd); + } + } + + sealed class CollectionForeach : Statement, OverloadResolver.IErrorHandler + { + class Body : Statement + { + TypeSpec type; + LocalVariableReference variable; + Expression current, conv; + Statement statement; + + public Body (TypeSpec type, LocalVariable variable, + Expression current, Statement statement, + Location loc) + { + this.type = type; + this.variable = new LocalVariableReference (variable, loc); + this.current = current; + this.statement = statement; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + public override bool Resolve (BlockContext ec) + { + current = current.Resolve (ec); + if (current == null) + return false; + + conv = Convert.ExplicitConversion (ec, current, type, loc); + if (conv == null) + return false; + + variable.local_info.Type = conv.Type; + variable.Resolve (ec); + + if (!statement.Resolve (ec)) + return false; + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + variable.local_info.CreateBuilder (ec); + variable.EmitAssign (ec, conv, false, false); + + statement.Emit (ec); + } + } + + class RuntimeDispose : Using.VariableDeclaration + { + public RuntimeDispose (LocalVariable lv, Location loc) + : base (lv, loc) + { + } + + protected override void CheckIDiposableConversion (BlockContext bc, LocalVariable li, Expression initializer) + { + // Defered to runtime check + } + + protected override Statement CreateDisposeCall (BlockContext bc, LocalVariable lv) + { + var idt = bc.BuiltinTypes.IDisposable; + + // + // Fabricates code like + // + // if ((temp = vr as IDisposable) != null) temp.Dispose (); + // + + var dispose_variable = LocalVariable.CreateCompilerGenerated (idt, bc.CurrentBlock, loc); + + var idisaposable_test = new Binary (Binary.Operator.Inequality, new CompilerAssign ( + dispose_variable.CreateReferenceExpression (bc, loc), + new As (lv.CreateReferenceExpression (bc, loc), new TypeExpression (dispose_variable.Type, loc), loc), + loc), new NullLiteral (loc), loc); + + var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc); + + var dispose_mg = MethodGroupExpr.CreatePredefined (m, idt, loc); + dispose_mg.InstanceExpression = dispose_variable.CreateReferenceExpression (bc, loc); + + Statement dispose = new StatementExpression (new Invocation (dispose_mg, null)); + return new If (idisaposable_test, dispose, loc); + } + } + + LocalVariable variable; + Expression expr; + Statement statement; + Expression var_type; + ExpressionStatement init; + TemporaryVariableReference enumerator_variable; + bool ambiguous_getenumerator_name; + + public CollectionForeach (Expression var_type, LocalVariable var, Expression expr, Statement stmt, Location l) + { + this.var_type = var_type; + this.variable = var; + this.expr = expr; + statement = stmt; + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + void Error_WrongEnumerator (ResolveContext rc, MethodSpec enumerator) + { + rc.Report.SymbolRelatedToPreviousError (enumerator); + rc.Report.Error (202, loc, + "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property", + enumerator.ReturnType.GetSignatureForError (), enumerator.GetSignatureForError ()); + } + + MethodGroupExpr ResolveGetEnumerator (ResolveContext rc) + { + // + // Option 1: Try to match by name GetEnumerator first + // + var mexpr = Expression.MemberLookup (rc, false, expr.Type, + "GetEnumerator", 0, Expression.MemberLookupRestrictions.ExactArity, loc); // TODO: What if CS0229 ? + + var mg = mexpr as MethodGroupExpr; + if (mg != null) { + mg.InstanceExpression = expr; + Arguments args = new Arguments (0); + mg = mg.OverloadResolve (rc, ref args, this, OverloadResolver.Restrictions.None); + + // For ambiguous GetEnumerator name warning CS0278 was reported, but Option 2 could still apply + if (ambiguous_getenumerator_name) + mg = null; + + if (mg != null && args.Count == 0 && !mg.BestCandidate.IsStatic && mg.BestCandidate.IsPublic) { + return mg; + } + } + + // + // Option 2: Try to match using IEnumerable interfaces with preference of generic version + // + var t = expr.Type; + PredefinedMember iface_candidate = null; + var ptypes = rc.Module.PredefinedTypes; + var gen_ienumerable = ptypes.IEnumerableGeneric; + if (!gen_ienumerable.Define ()) + gen_ienumerable = null; + + do { + var ifaces = t.Interfaces; + if (ifaces != null) { + foreach (var iface in ifaces) { + if (gen_ienumerable != null && iface.MemberDefinition == gen_ienumerable.TypeSpec.MemberDefinition) { + if (iface_candidate != null && iface_candidate != rc.Module.PredefinedMembers.IEnumerableGetEnumerator) { + rc.Report.SymbolRelatedToPreviousError (expr.Type); + rc.Report.Error (1640, loc, + "foreach statement cannot operate on variables of type `{0}' because it contains multiple implementation of `{1}'. Try casting to a specific implementation", + expr.Type.GetSignatureForError (), gen_ienumerable.TypeSpec.GetSignatureForError ()); + + return null; + } + + // TODO: Cache this somehow + iface_candidate = new PredefinedMember (rc.Module, iface, + MemberFilter.Method ("GetEnumerator", 0, ParametersCompiled.EmptyReadOnlyParameters, null)); + + continue; + } + + if (iface.BuiltinType == BuiltinTypeSpec.Type.IEnumerable && iface_candidate == null) { + iface_candidate = rc.Module.PredefinedMembers.IEnumerableGetEnumerator; + } + } + } + + if (t.IsGenericParameter) + t = t.BaseType; + else + t = null; + + } while (t != null); + + if (iface_candidate == null) { + rc.Report.Error (1579, loc, + "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `{1}' or is inaccessible", + expr.Type.GetSignatureForError (), "GetEnumerator"); + + return null; + } + + var method = iface_candidate.Resolve (loc); + if (method == null) + return null; + + mg = MethodGroupExpr.CreatePredefined (method, expr.Type, loc); + mg.InstanceExpression = expr; + return mg; + } + + MethodGroupExpr ResolveMoveNext (ResolveContext rc, MethodSpec enumerator) + { + var ms = MemberCache.FindMember (enumerator.ReturnType, + MemberFilter.Method ("MoveNext", 0, ParametersCompiled.EmptyReadOnlyParameters, rc.BuiltinTypes.Bool), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (ms == null || !ms.IsPublic) { + Error_WrongEnumerator (rc, enumerator); + return null; + } + + return MethodGroupExpr.CreatePredefined (ms, enumerator.ReturnType, loc); + } + + PropertySpec ResolveCurrent (ResolveContext rc, MethodSpec enumerator) + { + var ps = MemberCache.FindMember (enumerator.ReturnType, + MemberFilter.Property ("Current", null), + BindingRestriction.InstanceOnly) as PropertySpec; + + if (ps == null || !ps.IsPublic) { + Error_WrongEnumerator (rc, enumerator); + return null; + } + + return ps; + } + + public override bool Resolve (BlockContext ec) + { + bool is_dynamic = expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + + if (is_dynamic) { + expr = Convert.ImplicitConversionRequired (ec, expr, ec.BuiltinTypes.IEnumerable, loc); + } else if (expr.Type.IsNullableType) { + expr = new Nullable.UnwrapCall (expr).Resolve (ec); + } + + var get_enumerator_mg = ResolveGetEnumerator (ec); + if (get_enumerator_mg == null) { + return false; + } + + var get_enumerator = get_enumerator_mg.BestCandidate; + enumerator_variable = TemporaryVariableReference.Create (get_enumerator.ReturnType, variable.Block, loc); + enumerator_variable.Resolve (ec); + + // Prepare bool MoveNext () + var move_next_mg = ResolveMoveNext (ec, get_enumerator); + if (move_next_mg == null) { + return false; + } + + move_next_mg.InstanceExpression = enumerator_variable; + + // Prepare ~T~ Current { get; } + var current_prop = ResolveCurrent (ec, get_enumerator); + if (current_prop == null) { + return false; + } + + var current_pe = new PropertyExpr (current_prop, loc) { InstanceExpression = enumerator_variable }.Resolve (ec); + if (current_pe == null) + return false; + + VarExpr ve = var_type as VarExpr; + + if (ve != null) { + if (is_dynamic) { + // Source type is dynamic, set element type to dynamic too + variable.Type = ec.BuiltinTypes.Dynamic; + } else { + // Infer implicitly typed local variable from foreach enumerable type + variable.Type = current_pe.Type; + } + } else { + if (is_dynamic) { + // Explicit cast of dynamic collection elements has to be done at runtime + current_pe = EmptyCast.Create (current_pe, ec.BuiltinTypes.Dynamic); + } + + variable.Type = var_type.ResolveAsType (ec); + } + + if (variable.Type == null) + return false; + + var init = new Invocation (get_enumerator_mg, null); + + statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)), + new Body (variable.Type, variable, current_pe, statement, loc), loc); + + var enum_type = enumerator_variable.Type; + + // + // Add Dispose method call when enumerator can be IDisposable + // + if (!enum_type.ImplementsInterface (ec.BuiltinTypes.IDisposable, false)) { + if (!enum_type.IsSealed && !TypeSpec.IsValueType (enum_type)) { + // + // Runtime Dispose check + // + var vd = new RuntimeDispose (enumerator_variable.LocalInfo, loc); + vd.Initializer = init; + statement = new Using (vd, statement, loc); + } else { + // + // No Dispose call needed + // + this.init = new SimpleAssign (enumerator_variable, init); + this.init.Resolve (ec); + } + } else { + // + // Static Dispose check + // + var vd = new Using.VariableDeclaration (enumerator_variable.LocalInfo, loc); + vd.Initializer = init; + statement = new Using (vd, statement, loc); + } + + return statement.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + enumerator_variable.LocalInfo.CreateBuilder (ec); + + if (init != null) + init.EmitStatement (ec); + + statement.Emit (ec); + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + ec.Report.SymbolRelatedToPreviousError (best); + ec.Report.Warning (278, 2, loc, + "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'", + expr.Type.GetSignatureForError (), "enumerable", + best.GetSignatureForError (), ambiguous.GetSignatureForError ()); + + ambiguous_getenumerator_name = true; + return true; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + return false; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + Expression type; + LocalVariable variable; + Expression expr; + Statement statement; + + public Expression TypeExpr { + get { return this.type; } + } + + public LocalVariable Variable { + get { return this.variable; } + } + + public Foreach (Expression type, LocalVariable var, Expression expr, Statement stmt, Location l) + { + this.type = type; + this.variable = var; + this.expr = expr; + statement = stmt; + loc = l; + } + + public Statement Statement { + get { return statement; } + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return false; + + if (expr.IsNull) { + ec.Report.Error (186, loc, "Use of null is not valid in this context"); + return false; + } + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.String) { + statement = new ArrayForeach (this, 1); + } else if (expr.Type is ArrayContainer) { + statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank); + } else { + if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) { + ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'", + expr.ExprClassName); + return false; + } + + statement = new CollectionForeach (type, variable, expr, statement, loc); + } + + return statement.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd; + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + statement.Emit (ec); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Foreach target = (Foreach) t; + + target.type = type.Clone (clonectx); + target.expr = expr.Clone (clonectx); + target.statement = statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs new file mode 100644 index 0000000000..c10d13f893 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs @@ -0,0 +1,317 @@ +// +// support.cs: Support routines to work around the fact that System.Reflection.Emit +// can not introspect types that are being constructed +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2009 Novell, Inc +// + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace Mono.CSharp { + + sealed class ReferenceEquality : IEqualityComparer where T : class + { + public static readonly IEqualityComparer Default = new ReferenceEquality (); + + private ReferenceEquality () + { + } + + public bool Equals (T x, T y) + { + return ReferenceEquals (x, y); + } + + public int GetHashCode (T obj) + { + return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj); + } + } + + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + + public override int GetHashCode () + { + return ((object)Item1 ?? 0) .GetHashCode () ^ ((object)Item2 ?? 0).GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (Tuple other) + { + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2); + } + + #endregion + } + + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2, T3 item3) + { + Item1 = item1; + Item2 = item2; + Item3 = item3; + } + + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + public T3 Item3 { get; private set; } + + public override int GetHashCode () + { + return Item1.GetHashCode () ^ Item2.GetHashCode () ^ Item3.GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (Tuple other) + { + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2) && + EqualityComparer.Default.Equals (Item3, other.Item3); + } + + #endregion + } + + static class Tuple + { + public static Tuple Create (T1 item1, T2 item2) + { + return new Tuple (item1, item2); + } + + public static Tuple Create (T1 item1, T2 item2, T3 item3) + { + return new Tuple (item1, item2, item3); + } + } + + static class ArrayComparer + { + public static bool IsEqual (T[] array1, T[] array2) + { + if (array1 == null || array2 == null) + return array1 == array2; + + var eq = EqualityComparer.Default; + + for (int i = 0; i < array1.Length; ++i) { + if (!eq.Equals (array1[i], array2[i])) { + return false; + } + } + + return true; + } + } + + /// + /// This is an arbitrarily seekable StreamReader wrapper. + /// + /// It uses a self-tuning buffer to cache the seekable data, + /// but if the seek is too far, it may read the underly + /// stream all over from the beginning. + /// + public class SeekableStreamReader : IDisposable + { + StreamReader reader; + Stream stream; + + static char[] buffer; + int read_ahead_length; // the length of read buffer + int buffer_start; // in chars + int char_count; // count of filled characters in buffer[] + int pos; // index into buffer[] + + public SeekableStreamReader (Stream stream, Encoding encoding) + { + this.stream = stream; + + const int default_read_ahead = 2048; + InitializeStream (default_read_ahead); + reader = new StreamReader (stream, encoding, true); + } + + public void Dispose () + { + // Needed to release stream reader buffers + reader.Dispose (); + } + + void InitializeStream (int read_length_inc) + { + read_ahead_length += read_length_inc; + + int required_buffer_size = read_ahead_length * 2; + + if (buffer == null || buffer.Length < required_buffer_size) + buffer = new char [required_buffer_size]; + + stream.Position = 0; + buffer_start = char_count = pos = 0; + } + + /// + /// This value corresponds to the current position in a stream of characters. + /// The StreamReader hides its manipulation of the underlying byte stream and all + /// character set/decoding issues. Thus, we cannot use this position to guess at + /// the corresponding position in the underlying byte stream even though there is + /// a correlation between them. + /// + public int Position { + get { + return buffer_start + pos; + } + + set { + // + // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it + // This should never happen until we are parsing some weird source code + // + if (value < buffer_start) { + InitializeStream (read_ahead_length); + + // + // Discard buffer data after underlying stream changed position + // Cannot use handy reader.DiscardBufferedData () because it for + // some strange reason resets encoding as well + // + reader = new StreamReader (stream, reader.CurrentEncoding, true); + } + + while (value > buffer_start + char_count) { + pos = char_count; + if (!ReadBuffer ()) + throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value)); + } + + pos = value - buffer_start; + } + } + + bool ReadBuffer () + { + int slack = buffer.Length - char_count; + + // + // read_ahead_length is only half of the buffer to deal with + // reads ahead and moves back without re-reading whole buffer + // + if (slack <= read_ahead_length) { + // + // shift the buffer to make room for read_ahead_length number of characters + // + int shift = read_ahead_length - slack; + Array.Copy (buffer, shift, buffer, 0, char_count - shift); + + // Update all counters + pos -= shift; + char_count -= shift; + buffer_start += shift; + slack += shift; + } + + char_count += reader.Read (buffer, char_count, slack); + + return pos < char_count; + } + + public char[] ReadChars (int fromPosition, int toPosition) + { + char[] chars = new char[toPosition - fromPosition]; + if (buffer_start <= fromPosition && toPosition < buffer_start + buffer.Length) { + Array.Copy (buffer, fromPosition - buffer_start, chars, 0, chars.Length); + } else { + throw new NotImplementedException (); + } + + return chars; + } + + public int Peek () + { + if ((pos >= char_count) && !ReadBuffer ()) + return -1; + + return buffer [pos]; + } + + public int Read () + { + if ((pos >= char_count) && !ReadBuffer ()) + return -1; + + return buffer [pos++]; + } + } + + public class UnixUtils { + [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")] + extern static int _isatty (int fd); + + public static bool isatty (int fd) + { + try { + return _isatty (fd) == 1; + } catch { + return false; + } + } + } + + /// + /// An exception used to terminate the compiler resolution phase and provide completions + /// + /// + /// This is thrown when we want to return the completions or + /// terminate the completion process by AST nodes used in + /// the completion process. + /// + public class CompletionResult : Exception { + string [] result; + string base_text; + + public CompletionResult (string base_text, string [] res) + { + if (base_text == null) + throw new ArgumentNullException ("base_text"); + this.base_text = base_text; + + result = res; + Array.Sort (result); + } + + public string [] Result { + get { + return result; + } + } + + public string BaseText { + get { + return base_text; + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs new file mode 100644 index 0000000000..ce19cfc492 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs @@ -0,0 +1,245 @@ +// +// symbolwriter.cs: The debug symbol writer +// +// Authors: Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2010 Novell, Inc +// + +using System; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +using Mono.CompilerServices.SymbolWriter; + +namespace Mono.CSharp +{ + static class SymbolWriter + { +#if !NET_4_0 && !STATIC + delegate int GetILOffsetFunc (ILGenerator ig); + static GetILOffsetFunc get_il_offset_func; + + delegate Guid GetGuidFunc (ModuleBuilder mb); + static GetGuidFunc get_guid_func; + + static void Initialize () + { + var mi = typeof (ILGenerator).GetMethod ( + "Mono_GetCurrentOffset", + BindingFlags.Static | BindingFlags.NonPublic); + if (mi == null) + throw new MissingMethodException ("Mono_GetCurrentOffset"); + + get_il_offset_func = (GetILOffsetFunc) System.Delegate.CreateDelegate ( + typeof (GetILOffsetFunc), mi); + + mi = typeof (ModuleBuilder).GetMethod ( + "Mono_GetGuid", + BindingFlags.Static | BindingFlags.NonPublic); + if (mi == null) + throw new MissingMethodException ("Mono_GetGuid"); + + get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate ( + typeof (GetGuidFunc), mi); + } +#endif + + static int GetILOffset (ILGenerator ig) + { +#if NET_4_0 || STATIC + return ig.ILOffset; +#else + if (get_il_offset_func == null) + Initialize (); + + return get_il_offset_func (ig); +#endif + } + + public static Guid GetGuid (ModuleBuilder module) + { +#if NET_4_0 || STATIC + return module.ModuleVersionId; +#else + if (get_guid_func == null) + Initialize (); + + return get_guid_func (module); +#endif + } + + public static bool HasSymbolWriter { + get { return symwriter != null; } + } + + public static MonoSymbolWriter symwriter; + + public static void DefineLocalVariable (string name, LocalBuilder builder) + { + if (symwriter != null) { + symwriter.DefineLocalVariable (builder.LocalIndex, name); + } + } + + public static SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, + IMethodDef method) + { + if (symwriter != null) + return symwriter.OpenMethod (file, ns_id, method); + else + return null; + } + + public static void CloseMethod () + { + if (symwriter != null) + symwriter.CloseMethod (); + } + + public static int OpenScope (ILGenerator ig) + { + if (symwriter != null) { + int offset = GetILOffset (ig); + return symwriter.OpenScope (offset); + } else { + return -1; + } + } + + public static void CloseScope (ILGenerator ig) + { + if (symwriter != null) { + int offset = GetILOffset (ig); + symwriter.CloseScope (offset); + } + } + + public static int DefineNamespace (string name, CompileUnitEntry source, + string[] using_clauses, int parent) + { + if (symwriter != null) + return symwriter.DefineNamespace (name, source, using_clauses, parent); + else + return -1; + } + + public static void DefineAnonymousScope (int id) + { + if (symwriter != null) + symwriter.DefineAnonymousScope (id); + } + + public static void DefineScopeVariable (int scope, LocalBuilder builder) + { + if (symwriter != null) { + symwriter.DefineScopeVariable (scope, builder.LocalIndex); + } + } + + public static void DefineScopeVariable (int scope) + { + if (symwriter != null) + symwriter.DefineScopeVariable (scope, -1); + } + + public static void DefineCapturedLocal (int scope_id, string name, + string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedLocal (scope_id, name, captured_name); + } + + public static void DefineCapturedParameter (int scope_id, string name, + string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedParameter (scope_id, name, captured_name); + } + + public static void DefineCapturedThis (int scope_id, string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedThis (scope_id, captured_name); + } + + public static void DefineCapturedScope (int scope_id, int id, string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedScope (scope_id, id, captured_name); + } + + public static void OpenCompilerGeneratedBlock (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.OpenCompilerGeneratedBlock (offset); + } + } + + public static void CloseCompilerGeneratedBlock (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.CloseCompilerGeneratedBlock (offset); + } + } + + public static void StartIteratorBody (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.StartIteratorBody (offset); + } + } + + public static void EndIteratorBody (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.EndIteratorBody (offset); + } + } + + public static void StartIteratorDispatcher (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.StartIteratorDispatcher (offset); + } + } + + public static void EndIteratorDispatcher (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.EndIteratorDispatcher (offset); + } + } + + public static void MarkSequencePoint (ILGenerator ig, Location loc) + { + if (symwriter != null) { + SourceFileEntry file = loc.SourceFile.SourceFileEntry; + int offset = GetILOffset (ig); + symwriter.MarkSequencePoint ( + offset, file, loc.Row, loc.Column, loc.Hidden); + } + } + + public static void Reset () + { + symwriter = null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs new file mode 100644 index 0000000000..2e2d17064d --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs @@ -0,0 +1,980 @@ +// +// typemanager.cs: C# type manager +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Globalization; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace Mono.CSharp +{ + // + // All compiler built-in types (they have to exist otherwise the compiler will not work) + // + public class BuiltinTypes + { + public readonly BuiltinTypeSpec Object; + public readonly BuiltinTypeSpec ValueType; + public readonly BuiltinTypeSpec Attribute; + + public readonly BuiltinTypeSpec Int; + public readonly BuiltinTypeSpec UInt; + public readonly BuiltinTypeSpec Long; + public readonly BuiltinTypeSpec ULong; + public readonly BuiltinTypeSpec Float; + public readonly BuiltinTypeSpec Double; + public readonly BuiltinTypeSpec Char; + public readonly BuiltinTypeSpec Short; + public readonly BuiltinTypeSpec Decimal; + public readonly BuiltinTypeSpec Bool; + public readonly BuiltinTypeSpec SByte; + public readonly BuiltinTypeSpec Byte; + public readonly BuiltinTypeSpec UShort; + public readonly BuiltinTypeSpec String; + + public readonly BuiltinTypeSpec Enum; + public readonly BuiltinTypeSpec Delegate; + public readonly BuiltinTypeSpec MulticastDelegate; + public readonly BuiltinTypeSpec Void; + public readonly BuiltinTypeSpec Array; + public readonly BuiltinTypeSpec Type; + public readonly BuiltinTypeSpec IEnumerator; + public readonly BuiltinTypeSpec IEnumerable; + public readonly BuiltinTypeSpec IDisposable; + public readonly BuiltinTypeSpec IntPtr; + public readonly BuiltinTypeSpec UIntPtr; + public readonly BuiltinTypeSpec RuntimeFieldHandle; + public readonly BuiltinTypeSpec RuntimeTypeHandle; + public readonly BuiltinTypeSpec Exception; + + // + // These are internal buil-in types which depend on other + // build-in type (mostly object) + // + public readonly BuiltinTypeSpec Dynamic; + + // Predefined operators tables + public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard; + public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality; + public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe; + public readonly TypeSpec[][] OperatorsUnary; + public readonly TypeSpec[] OperatorsUnaryMutator; + + public readonly TypeSpec[] BinaryPromotionsTypes; + public readonly TypeSpec[] SwitchUserTypes; + + readonly BuiltinTypeSpec[] types; + + public BuiltinTypes () + { + Object = new BuiltinTypeSpec (MemberKind.Class, "System", "Object", BuiltinTypeSpec.Type.Object); + ValueType = new BuiltinTypeSpec (MemberKind.Class, "System", "ValueType", BuiltinTypeSpec.Type.ValueType); + Attribute = new BuiltinTypeSpec (MemberKind.Class, "System", "Attribute", BuiltinTypeSpec.Type.Attribute); + + Int = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int32", BuiltinTypeSpec.Type.Int); + Long = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int64", BuiltinTypeSpec.Type.Long); + UInt = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt32", BuiltinTypeSpec.Type.UInt); + ULong = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt64", BuiltinTypeSpec.Type.ULong); + Byte = new BuiltinTypeSpec (MemberKind.Struct, "System", "Byte", BuiltinTypeSpec.Type.Byte); + SByte = new BuiltinTypeSpec (MemberKind.Struct, "System", "SByte", BuiltinTypeSpec.Type.SByte); + Short = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int16", BuiltinTypeSpec.Type.Short); + UShort = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt16", BuiltinTypeSpec.Type.UShort); + + IEnumerator = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuiltinTypeSpec.Type.IEnumerator); + IEnumerable = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuiltinTypeSpec.Type.IEnumerable); + IDisposable = new BuiltinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuiltinTypeSpec.Type.IDisposable); + + Char = new BuiltinTypeSpec (MemberKind.Struct, "System", "Char", BuiltinTypeSpec.Type.Char); + String = new BuiltinTypeSpec (MemberKind.Class, "System", "String", BuiltinTypeSpec.Type.String); + Float = new BuiltinTypeSpec (MemberKind.Struct, "System", "Single", BuiltinTypeSpec.Type.Float); + Double = new BuiltinTypeSpec (MemberKind.Struct, "System", "Double", BuiltinTypeSpec.Type.Double); + Decimal = new BuiltinTypeSpec (MemberKind.Struct, "System", "Decimal", BuiltinTypeSpec.Type.Decimal); + Bool = new BuiltinTypeSpec (MemberKind.Struct, "System", "Boolean", BuiltinTypeSpec.Type.Bool); + IntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuiltinTypeSpec.Type.IntPtr); + UIntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuiltinTypeSpec.Type.UIntPtr); + + MulticastDelegate = new BuiltinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuiltinTypeSpec.Type.MulticastDelegate); + Delegate = new BuiltinTypeSpec (MemberKind.Class, "System", "Delegate", BuiltinTypeSpec.Type.Delegate); + Enum = new BuiltinTypeSpec (MemberKind.Class, "System", "Enum", BuiltinTypeSpec.Type.Enum); + Array = new BuiltinTypeSpec (MemberKind.Class, "System", "Array", BuiltinTypeSpec.Type.Array); + Void = new BuiltinTypeSpec (MemberKind.Void, "System", "Void", BuiltinTypeSpec.Type.Other); + Type = new BuiltinTypeSpec (MemberKind.Class, "System", "Type", BuiltinTypeSpec.Type.Type); + Exception = new BuiltinTypeSpec (MemberKind.Class, "System", "Exception", BuiltinTypeSpec.Type.Exception); + RuntimeFieldHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuiltinTypeSpec.Type.Other); + RuntimeTypeHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuiltinTypeSpec.Type.Other); + + // TODO: Maybe I should promote it to different kind for faster compares + Dynamic = new BuiltinTypeSpec ("dynamic", BuiltinTypeSpec.Type.Dynamic); + + OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this); + OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this); + OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this); + OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this); + OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this); + + BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this); + SwitchUserTypes = Switch.CreateSwitchUserTypes (this); + + types = new BuiltinTypeSpec[] { + Object, ValueType, Attribute, + Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String, + Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable, + IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception }; + } + + public BuiltinTypeSpec[] AllTypes { + get { + return types; + } + } + + public bool CheckDefinitions (ModuleContainer module) + { + var ctx = module.Compiler; + foreach (var p in types) { + var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity); + if (found == null || found == p) + continue; + + var tc = found.MemberDefinition as TypeContainer; + if (tc != null) { + var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false); + ns.SetBuiltinType (p); + + tc.SetPredefinedSpec (p); + p.SetDefinition (found); + } + } + + if (ctx.Report.Errors != 0) + return false; + + // Set internal build-in types + Dynamic.SetDefinition (Object); + + return true; + } + } + + // + // Compiler predefined types. Usually used for compiler generated + // code or for comparison against well known framework type. They + // may not exist as they are optional + // + class PredefinedTypes + { + public readonly PredefinedType ArgIterator; + public readonly PredefinedType TypedReference; + public readonly PredefinedType MarshalByRefObject; + public readonly PredefinedType RuntimeHelpers; + public readonly PredefinedType IAsyncResult; + public readonly PredefinedType AsyncCallback; + public readonly PredefinedType RuntimeArgumentHandle; + public readonly PredefinedType CharSet; + public readonly PredefinedType IsVolatile; + public readonly PredefinedType IEnumeratorGeneric; + public readonly PredefinedType IListGeneric; + public readonly PredefinedType ICollectionGeneric; + public readonly PredefinedType IEnumerableGeneric; + public readonly PredefinedType Nullable; + public readonly PredefinedType Activator; + public readonly PredefinedType Interlocked; + public readonly PredefinedType Monitor; + public readonly PredefinedType NotSupportedException; + public readonly PredefinedType RuntimeFieldHandle; + public readonly PredefinedType RuntimeMethodHandle; + public readonly PredefinedType SecurityAction; + public readonly PredefinedType Dictionary; + public readonly PredefinedType Hashtable; + + // + // C# 3.0 + // + public readonly PredefinedType Expression; + public readonly PredefinedType ExpressionGeneric; + public readonly PredefinedType ParameterExpression; + public readonly PredefinedType FieldInfo; + public readonly PredefinedType MethodBase; + public readonly PredefinedType MethodInfo; + public readonly PredefinedType ConstructorInfo; + + // + // C# 4.0 + // + public readonly PredefinedType Binder; + public readonly PredefinedType CallSite; + public readonly PredefinedType CallSiteGeneric; + public readonly PredefinedType BinderFlags; + + // + // C# 5.0 + // + public readonly PredefinedType AsyncVoidMethodBuilder; + public readonly PredefinedType AsyncTaskMethodBuilder; + public readonly PredefinedType AsyncTaskMethodBuilderGeneric; + public readonly PredefinedType Action; + public readonly PredefinedType Task; + public readonly PredefinedType TaskGeneric; + + public PredefinedTypes (ModuleContainer module) + { + TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference"); + ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator"); + + MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject"); + RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers"); + IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult"); + AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback"); + RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle"); + CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet"); + IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile"); + IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1); + IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1); + ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1); + IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1); + Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1); + Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator"); + Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked"); + Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor"); + NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException"); + RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle"); + RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle"); + SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction"); + Dictionary = new PredefinedType (module, MemberKind.Class, "System.Collections.Generic", "Dictionary", 2); + Hashtable = new PredefinedType (module, MemberKind.Class, "System.Collections", "Hashtable"); + + Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression"); + ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1); + ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression"); + FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo"); + MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase"); + MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo"); + ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo"); + + CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite"); + CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1); + Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder"); + BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags"); + + Action = new PredefinedType (module, MemberKind.Delegate, "System", "Action"); + AsyncVoidMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncVoidMethodBuilder"); + AsyncTaskMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder"); + AsyncTaskMethodBuilderGeneric = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder", 1); + Task = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task"); + TaskGeneric = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task", 1); + + // + // Define types which are used for comparison. It does not matter + // if they don't exist as no error report is needed + // + if (TypedReference.Define ()) + TypedReference.TypeSpec.IsSpecialRuntimeType = true; + + if (ArgIterator.Define ()) + ArgIterator.TypeSpec.IsSpecialRuntimeType = true; + + if (IEnumerableGeneric.Define ()) + IEnumerableGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (IListGeneric.Define ()) + IListGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (ICollectionGeneric.Define ()) + ICollectionGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (Nullable.Define ()) + Nullable.TypeSpec.IsNullableType = true; + + if (ExpressionGeneric.Define ()) + ExpressionGeneric.TypeSpec.IsExpressionTreeType = true; + + Task.Define (); + if (TaskGeneric.Define ()) + TaskGeneric.TypeSpec.IsGenericTask = true; + } + } + + class PredefinedMembers + { + public readonly PredefinedMember ActivatorCreateInstance; + public readonly PredefinedMember AsyncTaskMethodBuilderCreate; + public readonly PredefinedMember AsyncTaskMethodBuilderSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderTask; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericCreate; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericTask; + public readonly PredefinedMember AsyncVoidMethodBuilderCreate; + public readonly PredefinedMember AsyncVoidMethodBuilderSetException; + public readonly PredefinedMember AsyncVoidMethodBuilderSetResult; + public readonly PredefinedMember DecimalCtor; + public readonly PredefinedMember DecimalCtorInt; + public readonly PredefinedMember DecimalCtorLong; + public readonly PredefinedMember DecimalConstantAttributeCtor; + public readonly PredefinedMember DefaultMemberAttributeCtor; + public readonly PredefinedMember DelegateCombine; + public readonly PredefinedMember DelegateEqual; + public readonly PredefinedMember DelegateInequal; + public readonly PredefinedMember DelegateRemove; + public readonly PredefinedMember DynamicAttributeCtor; + public readonly PredefinedMember FieldInfoGetFieldFromHandle; + public readonly PredefinedMember FieldInfoGetFieldFromHandle2; + public readonly PredefinedMember IDisposableDispose; + public readonly PredefinedMember IEnumerableGetEnumerator; + public readonly PredefinedMember InterlockedCompareExchange; + public readonly PredefinedMember InterlockedCompareExchange_T; + public readonly PredefinedMember FixedBufferAttributeCtor; + public readonly PredefinedMember MethodInfoGetMethodFromHandle; + public readonly PredefinedMember MethodInfoGetMethodFromHandle2; + public readonly PredefinedMember MonitorEnter; + public readonly PredefinedMember MonitorEnter_v4; + public readonly PredefinedMember MonitorExit; + public readonly PredefinedMember RuntimeCompatibilityWrapNonExceptionThrows; + public readonly PredefinedMember RuntimeHelpersInitializeArray; + public readonly PredefinedMember RuntimeHelpersOffsetToStringData; + public readonly PredefinedMember SecurityActionRequestMinimum; + public readonly PredefinedMember StringEmpty; + public readonly PredefinedMember StringEqual; + public readonly PredefinedMember StringInequal; + public readonly PredefinedMember StructLayoutAttributeCtor; + public readonly PredefinedMember StructLayoutCharSet; + public readonly PredefinedMember StructLayoutSize; + public readonly PredefinedMember TypeGetTypeFromHandle; + + public PredefinedMembers (ModuleContainer module) + { + var types = module.PredefinedTypes; + var atypes = module.PredefinedAttributes; + var btypes = module.Compiler.BuiltinTypes; + + ActivatorCreateInstance = new PredefinedMember (module, types.Activator, + MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null)); + + AsyncTaskMethodBuilderCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncTaskMethodBuilder.TypeSpec)); + + AsyncTaskMethodBuilderSetResult = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); + + AsyncTaskMethodBuilderTask = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Property ("Task", null)); + + AsyncTaskMethodBuilderGenericCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); + + AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Method ("SetResult", 0, + new ParametersImported ( + new[] { + new ParameterData (null, Parameter.Modifier.NONE) + }, + new[] { + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null) + }, false), btypes.Void)); + + AsyncTaskMethodBuilderGenericTask = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Property ("Task", null)); + + AsyncVoidMethodBuilderCreate = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); + + AsyncVoidMethodBuilderSetException = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("SetException", 0, null, btypes.Void)); + + AsyncVoidMethodBuilderSetResult = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); + + DecimalCtor = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + btypes.Int, btypes.Int, btypes.Int, btypes.Bool, btypes.Byte))); + + DecimalCtorInt = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Int))); + + DecimalCtorLong = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Long))); + + DecimalConstantAttributeCtor = new PredefinedMember (module, atypes.DecimalConstant, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + btypes.Byte, btypes.Byte, btypes.UInt, btypes.UInt, btypes.UInt))); + + DefaultMemberAttributeCtor = new PredefinedMember (module, atypes.DefaultMember, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.String))); + + DelegateCombine = new PredefinedMember (module, btypes.Delegate, "Combine", btypes.Delegate, btypes.Delegate); + DelegateRemove = new PredefinedMember (module, btypes.Delegate, "Remove", btypes.Delegate, btypes.Delegate); + + DelegateEqual = new PredefinedMember (module, btypes.Delegate, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); + + DelegateInequal = new PredefinedMember (module, btypes.Delegate, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); + + DynamicAttributeCtor = new PredefinedMember (module, atypes.Dynamic, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + ArrayContainer.MakeType (module, btypes.Bool)))); + + FieldInfoGetFieldFromHandle = new PredefinedMember (module, types.FieldInfo, + "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle); + + FieldInfoGetFieldFromHandle2 = new PredefinedMember (module, types.FieldInfo, + "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle, new PredefinedType (btypes.RuntimeTypeHandle)); + + FixedBufferAttributeCtor = new PredefinedMember (module, atypes.FixedBuffer, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Type, btypes.Int))); + + IDisposableDispose = new PredefinedMember (module, btypes.IDisposable, "Dispose", TypeSpec.EmptyTypes); + + IEnumerableGetEnumerator = new PredefinedMember (module, btypes.IEnumerable, + "GetEnumerator", TypeSpec.EmptyTypes); + + InterlockedCompareExchange = new PredefinedMember (module, types.Interlocked, + MemberFilter.Method ("CompareExchange", 0, + new ParametersImported ( + new[] { + new ParameterData (null, Parameter.Modifier.REF), + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.NONE) + }, + new[] { + btypes.Int, btypes.Int, btypes.Int + }, + false), + btypes.Int)); + + InterlockedCompareExchange_T = new PredefinedMember (module, types.Interlocked, + MemberFilter.Method ("CompareExchange", 1, + new ParametersImported ( + new[] { + new ParameterData (null, Parameter.Modifier.REF), + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.NONE) + }, + new[] { + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + }, false), + null)); + + MethodInfoGetMethodFromHandle = new PredefinedMember (module, types.MethodBase, + "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle); + + MethodInfoGetMethodFromHandle2 = new PredefinedMember (module, types.MethodBase, + "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle, new PredefinedType (btypes.RuntimeTypeHandle)); + + MonitorEnter = new PredefinedMember (module, types.Monitor, "Enter", btypes.Object); + + MonitorEnter_v4 = new PredefinedMember (module, types.Monitor, + MemberFilter.Method ("Enter", 0, + new ParametersImported (new[] { + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.REF) + }, + new[] { + btypes.Object, btypes.Bool + }, false), null)); + + MonitorExit = new PredefinedMember (module, types.Monitor, "Exit", btypes.Object); + + RuntimeCompatibilityWrapNonExceptionThrows = new PredefinedMember (module, atypes.RuntimeCompatibility, + MemberFilter.Property ("WrapNonExceptionThrows", btypes.Bool)); + + RuntimeHelpersInitializeArray = new PredefinedMember (module, types.RuntimeHelpers, + "InitializeArray", btypes.Array, btypes.RuntimeFieldHandle); + + RuntimeHelpersOffsetToStringData = new PredefinedMember (module, types.RuntimeHelpers, + MemberFilter.Property ("OffsetToStringData", btypes.Int)); + + SecurityActionRequestMinimum = new PredefinedMember (module, types.SecurityAction, "RequestMinimum", + MemberKind.Field, types.SecurityAction); + + StringEmpty = new PredefinedMember (module, btypes.String, MemberFilter.Field ("Empty", btypes.String)); + + StringEqual = new PredefinedMember (module, btypes.String, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); + + StringInequal = new PredefinedMember (module, btypes.String, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); + + StructLayoutAttributeCtor = new PredefinedMember (module, atypes.StructLayout, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Short))); + + StructLayoutCharSet = new PredefinedMember (module, atypes.StructLayout, "CharSet", + MemberKind.Field, types.CharSet); + + StructLayoutSize = new PredefinedMember (module, atypes.StructLayout, + MemberFilter.Field ("Size", btypes.Int)); + + TypeGetTypeFromHandle = new PredefinedMember (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle); + } + } + + public class PredefinedType + { + readonly string name; + readonly string ns; + readonly int arity; + readonly MemberKind kind; + protected readonly ModuleContainer module; + protected TypeSpec type; + + public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity) + : this (module, kind, ns, name) + { + this.arity = arity; + } + + public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name) + { + this.module = module; + this.kind = kind; + this.name = name; + this.ns = ns; + } + + public PredefinedType (BuiltinTypeSpec type) + { + this.kind = type.Kind; + this.name = type.Name; + this.ns = type.Namespace; + this.type = type; + } + + #region Properties + + public int Arity { + get { + return arity; + } + } + + public bool IsDefined { + get { + return type != null; + } + } + + public string Name { + get { + return name; + } + } + + public string Namespace { + get { + return ns; + } + } + + public TypeSpec TypeSpec { + get { + return type; + } + } + + #endregion + + public bool Define () + { + if (type != null) + return true; + + type = Resolve (module, kind, ns, name, arity, false); + return type != null; + } + + public string GetSignatureForError () + { + return ns + "." + name; + } + + public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity) + { + return Resolve (module, kind, ns, name, arity, true); + } + + public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, bool reportErrors) + { + Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true); + var found = type_ns.GetAllTypes (name); + if (found == null) { + if (reportErrors) + module.Compiler.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", ns, name); + + return null; + } + + TypeSpec best_match = null; + foreach (var candidate in found) { + if (candidate.Kind != kind) { + if (candidate.Kind == MemberKind.Struct && kind == MemberKind.Void && candidate.MemberDefinition is TypeContainer) { + // Void is declared as struct but we keep it internally as + // special kind, the swap will be done by caller + } else { + continue; + } + } + + if (candidate.Arity != arity) + continue; + + if ((candidate.Modifiers & Modifiers.INTERNAL) != 0 && !candidate.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly)) + continue; + + if (best_match == null) { + best_match = candidate; + continue; + } + + var other_match = best_match; + if (!best_match.MemberDefinition.IsImported && + module.Compiler.BuiltinTypes.Object.MemberDefinition.DeclaringAssembly == candidate.MemberDefinition.DeclaringAssembly) { + best_match = candidate; + } + + string location; + if (best_match.MemberDefinition is MemberCore) { + location = ((MemberCore) best_match.MemberDefinition).Location.Name; + } else { + var assembly = (ImportedAssemblyDefinition) best_match.MemberDefinition.DeclaringAssembly; + location = Path.GetFileName (assembly.Location); + } + + module.Compiler.Report.SymbolRelatedToPreviousError (other_match); + module.Compiler.Report.SymbolRelatedToPreviousError (candidate); + + module.Compiler.Report.Warning (1685, 1, + "The predefined type `{0}.{1}' is defined multiple times. Using definition from `{2}'", + ns, name, location); + + break; + } + + if (best_match == null && reportErrors) { + Location loc; + if (found[0].MemberDefinition is MemberCore) { + loc = ((MemberCore) found[0].MemberDefinition).Location; + } else { + loc = Location.Null; + module.Compiler.Report.SymbolRelatedToPreviousError (found[0]); + } + + module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name); + } + + return best_match; + } + + public TypeSpec Resolve () + { + if (type == null) + type = Resolve (module, kind, ns, name, arity); + + return type; + } + } + + class PredefinedMember where T : MemberSpec + { + readonly ModuleContainer module; + T member; + TypeSpec declaring_type; + readonly PredefinedType declaring_type_predefined; + readonly PredefinedType[] parameters_predefined; + MemberFilter filter; + + public PredefinedMember (ModuleContainer module, PredefinedType type, MemberFilter filter) + { + this.module = module; + this.declaring_type_predefined = type; + this.filter = filter; + } + + public PredefinedMember (ModuleContainer module, TypeSpec type, MemberFilter filter) + { + this.module = module; + this.declaring_type = type; + this.filter = filter; + } + + public PredefinedMember (ModuleContainer module, PredefinedType type, string name, params TypeSpec[] types) + : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null)) + { + } + + public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, params PredefinedType[] types) + : this (module, type, new MemberFilter (name, 0, kind, null, null)) + { + parameters_predefined = types; + } + + public PredefinedMember (ModuleContainer module, BuiltinTypeSpec type, string name, params TypeSpec[] types) + : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null)) + { + } + + public T Get () + { + if (member != null) + return member; + + if (declaring_type == null) { + if (!declaring_type_predefined.Define ()) + return null; + + declaring_type = declaring_type_predefined.TypeSpec; + } + + if (parameters_predefined != null) { + TypeSpec[] types = new TypeSpec [parameters_predefined.Length]; + for (int i = 0; i < types.Length; ++i) { + var p = parameters_predefined [i]; + if (!p.Define ()) + return null; + + types[i] = p.TypeSpec; + } + + if (filter.Kind == MemberKind.Field) + filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, null, types [0]); + else + filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType); + } + + member = MemberCache.FindMember (declaring_type, filter, BindingRestriction.DeclaredOnly) as T; + if (member == null) + return null; + + if (!member.IsAccessible (module)) + return null; + + return member; + } + + public T Resolve (Location loc) + { + if (member != null) + return member; + + if (Get () != null) + return member; + + if (declaring_type == null) { + if (declaring_type_predefined.Resolve () == null) + return null; + } + + if (parameters_predefined != null) { + TypeSpec[] types = new TypeSpec[parameters_predefined.Length]; + for (int i = 0; i < types.Length; ++i) { + var p = parameters_predefined[i]; + types[i] = p.Resolve (); + if (types[i] == null) + return null; + } + + filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType); + } + + string method_args = null; + if (filter.Parameters != null) + method_args = filter.Parameters.GetSignatureForError (); + + module.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible", + declaring_type.GetSignatureForError (), filter.Name, method_args); + + return null; + } + } + + partial class TypeManager { + + /// + /// Returns the C# name of a type if possible, or the full type name otherwise + /// + static public string CSharpName (TypeSpec t) + { + return t.GetSignatureForError (); + } + + static public string CSharpName (IList types) + { + if (types.Count == 0) + return string.Empty; + + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < types.Count; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (CSharpName (types [i])); + } + return sb.ToString (); + } + + static public string GetFullNameSignature (MemberSpec mi) + { + return mi.GetSignatureForError (); + } + + static public string CSharpSignature (MemberSpec mb) + { + return mb.GetSignatureForError (); + } + + // Obsolete + public static bool IsDelegateType (TypeSpec t) + { + return t.IsDelegate; + } + + // Obsolete + public static bool IsEnumType (TypeSpec t) + { + return t.IsEnum; + } + + // + // Whether a type is unmanaged. This is used by the unsafe code (25.2) + // + public static bool IsUnmanagedType (TypeSpec t) + { + var ds = t.MemberDefinition as DeclSpace; + if (ds != null) + return ds.IsUnmanagedType (); + + if (t.Kind == MemberKind.Void) + return true; + + // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it. + if (t.IsPointer) + return IsUnmanagedType (GetElementType (t)); + + if (!TypeSpec.IsValueType (t)) + return false; + + if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric) + return false; + + return true; + } + + public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent) + { +// TypeParameter tparam = LookupTypeParameter (type); +// TypeParameter pparam = LookupTypeParameter (parent); + + if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) { + if (type == parent) + return true; + + throw new NotImplementedException ("net"); +// return tparam.IsSubclassOf (parent); + } + + do { + if (IsInstantiationOfSameGenericType (type, parent)) + return true; + + type = type.BaseType; + } while (type != null); + + return false; + } + + // + // Checks whether `type' is a nested child of `parent'. + // + public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent) + { + if (type == null) + return false; + + if (type.MemberDefinition == parent) + return false; + + type = type.DeclaringType; + while (type != null) { + if (type.MemberDefinition == parent) + return true; + + type = type.DeclaringType; + } + + return false; + } + + public static TypeSpec GetElementType (TypeSpec t) + { + return ((ElementTypeSpec)t).Element; + } + + /// + /// This method is not implemented by MS runtime for dynamic types + /// + public static bool HasElementType (TypeSpec t) + { + return t is ElementTypeSpec; + } + + /// + /// Utility function that can be used to probe whether a type + /// is managed or not. + /// + public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc) + { + while (t.IsPointer) + t = GetElementType (t); + + if (IsUnmanagedType (t)) + return true; + + rc.Compiler.Report.SymbolRelatedToPreviousError (t); + rc.Compiler.Report.Error (208, loc, + "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'", + CSharpName (t)); + + return false; + } +#region Generics + // This method always return false for non-generic compiler, + // while Type.IsGenericParameter is returned if it is supported. + public static bool IsGenericParameter (TypeSpec type) + { + return type.IsGenericParameter; + } + + public static bool IsGenericType (TypeSpec type) + { + return type.IsGeneric; + } + + public static TypeSpec[] GetTypeArguments (TypeSpec t) + { + // TODO: return empty array !! + return t.TypeArguments; + } + + /// + /// Check whether `type' and `parent' are both instantiations of the same + /// generic type. Note that we do not check the type parameters here. + /// + public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent) + { + return type == parent || type.MemberDefinition == parent.MemberDefinition; + } +#endregion +} + +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs new file mode 100644 index 0000000000..8c0a5ddc2f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs @@ -0,0 +1,1759 @@ +// +// typespec.cs: Type specification +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2010 Novell, Inc +// + +using System; +using System.Collections.Generic; +using System.Text; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; +using System.Reflection; +#endif + +namespace Mono.CSharp +{ + public class TypeSpec : MemberSpec + { + protected MetaType info; + protected MemberCache cache; + protected IList ifaces; + TypeSpec base_type; + + Dictionary inflated_instances; + + public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0]; + +#if !STATIC + // Reflection Emit hacking + static readonly Type TypeBuilder; + static readonly Type GenericTypeBuilder; + + static TypeSpec () + { + var assembly = typeof (object).Assembly; + TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder"); + GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass"); + if (GenericTypeBuilder == null) + GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation"); + } +#endif + + public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers) + : base (kind, declaringType, definition, modifiers) + { + this.declaringType = declaringType; + this.info = info; + + if (definition != null && definition.TypeParametersCount > 0) + state |= StateFlags.IsGeneric; + } + + #region Properties + + public override int Arity { + get { + return MemberDefinition.TypeParametersCount; + } + } + + public virtual TypeSpec BaseType { + get { + return base_type; + } + set { + base_type = value; + } + } + + public virtual BuiltinTypeSpec.Type BuiltinType { + get { + return BuiltinTypeSpec.Type.None; + } + } + + public bool HasDynamicElement { + get { + return (state & StateFlags.HasDynamicElement) != 0; + } + } + + public virtual IList Interfaces { + get { + return ifaces; + } + set { + ifaces = value; + } + } + + public bool IsArray { + get { + return Kind == MemberKind.ArrayType; + } + } + + public bool IsAttribute { + get { + if (!IsClass) + return false; + + var type = this; + do { + if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute) + return true; + + if (type.IsGeneric) + return false; + + type = type.base_type; + } while (type != null); + + return false; + } + } + + public bool IsInterface { + get { + return Kind == MemberKind.Interface; + } + } + + public bool IsClass { + get { + return Kind == MemberKind.Class; + } + } + + public bool IsConstantCompatible { + get { + if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0) + return true; + + switch (BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Decimal: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + return false; + } + } + + public bool IsDelegate { + get { + return Kind == MemberKind.Delegate; + } + } + + // + // Returns true for instances of Expression + // + public virtual bool IsExpressionTreeType { + get { + return false; + } + set { + state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType; + } + } + + public bool IsEnum { + get { + return Kind == MemberKind.Enum; + } + } + + // + // Returns true for instances of IList, IEnumerable, ICollection + // + public virtual bool IsGenericIterateInterface { + get { + return false; + } + set { + state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface; + } + } + + // + // Returns true for instances of System.Threading.Tasks.Task + // + public virtual bool IsGenericTask { + get { + return false; + } + set { + state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask; + } + } + + // TODO: Should probably do + // IsGenericType -- recursive + // HasTypeParameter -- non-recursive + public bool IsGenericOrParentIsGeneric { + get { + var ts = this; + do { + if (ts.IsGeneric) + return true; + ts = ts.declaringType; + } while (ts != null); + + return false; + } + } + + public bool IsGenericParameter { + get { + return Kind == MemberKind.TypeParameter; + } + } + + // + // Returns true for instances of Nullable + // + public virtual bool IsNullableType { + get { + return false; + } + set { + state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType; + } + } + + public bool IsNested { + get { return declaringType != null && Kind != MemberKind.TypeParameter; } + } + + public bool IsPointer { + get { + return Kind == MemberKind.PointerType; + } + } + + public bool IsSealed { + get { return (Modifiers & Modifiers.SEALED) != 0; } + } + + public bool IsSpecialRuntimeType { + get { + return (state & StateFlags.SpecialRuntimeType) != 0; + } + set { + state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType; + } + } + + public bool IsStruct { + get { + return Kind == MemberKind.Struct; + } + } + + public bool IsTypeBuilder { + get { +#if STATIC + return true; +#else + var meta = GetMetaInfo().GetType (); + return meta == TypeBuilder || meta == GenericTypeBuilder; +#endif + } + } + + public MemberCache MemberCache { + get { + if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0) + InitializeMemberCache (false); + + return cache; + } + set { + if (cache != null) + throw new InternalErrorException ("Membercache reset"); + + cache = value; + } + } + + public MemberCache MemberCacheTypes { + get { + if (cache == null) + InitializeMemberCache (true); + + return cache; + } + } + + public new ITypeDefinition MemberDefinition { + get { + return (ITypeDefinition) definition; + } + } + + // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and + // remove the property, YES IT WOULD !!! + public virtual TypeSpec[] TypeArguments { + get { return TypeSpec.EmptyTypes; } + } + + #endregion + + public bool AddInterface (TypeSpec iface) + { + if ((state & StateFlags.InterfacesExpanded) != 0) + throw new InternalErrorException ("Modifying expanded interface list"); + + if (ifaces == null) { + ifaces = new List () { iface }; + return true; + } + + if (!ifaces.Contains (iface)) { + ifaces.Add (iface); + return true; + } + + return false; + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + if (Kind != MemberKind.Class) + throw new InternalErrorException (); + + if (!pa.IsDefined) + return Attribute.DefaultUsageAttribute; + + AttributeUsageAttribute aua = null; + var type = this; + while (type != null) { + aua = type.MemberDefinition.GetAttributeUsage (pa); + if (aua != null) + break; + + type = type.BaseType; + } + + return aua; + } + + public virtual MetaType GetMetaInfo () + { + return info; + } + + public virtual TypeSpec GetDefinition () + { + return this; + } + + public override string GetSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + if (IsNested) { + sb.Append (DeclaringType.GetSignatureForDocumentation ()); + } else { + sb.Append (MemberDefinition.Namespace); + } + + if (sb.Length != 0) + sb.Append ("."); + + sb.Append (Name); + if (Arity > 0) { + if (this is InflatedTypeSpec) { + sb.Append ("{"); + for (int i = 0; i < Arity; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (TypeArguments[i].GetSignatureForDocumentation ()); + } + sb.Append ("}"); + } else { + sb.Append ("`"); + sb.Append (Arity.ToString ()); + } + } + + return sb.ToString (); + } + + public string GetExplicitNameSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + if (IsNested) { + sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ()); + } else if (MemberDefinition.Namespace != null) { + sb.Append (MemberDefinition.Namespace.Replace ('.', '#')); + } + + if (sb.Length != 0) + sb.Append ("#"); + + sb.Append (Name); + if (Arity > 0) { + sb.Append ("{"); + for (int i = 0; i < Arity; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ()); + } + sb.Append ("}"); + } + + return sb.ToString (); + } + + public override string GetSignatureForError () + { + string s; + + if (IsNested) { + s = DeclaringType.GetSignatureForError (); + } else if (MemberDefinition is AnonymousTypeClass) { + return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError (); + } else { + s = MemberDefinition.Namespace; + } + + if (!string.IsNullOrEmpty (s)) + s += "."; + + return s + Name + GetTypeNameSignature (); + } + + public string GetSignatureForErrorIncludingAssemblyName () + { + return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName); + } + + protected virtual string GetTypeNameSignature () + { + if (!IsGeneric) + return null; + + return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">"; + } + + public bool ImplementsInterface (TypeSpec iface, bool variantly) + { + var t = this; + do { + if (t.Interfaces != null) { + foreach (TypeSpec i in t.Interfaces) { + if (i == iface || TypeSpecComparer.IsEqual (i, iface)) + return true; + + if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface)) + return true; + } + } + + // TODO: Why is it needed when we do it during import + t = t.BaseType; + } while (t != null); + + return false; + } + + protected virtual void InitializeMemberCache (bool onlyTypes) + { + try { + MemberDefinition.LoadMembers (this, onlyTypes, ref cache); + } catch (Exception e) { + throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ()); + } + + if (onlyTypes) + state |= StateFlags.PendingMemberCacheMembers; + else + state &= ~StateFlags.PendingMemberCacheMembers; + } + + // + // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower + // comparison is used to hide differences between `object' and `dynamic' for generic + // types. Should not be used for comparisons where G != G + // + public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject) + { + if (dynamicIsObject && baseClass.IsGeneric) { + // + // Returns true for a hierarchies like this when passing baseClass of A + // + // class B : A {} + // + type = type.BaseType; + while (type != null) { + if (TypeSpecComparer.IsEqual (type, baseClass)) + return true; + + type = type.BaseType; + } + + return false; + } + + while (type != null) { + type = type.BaseType; + if (type == baseClass) + return true; + } + + return false; + } + + public static bool IsReferenceType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsReferenceType; + case MemberKind.Struct: + case MemberKind.Enum: + return false; + case MemberKind.InternalCompilerType: + // + // Null is considered to be a reference type + // + return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + default: + return true; + } + } + + public static bool IsValueType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsValueType; + case MemberKind.Struct: + case MemberKind.Enum: + return true; + default: + return false; + } + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes; + + // + // When inflating nested type from inside the type instance will be same + // because type parameters are same for all nested types + // + if (DeclaringType == inflator.TypeInstance) { + return MakeGenericType (inflator.Context, targs); + } + + return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs); + } + + public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs) + { + if (targs.Length == 0 && !IsNested) + throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ()); + + InflatedTypeSpec instance; + + if (inflated_instances == null) { + inflated_instances = new Dictionary (TypeSpecComparer.Default); + + if (IsNested) { + instance = this as InflatedTypeSpec; + if (instance != null) { + // + // Nested types could be inflated on already inflated instances + // Caching this type ensured we are using same instance for + // inside/outside inflation using local type parameters + // + inflated_instances.Add (TypeArguments, instance); + } + } + } + + if (!inflated_instances.TryGetValue (targs, out instance)) { + if (GetDefinition () != this && !IsNested) + throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType", + GetSignatureForError ()); + + instance = new InflatedTypeSpec (context, this, declaringType, targs); + inflated_instances.Add (targs, instance); + } + + return instance; + } + + public virtual TypeSpec Mutate (TypeParameterMutator mutator) + { + return this; + } + + public override List ResolveMissingDependencies () + { + List missing = null; + + if (Kind == MemberKind.MissingType) { + missing = new List (); + missing.Add (this); + return missing; + } + + foreach (var targ in TypeArguments) { + if (targ.Kind == MemberKind.MissingType) { + if (missing == null) + missing = new List (); + + missing.Add (targ); + } + } + + if (Interfaces != null) { + foreach (var iface in Interfaces) { + if (iface.Kind == MemberKind.MissingType) { + if (missing == null) + missing = new List (); + + missing.Add (iface); + } + } + } + + if (missing != null || BaseType == null) + return missing; + + return BaseType.ResolveMissingDependencies (); + } + + public void SetMetaInfo (MetaType info) + { + if (this.info != null) + throw new InternalErrorException ("MetaInfo reset"); + + this.info = info; + } + + public void SetExtensionMethodContainer () + { + modifiers |= Modifiers.METHOD_EXTENSION; + } + } + + public sealed class BuiltinTypeSpec : TypeSpec + { + public enum Type + { + None = 0, + + // Ordered carefully for fast compares + FirstPrimitive = 1, + Bool = 1, + Byte = 2, + SByte = 3, + Char = 4, + Short = 5, + UShort = 6, + Int = 7, + UInt = 8, + Long = 9, + ULong = 10, + Float = 11, + Double = 12, + LastPrimitive = 12, + Decimal = 13, + + IntPtr = 14, + UIntPtr = 15, + + Object = 16, + Dynamic = 17, + String = 18, + Type = 19, + + ValueType = 20, + Enum = 21, + Delegate = 22, + MulticastDelegate = 23, + Array = 24, + + IEnumerator, + IEnumerable, + IDisposable, + Exception, + Attribute, + Other, + } + + readonly Type type; + readonly string ns; + readonly string name; + + public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind) + : base (kind, null, null, null, Modifiers.PUBLIC) + { + this.type = builtinKind; + this.ns = ns; + this.name = name; + } + + public BuiltinTypeSpec (string name, Type builtinKind) + : this (MemberKind.InternalCompilerType, "", name, builtinKind) + { + // Make all internal types CLS-compliant, non-obsolete, compact + state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant; + } + + #region Properties + + public override int Arity { + get { + return 0; + } + } + + public override BuiltinTypeSpec.Type BuiltinType { + get { + return type; + } + } + + public string FullName { + get { + return ns + '.' + name; + } + } + + public override string Name { + get { + return name; + } + } + + public string Namespace { + get { + return ns; + } + } + + #endregion + + public static bool IsPrimitiveType (TypeSpec type) + { + return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive; + } + + public static bool IsPrimitiveTypeOrDecimal (TypeSpec type) + { + return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal; + } + + public override string GetSignatureForError () + { + switch (Name) { + case "Int32": return "int"; + case "Int64": return "long"; + case "String": return "string"; + case "Boolean": return "bool"; + case "Void": return "void"; + case "Object": return "object"; + case "UInt32": return "uint"; + case "Int16": return "short"; + case "UInt16": return "ushort"; + case "UInt64": return "ulong"; + case "Single": return "float"; + case "Double": return "double"; + case "Decimal": return "decimal"; + case "Char": return "char"; + case "Byte": return "byte"; + case "SByte": return "sbyte"; + } + + if (ns.Length == 0) + return name; + + return FullName; + } + + // + // Returns the size of type if known, otherwise, 0 + // + public static int GetSize (TypeSpec type) + { + switch (type.BuiltinType) { + case Type.Int: + case Type.UInt: + case Type.Float: + return 4; + case Type.Long: + case Type.ULong: + case Type.Double: + return 8; + case Type.Byte: + case Type.SByte: + case Type.Bool: + return 1; + case Type.Short: + case Type.Char: + case Type.UShort: + return 2; + case Type.Decimal: + return 16; + default: + return 0; + } + } + + public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod) + { + this.definition = td; + this.info = type; + this.modifiers |= (mod & ~Modifiers.AccessibilityMask); + } + + public void SetDefinition (TypeSpec ts) + { + this.definition = ts.MemberDefinition; + this.info = ts.GetMetaInfo (); + this.BaseType = ts.BaseType; + this.Interfaces = ts.Interfaces; + this.modifiers = ts.Modifiers; + } + } + + static class TypeSpecComparer + { + // + // Does strict reference comparion only + // + public static readonly DefaultImpl Default = new DefaultImpl (); + + public class DefaultImpl : IEqualityComparer + { + #region IEqualityComparer Members + + bool IEqualityComparer.Equals (TypeSpec[] x, TypeSpec[] y) + { + if (x == y) + return true; + + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; ++i) + if (x[i] != y[i]) + return false; + + return true; + } + + int IEqualityComparer.GetHashCode (TypeSpec[] obj) + { + int hash = 0; + for (int i = 0; i < obj.Length; ++i) + hash = (hash << 5) - hash + obj[i].GetHashCode (); + + return hash; + } + + #endregion + } + + // + // When comparing type signature of overrides or overloads + // this version tolerates different MVARs at same position + // + public static class Override + { + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a == b) + return true; + + // + // Consider the following example: + // + // public abstract class A + // { + // public abstract T Foo(); + // } + // + // public class B : A + // { + // public override U Foo() { return default (U); } + // } + // + // Here, `T' and `U' are method type parameters from different methods + // (A.Foo and B.Foo), so both `==' and Equals() will fail. + // + // However, since we're determining whether B.Foo() overrides A.Foo(), + // we need to do a signature based comparision and consider them equal. + // + + var tp_a = a as TypeParameterSpec; + if (tp_a != null) { + var tp_b = b as TypeParameterSpec; + return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition; + } + + var ac_a = a as ArrayContainer; + if (ac_a != null) { + var ac_b = b as ArrayContainer; + return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element); + } + + if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object; + + if (a.MemberDefinition != b.MemberDefinition) + return false; + + do { + for (int i = 0; i < a.TypeArguments.Length; ++i) { + if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i])) + return false; + } + + a = a.DeclaringType; + b = b.DeclaringType; + } while (a != null); + + return true; + } + + // + // Compares unordered arrays + // + public static bool IsSame (TypeSpec[] a, TypeSpec[] b) + { + if (a == b) + return true; + + if (a == null || b == null || a.Length != b.Length) + return false; + + for (int ai = 0; ai < a.Length; ++ai) { + bool found = false; + for (int bi = 0; bi < b.Length; ++bi) { + if (IsEqual (a[ai], b[bi])) { + found = true; + break; + } + } + + if (!found) + return false; + } + + return true; + } + + public static bool IsEqual (AParametersCollection a, AParametersCollection b) + { + if (a == b) + return true; + + if (a.Count != b.Count) + return false; + + for (int i = 0; i < a.Count; ++i) { + if (!IsEqual (a.Types[i], b.Types[i])) + return false; + + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out)) + return false; + } + + return true; + } + } + + // + // Type variance equality comparison + // + public static class Variant + { + public static bool IsEqual (TypeSpec type1, TypeSpec type2) + { + if (!type1.IsGeneric || !type2.IsGeneric) + return false; + + var target_type_def = type2.MemberDefinition; + if (type1.MemberDefinition != target_type_def) + return false; + + var t1_targs = type1.TypeArguments; + var t2_targs = type2.TypeArguments; + var targs_definition = target_type_def.TypeParameters; + + if (!type1.IsInterface && !type1.IsDelegate) { + return false; + } + + for (int i = 0; i < targs_definition.Length; ++i) { + Variance v = targs_definition[i].Variance; + if (v == Variance.None) { + if (t1_targs[i] == t2_targs[i]) + continue; + return false; + } + + if (v == Variance.Covariant) { + if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i])) + return false; + } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) { + return false; + } + } + + return true; + } + } + + // + // Checks whether two generic instances may become equal for some + // particular instantiation (26.3.1). + // + public static class Unify + { + // + // Either @a or @b must be generic type + // + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a.MemberDefinition != b.MemberDefinition) { + var base_ifaces = a.Interfaces; + if (base_ifaces != null) { + foreach (var base_iface in base_ifaces) { + if (base_iface.Arity > 0 && IsEqual (base_iface, b)) + return true; + } + } + + return false; + } + + var ta = a.TypeArguments; + var tb = b.TypeArguments; + for (int i = 0; i < ta.Length; i++) { + if (!MayBecomeEqualGenericTypes (ta[i], tb[i])) + return false; + } + + return true; + } + + static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type) + { + TypeSpec[] targs = type.TypeArguments; + for (int i = 0; i < targs.Length; i++) { + if (tparam == targs[i]) + return true; + + if (ContainsTypeParameter (tparam, targs[i])) + return true; + } + + return false; + } + + /// + /// Check whether `a' and `b' may become equal generic types. + /// The algorithm to do that is a little bit complicated. + /// + static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b) + { + if (a.IsGenericParameter) { + // + // If a is an array of a's type, they may never + // become equal. + // + if (b.IsArray) + return false; + + // + // If b is a generic parameter or an actual type, + // they may become equal: + // + // class X : I, I + // class X : I, I + // + if (b.IsGenericParameter) + return a != b && a.DeclaringType == b.DeclaringType; + + // + // We're now comparing a type parameter with a + // generic instance. They may become equal unless + // the type parameter appears anywhere in the + // generic instance: + // + // class X : I, I> + // -> error because you could instanciate it as + // X,int> + // + // class X : I, I> -> ok + // + + return !ContainsTypeParameter (a, b); + } + + if (b.IsGenericParameter) + return MayBecomeEqualGenericTypes (b, a); + + // + // At this point, neither a nor b are a type parameter. + // + // If one of them is a generic instance, compare them (if the + // other one is not a generic instance, they can never + // become equal). + // + if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b)) + return IsEqual (a, b); + + // + // If both of them are arrays. + // + var a_ac = a as ArrayContainer; + if (a_ac != null) { + var b_ac = b as ArrayContainer; + if (b_ac == null || a_ac.Rank != b_ac.Rank) + return false; + + return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element); + } + + // + // Ok, two ordinary types. + // + return false; + } + } + + public static bool Equals (TypeSpec[] x, TypeSpec[] y) + { + if (x == y) + return true; + + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; ++i) + if (!IsEqual (x[i], y[i])) + return false; + + return true; + } + + // + // Identity type conversion + // + // Default reference comparison, it has to be used when comparing + // two possible dynamic/internal types + // + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a == b) { + // This also rejects dynamic == dynamic + return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + } + + if (a == null || b == null) + return false; + + if (a.IsArray) { + var a_a = (ArrayContainer) a; + var b_a = b as ArrayContainer; + if (b_a == null) + return false; + + return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element); + } + + if (!a.IsGeneric || !b.IsGeneric) { + // + // object and dynamic are considered equivalent there is an identity conversion + // between object and dynamic, and between constructed types that are the same + // when replacing all occurences of dynamic with object. + // + if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object; + + return false; + } + + if (a.MemberDefinition != b.MemberDefinition) + return false; + + do { + if (!Equals (a.TypeArguments, b.TypeArguments)) + return false; + + a = a.DeclaringType; + b = b.DeclaringType; + } while (a != null); + + return true; + } + } + + public interface ITypeDefinition : IMemberDefinition + { + IAssemblyDefinition DeclaringAssembly { get; } + string Namespace { get; } + int TypeParametersCount { get; } + TypeParameterSpec[] TypeParameters { get; } + + TypeSpec GetAttributeCoClass (); + string GetAttributeDefaultMember (); + AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa); + bool IsInternalAsPublic (IAssemblyDefinition assembly); + void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache); + } + + class InternalType : TypeSpec, ITypeDefinition + { + public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method"); + public static readonly InternalType Arglist = new InternalType ("__arglist"); + public static readonly InternalType MethodGroup = new InternalType ("method group"); + public static readonly InternalType NullLiteral = new InternalType ("null"); + public static readonly InternalType FakeInternalType = new InternalType (""); + public static readonly InternalType Namespace = new InternalType (""); + + readonly string name; + + InternalType (string name, MemberCache cache) + : this (name) + { + this.cache = cache; + } + + InternalType (string name) + : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC) + { + this.name = name; + this.definition = this; + cache = MemberCache.Empty; + + // Make all internal types CLS-compliant, non-obsolete + state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant; + } + + #region Properties + + public override int Arity { + get { + return 0; + } + } + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + throw new NotImplementedException (); + } + } + + bool IMemberDefinition.IsImported { + get { + return false; + } + } + + public override string Name { + get { + return name; + } + } + + string ITypeDefinition.Namespace { + get { + return null; + } + } + + int ITypeDefinition.TypeParametersCount { + get { + return 0; + } + } + + TypeParameterSpec[] ITypeDefinition.TypeParameters { + get { + return null; + } + } + + #endregion + + public override string GetSignatureForError () + { + return name; + } + + #region ITypeDefinition Members + + TypeSpec ITypeDefinition.GetAttributeCoClass () + { + return null; + } + + string ITypeDefinition.GetAttributeDefaultMember () + { + return null; + } + + AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa) + { + return null; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + throw new NotImplementedException (); + } + + void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotImplementedException (); + } + + string[] IMemberDefinition.ConditionalConditions () + { + return null; + } + + ObsoleteAttribute IMemberDefinition.GetAttributeObsolete () + { + return null; + } + + bool? IMemberDefinition.CLSAttributeValue { + get { + return null; + } + } + + void IMemberDefinition.SetIsAssigned () + { + } + + void IMemberDefinition.SetIsUsed () + { + } + + #endregion + } + + public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition + { + protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info) + : base (kind, element.DeclaringType, null, info, element.Modifiers) + { + this.Element = element; + + // Some flags can be copied directly from the element + const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected + | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement; + state &= ~shared_flags; + state |= (element.state & shared_flags); + + if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + state |= StateFlags.HasDynamicElement; + + // Has to use its own type definition instead of just element definition to + // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition + this.definition = this; + + cache = MemberCache.Empty; + } + + #region Properties + + public TypeSpec Element { get; private set; } + + public override string Name { + get { + throw new NotSupportedException (); + } + } + + #endregion + + public override ObsoleteAttribute GetAttributeObsolete () + { + return Element.GetAttributeObsolete (); + } + + protected virtual string GetPostfixSignature () + { + return null; + } + + public override string GetSignatureForDocumentation () + { + return Element.GetSignatureForDocumentation () + GetPostfixSignature (); + } + + public override string GetSignatureForError () + { + return Element.GetSignatureForError () + GetPostfixSignature (); + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + var me = Element.Mutate (mutator); + if (me == Element) + return this; + + var mutated = (ElementTypeSpec) MemberwiseClone (); + mutated.Element = me; + mutated.info = null; + return mutated; + } + + #region ITypeDefinition Members + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + return Element.MemberDefinition.DeclaringAssembly; + } + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return Element.MemberDefinition.IsInternalAsPublic (assembly); + } + + public string Namespace { + get { throw new NotImplementedException (); } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + throw new NotSupportedException (); + } + } + + public TypeSpec GetAttributeCoClass () + { + return Element.MemberDefinition.GetAttributeCoClass (); + } + + public string GetAttributeDefaultMember () + { + return Element.MemberDefinition.GetAttributeDefaultMember (); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache); + } + + public bool IsImported { + get { + return Element.MemberDefinition.IsImported; + } + } + + public string[] ConditionalConditions () + { + return Element.MemberDefinition.ConditionalConditions (); + } + + bool? IMemberDefinition.CLSAttributeValue { + get { + return Element.MemberDefinition.CLSAttributeValue; + } + } + + public void SetIsAssigned () + { + Element.MemberDefinition.SetIsAssigned (); + } + + public void SetIsUsed () + { + Element.MemberDefinition.SetIsUsed (); + } + + #endregion + } + + public class ArrayContainer : ElementTypeSpec + { + public struct TypeRankPair : IEquatable + { + TypeSpec ts; + int rank; + + public TypeRankPair (TypeSpec ts, int rank) + { + this.ts = ts; + this.rank = rank; + } + + public override int GetHashCode () + { + return ts.GetHashCode () ^ rank.GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (TypeRankPair other) + { + return other.ts == ts && other.rank == rank; + } + + #endregion + } + + readonly int rank; + readonly ModuleContainer module; + + private ArrayContainer (ModuleContainer module, TypeSpec element, int rank) + : base (MemberKind.ArrayType, element, null) + { + this.module = module; + this.rank = rank; + } + + public int Rank { + get { + return rank; + } + } + + public MethodInfo GetConstructor () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var ctor = mb.GetArrayMethod ( + GetMetaInfo (), Constructor.ConstructorName, + CallingConventions.HasThis, + null, arg_types); + + return ctor; + } + + public MethodInfo GetAddressMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var address = mb.GetArrayMethod ( + GetMetaInfo (), "Address", + CallingConventions.HasThis | CallingConventions.Standard, + ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types); + + return address; + } + + public MethodInfo GetGetMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var get = mb.GetArrayMethod ( + GetMetaInfo (), "Get", + CallingConventions.HasThis | CallingConventions.Standard, + Element.GetMetaInfo (), arg_types); + + return get; + } + + public MethodInfo GetSetMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank + 1]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + arg_types[rank] = Element.GetMetaInfo (); + + var set = mb.GetArrayMethod ( + GetMetaInfo (), "Set", + CallingConventions.HasThis | CallingConventions.Standard, + module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types); + + return set; + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + if (rank == 1) + info = Element.GetMetaInfo ().MakeArrayType (); + else + info = Element.GetMetaInfo ().MakeArrayType (rank); + } + + return info; + } + + protected override string GetPostfixSignature() + { + return GetPostfixSignature (rank); + } + + public static string GetPostfixSignature (int rank) + { + StringBuilder sb = new StringBuilder (); + sb.Append ("["); + for (int i = 1; i < rank; i++) { + sb.Append (","); + } + sb.Append ("]"); + + return sb.ToString (); + } + + public override string GetSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + GetElementSignatureForDocumentation (sb); + return sb.ToString (); + } + + void GetElementSignatureForDocumentation (StringBuilder sb) + { + var ac = Element as ArrayContainer; + if (ac == null) + sb.Append (Element.GetSignatureForDocumentation ()); + else + ac.GetElementSignatureForDocumentation (sb); + + sb.Append ("["); + for (int i = 1; i < rank; i++) { + if (i == 1) + sb.Append ("0:"); + + sb.Append (",0:"); + } + sb.Append ("]"); + } + + public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element) + { + return MakeType (module, element, 1); + } + + public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank) + { + ArrayContainer ac; + var key = new TypeRankPair (element, rank); + if (!module.ArrayTypesCache.TryGetValue (key, out ac)) { + ac = new ArrayContainer (module, element, rank) { + BaseType = module.Compiler.BuiltinTypes.Array + }; + + module.ArrayTypesCache.Add (key, ac); + } + + return ac; + } + } + + class ReferenceContainer : ElementTypeSpec + { + private ReferenceContainer (TypeSpec element) + : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong + { + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + info = Element.GetMetaInfo ().MakeByRefType (); + } + + return info; + } + + public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element) + { + ReferenceContainer pc; + if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) { + pc = new ReferenceContainer (element); + module.ReferenceTypesCache.Add (element, pc); + } + + return pc; + } + } + + class PointerContainer : ElementTypeSpec + { + private PointerContainer (TypeSpec element) + : base (MemberKind.PointerType, element, null) + { + // It's never CLS-Compliant + state &= ~StateFlags.CLSCompliant_Undetected; + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + info = Element.GetMetaInfo ().MakePointerType (); + } + + return info; + } + + protected override string GetPostfixSignature() + { + return "*"; + } + + public static PointerContainer MakeType (ModuleContainer module, TypeSpec element) + { + PointerContainer pc; + if (!module.PointerTypesCache.TryGetValue (element, out pc)) { + pc = new PointerContainer (element); + module.PointerTypesCache.Add (element, pc); + } + + return pc; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs new file mode 100644 index 0000000000..0ac678300c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs @@ -0,0 +1,630 @@ +// +// visit.cs: Visitors for parsed dom +// +// Authors: Mike Krüger (mkrueger@novell.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// + +using System; + +namespace Mono.CSharp +{ + public abstract class StructuralVisitor + { + public virtual void Visit (MemberCore member) + { + Console.WriteLine ("unknown member type: " + member.GetType ()); + } + + public virtual void Visit (ModuleContainer mc) + {/* + if (mc.Delegates != null) { + foreach (TypeContainer tc in mc.Delegates) { + tc.Accept (this); + } + }*/ + if (mc.Types != null) { + foreach (TypeContainer tc in mc.Types) { + tc.Accept (this); + } + } + } + + void VisitTypeContainer (TypeContainer tc) + { + foreach (MemberCore member in tc.OrderedAllMembers) { + member.Accept (this); + } + } + + protected void VisitNamespaceUsings (UsingsBag.Namespace nspace) + { + foreach (object u in nspace.usings) { + if (u is UsingsBag.Using) { + ((UsingsBag.Using)u).Accept (this); + } else { + ((UsingsBag.AliasUsing)u).Accept (this); + } + } + } + + protected void VisitNamespaceBody (UsingsBag.Namespace nspace) + { + foreach (object member in nspace.members) { + if (member is MemberCore) { + ((MemberCore)member).Accept (this); + } else { + ((UsingsBag.Namespace)member).Accept (this); + } + } + } + + public virtual void Visit (UsingsBag.Namespace nspace) + { + VisitNamespaceUsings (nspace); + VisitNamespaceBody (nspace); + } + + public virtual void Visit (UsingsBag.Using u) + { + } + + public virtual void Visit (UsingsBag.AliasUsing aliasUsing) + { + } + + public virtual void Visit (UsingsBag.ExternAlias externAlias) + { + } + + public virtual void Visit (Class c) + { + VisitTypeContainer (c); + } + + public virtual void Visit (Struct s) + { + VisitTypeContainer (s); + } + + + public virtual void Visit (Interface i) + { + VisitTypeContainer (i); + } + + public virtual void Visit (Delegate d) + { + } + + public virtual void Visit (Enum e) + { + VisitTypeContainer (e); + } + + public virtual void Visit (FixedField f) + { + } + + public virtual void Visit (Const c) + { + } + + public virtual void Visit (Field f) + { + } + + public virtual void Visit (Operator o) + { + } + + public virtual void Visit (Indexer i) + { + } + + public virtual void Visit (Method m) + { + } + + public virtual void Visit (Property p) + { + } + + public virtual void Visit (Constructor c) + { + } + + public virtual void Visit (Destructor d) + { + } + + public virtual void Visit (EventField e) + { + } + public virtual void Visit (EventProperty ep) + { + } + + public virtual void Visit (EnumMember em) + { + } + + public virtual object Visit (Statement stmt) + { + Console.WriteLine ("unknown statement:" + stmt); + return null; + } + + public virtual object Visit (BlockVariableDeclaration blockVariableDeclaration) + { + return null; + } + + public virtual object Visit (BlockConstantDeclaration blockConstantDeclaration) + { + return null; + } + + public virtual object Visit (EmptyStatement emptyStatement) + { + return null; + } + + public virtual object Visit (EmptyExpressionStatement emptyExpressionStatement) + { + return null; + } + + public virtual object Visit (If ifStatement) + { + return null; + } + + + public virtual object Visit (Do doStatement) + { + return null; + } + + + public virtual object Visit (While whileStatement) + { + return null; + } + + + public virtual object Visit (For forStatement) + { + return null; + } + + + public virtual object Visit (StatementExpression statementExpression) + { + return null; + } + + + public virtual object Visit (Return returnStatement) + { + return null; + } + + + public virtual object Visit (Goto gotoStatement) + { + return null; + } + + + public virtual object Visit (LabeledStatement labeledStatement) + { + return null; + } + + + public virtual object Visit (GotoDefault gotoDefault) + { + return null; + } + + + public virtual object Visit (GotoCase gotoCase) + { + return null; + } + + + public virtual object Visit (Throw throwStatement) + { + return null; + } + + + public virtual object Visit (Break breakStatement) + { + return null; + } + + + public virtual object Visit (Continue continueStatement) + { + return null; + } + + + public virtual object Visit (Block blockStatement) + { + return null; + } + + public virtual object Visit (Switch switchStatement) + { + return null; + } + + public virtual object Visit (StatementList statementList) + { + return null; + } + + public virtual object Visit (Lock lockStatement) + { + return null; + } + + + public virtual object Visit (Unchecked uncheckedStatement) + { + return null; + } + + + public virtual object Visit (Checked checkedStatement) + { + return null; + } + + + public virtual object Visit (Unsafe unsafeStatement) + { + return null; + } + + + public virtual object Visit (Fixed fixedStatement) + { + return null; + } + + + public virtual object Visit (TryFinally tryFinallyStatement) + { + return null; + } + + + public virtual object Visit (TryCatch tryCatchStatement) + { + return null; + } + + public virtual object Visit (Using usingStatement) + { + return null; + } + + public virtual object Visit (Foreach foreachStatement) + { + return null; + } + + public virtual object Visit (Yield yieldStatement) + { + return null; + } + + public virtual object Visit (YieldBreak yieldBreakStatement) + { + return null; + } + + public virtual object Visit (Expression expression) + { + Console.WriteLine ("Visit unknown expression:" + expression); + return null; + } + + public virtual object Visit (MemberAccess memberAccess) + { + return null; + } + + public virtual object Visit (QualifiedAliasMember qualifiedAliasMember) + { + return null; + } + + public virtual object Visit (LocalVariableReference localVariableReference) + { + return null; + } + + public virtual object Visit (Constant constant) + { + return null; + } + + public virtual object Visit (BooleanExpression booleanExpression) + { + return null; + } + + public virtual object Visit (SimpleName simpleName) + { + return null; + } + + public virtual object Visit (ParenthesizedExpression parenthesizedExpression) + { + return null; + } + + public virtual object Visit (Unary unaryExpression) + { + return null; + } + + public virtual object Visit (UnaryMutator unaryMutatorExpression) + { + return null; + } + + // *expr + public virtual object Visit (Indirection indirectionExpression) + { + return null; + } + + public virtual object Visit (Is isExpression) + { + return null; + } + + public virtual object Visit (As asExpression) + { + return null; + } + + public virtual object Visit (Cast castExpression) + { + return null; + } + + public virtual object Visit (ComposedCast composedCast) + { + return null; + } + + public virtual object Visit (DefaultValueExpression defaultValueExpression) + { + return null; + } + + public virtual object Visit (DefaultParameterValueExpression defaultParameterValueExpression) + { + return null; + } + + public virtual object Visit (Binary binaryExpression) + { + return null; + } + + public virtual object Visit (Nullable.NullCoalescingOperator nullCoalescingOperator) + { + return null; + } + + + public virtual object Visit (Conditional conditionalExpression) + { + return null; + } + + public virtual object Visit (Invocation invocationExpression) + { + return null; + } + + public virtual object Visit (New newExpression) + { + return null; + } + + public virtual object Visit (NewAnonymousType newAnonymousType) + { + return null; + } + + public virtual object Visit (NewInitialize newInitializeExpression) + { + return null; + } + + public virtual object Visit (ArrayCreation arrayCreationExpression) + { + return null; + } + + public virtual object Visit (This thisExpression) + { + return null; + } + + public virtual object Visit (ArglistAccess argListAccessExpression) + { + return null; + } + + public virtual object Visit (Arglist argListExpression) + { + return null; + } + + public virtual object Visit (TypeOf typeOfExpression) + { + return null; + } + + public virtual object Visit (SizeOf sizeOfExpression) + { + return null; + } + + public virtual object Visit (CheckedExpr checkedExpression) + { + return null; + } + + public virtual object Visit (UnCheckedExpr uncheckedExpression) + { + return null; + } + + public virtual object Visit (ElementAccess elementAccessExpression) + { + return null; + } + + public virtual object Visit (BaseThis baseAccessExpression) + { + return null; + } + + public virtual object Visit (StackAlloc stackAllocExpression) + { + return null; + } + + public virtual object Visit (SimpleAssign simpleAssign) + { + return null; + } + + public virtual object Visit (CompoundAssign compoundAssign) + { + return null; + } + + public virtual object Visit (TypeExpression typeExpression) + { + return null; + } + + public virtual object Visit (AnonymousMethodExpression anonymousMethodExpression) + { + return null; + } + + public virtual object Visit (LambdaExpression lambdaExpression) + { + return null; + } + + public virtual object Visit (ConstInitializer constInitializer) + { + return null; + } + + public virtual object Visit (ArrayInitializer arrayInitializer) + { + return null; + } + + public virtual object Visit (Linq.QueryExpression queryExpression) + { + return null; + } + + public virtual object Visit (Linq.QueryStartClause queryExpression) + { + return null; + } + + public virtual object Visit (Linq.SelectMany selectMany) + { + return null; + } + + public virtual object Visit (Linq.Select select) + { + return null; + } + + public virtual object Visit (Linq.GroupBy groupBy) + { + return null; + } + + public virtual object Visit (Linq.Let let) + { + return null; + } + + public virtual object Visit (Linq.Where where) + { + return null; + } + + public virtual object Visit (Linq.Join join) + { + return null; + } + + public virtual object Visit (Linq.GroupJoin groupJoin) + { + return null; + } + + public virtual object Visit (Linq.OrderByAscending orderByAscending) + { + return null; + } + + public virtual object Visit (Linq.OrderByDescending orderByDescending) + { + return null; + } + + public virtual object Visit (Linq.ThenByAscending thenByAscending) + { + return null; + } + + public virtual object Visit (Linq.ThenByDescending thenByDescending) + { + return null; + } + + // undocumented expressions + public virtual object Visit (RefValueExpr refValueExpr) + { + return null; + } + + public virtual object Visit (RefTypeExpr refTypeExpr) + { + return null; + } + + public virtual object Visit (MakeRefExpr makeRefExpr) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output new file mode 100644 index 0000000000..a545cab253 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output @@ -0,0 +1,31920 @@ + 0 $accept : compilation_unit $end + + 1 compilation_unit : outer_declarations opt_EOF + 2 | outer_declarations global_attributes opt_EOF + 3 | global_attributes opt_EOF + 4 | opt_EOF + + 5 $$1 : + + 6 compilation_unit : interactive_parsing $$1 opt_EOF + + 7 opt_EOF : + 8 | EOF + + 9 outer_declarations : outer_declaration + 10 | outer_declarations outer_declaration + + 11 outer_declaration : extern_alias_directive + 12 | using_directive + 13 | namespace_member_declaration + + 14 extern_alias_directives : extern_alias_directive + 15 | extern_alias_directives extern_alias_directive + + 16 extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON + 17 | EXTERN_ALIAS error + + 18 using_directives : using_directive + 19 | using_directives using_directive + + 20 using_directive : using_alias_directive + 21 | using_namespace_directive + + 22 using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON + 23 | USING error + + 24 using_namespace_directive : USING namespace_name SEMICOLON + + 25 $$2 : + + 26 namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon + + 27 qualified_identifier : IDENTIFIER + 28 | qualified_identifier DOT IDENTIFIER + 29 | error + + 30 opt_semicolon : + 31 | SEMICOLON + + 32 opt_comma : + 33 | COMMA + + 34 namespace_name : namespace_or_type_name + + 35 $$3 : + + 36 namespace_body : OPEN_BRACE $$3 namespace_body_body + + 37 namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations CLOSE_BRACE + + 38 $$4 : + + 39 namespace_body_body : error $$4 CLOSE_BRACE + 40 | opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations EOF + + 41 opt_using_directives : + 42 | using_directives + + 43 opt_extern_alias_directives : + 44 | extern_alias_directives + + 45 opt_namespace_member_declarations : + 46 | namespace_member_declarations + + 47 namespace_member_declarations : namespace_member_declaration + 48 | namespace_member_declarations namespace_member_declaration + + 49 namespace_member_declaration : type_declaration + 50 | namespace_declaration + 51 | field_declaration + 52 | method_declaration + + 53 type_declaration : class_declaration + 54 | struct_declaration + 55 | interface_declaration + 56 | enum_declaration + 57 | delegate_declaration + + 58 global_attributes : attribute_sections + + 59 opt_attributes : + 60 | attribute_sections + + 61 attribute_sections : attribute_section + 62 | attribute_sections attribute_section + + 63 attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET + 64 | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET + + 65 attribute_target_specifier : attribute_target COLON + + 66 attribute_target : IDENTIFIER + 67 | EVENT + 68 | RETURN + 69 | error + + 70 attribute_list : attribute + 71 | attribute_list COMMA attribute + + 72 $$5 : + + 73 attribute : attribute_name $$5 opt_attribute_arguments + + 74 attribute_name : namespace_or_type_name + + 75 opt_attribute_arguments : + 76 | OPEN_PARENS attribute_arguments CLOSE_PARENS + + 77 attribute_arguments : + 78 | positional_or_named_argument + 79 | named_attribute_argument + 80 | attribute_arguments COMMA positional_or_named_argument + 81 | attribute_arguments COMMA named_attribute_argument + + 82 positional_or_named_argument : expression + 83 | named_argument + + 84 $$6 : + + 85 named_attribute_argument : IDENTIFIER ASSIGN $$6 expression + + 86 named_argument : IDENTIFIER COLON opt_named_modifier expression + + 87 opt_named_modifier : + 88 | REF + 89 | OUT + + 90 opt_class_member_declarations : + 91 | class_member_declarations + + 92 class_member_declarations : class_member_declaration + 93 | class_member_declarations class_member_declaration + + 94 class_member_declaration : constant_declaration + 95 | field_declaration + 96 | method_declaration + 97 | property_declaration + 98 | event_declaration + 99 | indexer_declaration + 100 | operator_declaration + 101 | constructor_declaration + 102 | destructor_declaration + 103 | type_declaration + 104 | error + + 105 $$7 : + + 106 $$8 : + + 107 $$9 : + + 108 $$10 : + + 109 struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon + 110 | opt_attributes opt_modifiers opt_partial STRUCT error + + 111 $$11 : + + 112 struct_body : OPEN_BRACE $$11 opt_struct_member_declarations CLOSE_BRACE + + 113 opt_struct_member_declarations : + 114 | struct_member_declarations + + 115 struct_member_declarations : struct_member_declaration + 116 | struct_member_declarations struct_member_declaration + + 117 struct_member_declaration : constant_declaration + 118 | field_declaration + 119 | method_declaration + 120 | property_declaration + 121 | event_declaration + 122 | indexer_declaration + 123 | operator_declaration + 124 | constructor_declaration + 125 | type_declaration + 126 | destructor_declaration + + 127 $$12 : + + 128 constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON + + 129 opt_constant_declarators : + 130 | constant_declarators + + 131 constant_declarators : constant_declarator + 132 | constant_declarators constant_declarator + + 133 constant_declarator : COMMA IDENTIFIER constant_initializer + + 134 $$13 : + + 135 constant_initializer : ASSIGN $$13 constant_initializer_expr + 136 | error + + 137 constant_initializer_expr : constant_expression + 138 | array_initializer + + 139 $$14 : + + 140 field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON + + 141 $$15 : + + 142 field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON + 143 | opt_attributes opt_modifiers FIXED simple_type error SEMICOLON + + 144 opt_field_initializer : + + 145 $$16 : + + 146 opt_field_initializer : ASSIGN $$16 variable_initializer + + 147 opt_field_declarators : + 148 | field_declarators + + 149 field_declarators : field_declarator + 150 | field_declarators field_declarator + + 151 field_declarator : COMMA IDENTIFIER + + 152 $$17 : + + 153 field_declarator : COMMA IDENTIFIER ASSIGN $$17 variable_initializer + + 154 opt_fixed_field_declarators : + 155 | fixed_field_declarators + + 156 fixed_field_declarators : fixed_field_declarator + 157 | fixed_field_declarators fixed_field_declarator + + 158 fixed_field_declarator : COMMA IDENTIFIER fixed_field_size + + 159 $$18 : + + 160 fixed_field_size : OPEN_BRACKET $$18 expression CLOSE_BRACKET + 161 | OPEN_BRACKET error + + 162 local_variable_declarators : local_variable_declarator + 163 | local_variable_declarators COMMA local_variable_declarator + + 164 local_variable_declarator : IDENTIFIER ASSIGN local_variable_initializer + 165 | IDENTIFIER + 166 | IDENTIFIER variable_bad_array + + 167 local_variable_initializer : expression + 168 | array_initializer + 169 | STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET + 170 | ARGLIST + 171 | STACKALLOC simple_type + + 172 variable_bad_array : OPEN_BRACKET_EXPR opt_expression CLOSE_BRACKET + + 173 variable_initializer : expression + 174 | array_initializer + + 175 $$19 : + + 176 method_declaration : method_header $$19 method_body + + 177 $$20 : + + 178 $$21 : + + 179 method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses + + 180 $$22 : + + 181 $$23 : + + 182 method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses + 183 | opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + + 184 method_body : block + 185 | SEMICOLON + + 186 opt_formal_parameter_list : + 187 | formal_parameter_list + + 188 formal_parameter_list : fixed_parameters + 189 | fixed_parameters COMMA parameter_array + 190 | fixed_parameters COMMA arglist_modifier + 191 | parameter_array COMMA error + 192 | fixed_parameters COMMA parameter_array COMMA error + 193 | arglist_modifier COMMA error + 194 | fixed_parameters COMMA ARGLIST COMMA error + 195 | parameter_array + 196 | arglist_modifier + + 197 fixed_parameters : fixed_parameter + 198 | fixed_parameters COMMA fixed_parameter + + 199 fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER + 200 | opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + 201 | opt_attributes opt_parameter_modifier parameter_type error + + 202 $$24 : + + 203 fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression + + 204 opt_parameter_modifier : + 205 | parameter_modifiers + + 206 parameter_modifiers : parameter_modifier + 207 | parameter_modifiers parameter_modifier + + 208 parameter_modifier : REF + 209 | OUT + 210 | THIS + + 211 parameter_array : opt_attributes params_modifier type IDENTIFIER + 212 | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression + 213 | opt_attributes params_modifier type error + + 214 params_modifier : PARAMS + 215 | PARAMS parameter_modifier + 216 | PARAMS params_modifier + + 217 arglist_modifier : ARGLIST + + 218 $$25 : + + 219 $$26 : + + 220 $$27 : + + 221 property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE + + 222 $$28 : + + 223 $$29 : + + 224 $$30 : + + 225 indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE + + 226 accessor_declarations : get_accessor_declaration + 227 | get_accessor_declaration accessor_declarations + 228 | set_accessor_declaration + 229 | set_accessor_declaration accessor_declarations + 230 | error + + 231 $$31 : + + 232 get_accessor_declaration : opt_attributes opt_modifiers GET $$31 accessor_body + + 233 $$32 : + + 234 set_accessor_declaration : opt_attributes opt_modifiers SET $$32 accessor_body + + 235 accessor_body : block + 236 | SEMICOLON + 237 | error + + 238 $$33 : + + 239 $$34 : + + 240 $$35 : + + 241 $$36 : + + 242 interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon + 243 | opt_attributes opt_modifiers opt_partial INTERFACE error + + 244 opt_interface_member_declarations : + 245 | interface_member_declarations + + 246 interface_member_declarations : interface_member_declaration + 247 | interface_member_declarations interface_member_declaration + + 248 interface_member_declaration : constant_declaration + 249 | field_declaration + 250 | method_declaration + 251 | property_declaration + 252 | event_declaration + 253 | indexer_declaration + 254 | operator_declaration + 255 | constructor_declaration + 256 | type_declaration + + 257 $$37 : + + 258 operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 operator_body + + 259 operator_body : block + 260 | SEMICOLON + + 261 operator_type : type_expression_or_array + 262 | VOID + + 263 $$38 : + + 264 operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS + 265 | conversion_operator_declarator + + 266 overloadable_operator : BANG + 267 | TILDE + 268 | OP_INC + 269 | OP_DEC + 270 | TRUE + 271 | FALSE + 272 | PLUS + 273 | MINUS + 274 | STAR + 275 | DIV + 276 | PERCENT + 277 | BITWISE_AND + 278 | BITWISE_OR + 279 | CARRET + 280 | OP_SHIFT_LEFT + 281 | OP_SHIFT_RIGHT + 282 | OP_EQ + 283 | OP_NE + 284 | OP_GT + 285 | OP_LT + 286 | OP_GE + 287 | OP_LE + + 288 $$39 : + + 289 conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS + + 290 $$40 : + + 291 conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS + 292 | IMPLICIT error + 293 | EXPLICIT error + + 294 constructor_declaration : constructor_declarator constructor_body + + 295 $$41 : + + 296 $$42 : + + 297 constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer + + 298 constructor_body : block_prepared + 299 | SEMICOLON + + 300 opt_constructor_initializer : + 301 | constructor_initializer + + 302 $$43 : + + 303 constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS + + 304 $$44 : + + 305 constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS + 306 | COLON error + + 307 $$45 : + + 308 destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body + + 309 $$46 : + + 310 event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON + + 311 $$47 : + + 312 $$48 : + + 313 event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE + + 314 opt_event_initializer : + + 315 $$49 : + + 316 opt_event_initializer : ASSIGN $$49 event_variable_initializer + + 317 opt_event_declarators : + 318 | event_declarators + + 319 event_declarators : event_declarator + 320 | event_declarators event_declarator + + 321 event_declarator : COMMA IDENTIFIER + + 322 $$50 : + + 323 event_declarator : COMMA IDENTIFIER ASSIGN $$50 event_variable_initializer + + 324 $$51 : + + 325 event_variable_initializer : $$51 variable_initializer + + 326 event_accessor_declarations : add_accessor_declaration remove_accessor_declaration + 327 | remove_accessor_declaration add_accessor_declaration + 328 | add_accessor_declaration + 329 | remove_accessor_declaration + 330 | error + + 331 $$52 : + + 332 add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 event_accessor_block + + 333 $$53 : + + 334 remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 event_accessor_block + + 335 event_accessor_block : opt_semicolon + 336 | block + + 337 $$54 : + + 338 $$55 : + + 339 $$56 : + + 340 enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon + + 341 opt_enum_base : + 342 | COLON type + 343 | COLON error + + 344 opt_enum_member_declarations : + 345 | enum_member_declarations + 346 | enum_member_declarations COMMA + + 347 enum_member_declarations : enum_member_declaration + 348 | enum_member_declarations COMMA enum_member_declaration + + 349 enum_member_declaration : opt_attributes IDENTIFIER + + 350 $$57 : + + 351 enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN constant_expression + + 352 $$58 : + + 353 $$59 : + + 354 $$60 : + + 355 delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON + + 356 opt_nullable : + 357 | INTERR_NULLABLE + + 358 namespace_or_type_name : member_name + 359 | qualified_alias_member IDENTIFIER opt_type_argument_list + + 360 member_name : type_name + 361 | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list + + 362 type_name : IDENTIFIER opt_type_argument_list + + 363 opt_type_argument_list : + 364 | OP_GENERICS_LT type_arguments OP_GENERICS_GT + 365 | OP_GENERICS_LT error + + 366 type_arguments : type + 367 | type_arguments COMMA type + + 368 $$61 : + + 369 type_declaration_name : IDENTIFIER $$61 opt_type_parameter_list + + 370 member_declaration_name : method_declaration_name + + 371 method_declaration_name : type_declaration_name + 372 | explicit_interface IDENTIFIER opt_type_parameter_list + + 373 indexer_declaration_name : THIS + 374 | explicit_interface THIS + + 375 explicit_interface : IDENTIFIER opt_type_argument_list DOT + 376 | qualified_alias_member IDENTIFIER opt_type_argument_list DOT + 377 | explicit_interface IDENTIFIER opt_type_argument_list DOT + + 378 opt_type_parameter_list : + 379 | OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT + + 380 type_parameters : type_parameter + 381 | type_parameters COMMA type_parameter + + 382 type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER + 383 | error + + 384 type_and_void : type_expression_or_array + 385 | VOID + + 386 member_type : type_and_void + + 387 type : type_expression_or_array + 388 | VOID + + 389 simple_type : type_expression + 390 | VOID + + 391 parameter_type : type_expression_or_array + 392 | VOID + + 393 type_expression_or_array : type_expression + 394 | type_expression rank_specifiers + + 395 type_expression : namespace_or_type_name opt_nullable + 396 | builtin_types opt_nullable + 397 | type_expression STAR + 398 | VOID STAR + + 399 type_list : base_type_name + 400 | type_list COMMA base_type_name + + 401 base_type_name : type + 402 | error + + 403 builtin_types : OBJECT + 404 | STRING + 405 | BOOL + 406 | DECIMAL + 407 | FLOAT + 408 | DOUBLE + 409 | integral_type + + 410 integral_type : SBYTE + 411 | BYTE + 412 | SHORT + 413 | USHORT + 414 | INT + 415 | UINT + 416 | LONG + 417 | ULONG + 418 | CHAR + + 419 primary_expression : primary_expression_no_array_creation + 420 | array_creation_expression + + 421 primary_expression_no_array_creation : literal + 422 | IDENTIFIER opt_type_argument_list + 423 | IDENTIFIER GENERATE_COMPLETION + 424 | parenthesized_expression + 425 | default_value_expression + 426 | member_access + 427 | invocation_expression + 428 | element_access + 429 | this_access + 430 | base_access + 431 | post_increment_expression + 432 | post_decrement_expression + 433 | object_or_delegate_creation_expression + 434 | anonymous_type_expression + 435 | typeof_expression + 436 | sizeof_expression + 437 | checked_expression + 438 | unchecked_expression + 439 | pointer_member_access + 440 | anonymous_method_expression + + 441 literal : boolean_literal + 442 | LITERAL + 443 | NULL + + 444 boolean_literal : TRUE + 445 | FALSE + + 446 open_parens_any : OPEN_PARENS + 447 | OPEN_PARENS_CAST + + 448 close_parens : CLOSE_PARENS + 449 | COMPLETE_COMPLETION + + 450 parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS + 451 | OPEN_PARENS expression COMPLETE_COMPLETION + + 452 member_access : primary_expression DOT IDENTIFIER opt_type_argument_list + 453 | builtin_types DOT IDENTIFIER opt_type_argument_list + 454 | BASE DOT IDENTIFIER opt_type_argument_list + 455 | qualified_alias_member IDENTIFIER opt_type_argument_list + 456 | primary_expression DOT GENERATE_COMPLETION + 457 | primary_expression DOT IDENTIFIER GENERATE_COMPLETION + 458 | builtin_types DOT GENERATE_COMPLETION + 459 | builtin_types DOT IDENTIFIER GENERATE_COMPLETION + + 460 invocation_expression : primary_expression open_parens_any opt_argument_list close_parens + + 461 opt_object_or_collection_initializer : + 462 | object_or_collection_initializer + + 463 object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion + 464 | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE + + 465 opt_member_initializer_list : + 466 | member_initializer_list + + 467 member_initializer_list : member_initializer + 468 | member_initializer_list COMMA member_initializer + 469 | member_initializer_list error + + 470 member_initializer : IDENTIFIER ASSIGN initializer_value + 471 | GENERATE_COMPLETION + 472 | non_assignment_expression opt_COMPLETE_COMPLETION + 473 | OPEN_BRACE expression_list CLOSE_BRACE + 474 | OPEN_BRACE CLOSE_BRACE + + 475 initializer_value : expression + 476 | object_or_collection_initializer + + 477 opt_argument_list : + 478 | argument_list + + 479 argument_list : argument_or_named_argument + 480 | argument_list COMMA argument + 481 | argument_list COMMA named_argument + 482 | argument_list COMMA + 483 | COMMA error + + 484 argument : expression + 485 | non_simple_argument + + 486 argument_or_named_argument : argument + 487 | named_argument + + 488 non_simple_argument : REF variable_reference + 489 | OUT variable_reference + 490 | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS + 491 | ARGLIST OPEN_PARENS CLOSE_PARENS + 492 | ARGLIST + + 493 variable_reference : expression + + 494 element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + + 495 expression_list : expression + 496 | expression_list COMMA expression + 497 | expression_list error + + 498 expression_list_arguments : expression_list_argument + 499 | expression_list_arguments COMMA expression_list_argument + + 500 expression_list_argument : expression + 501 | named_argument + + 502 this_access : THIS + + 503 base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + 504 | BASE OPEN_BRACKET error + + 505 post_increment_expression : primary_expression OP_INC + + 506 post_decrement_expression : primary_expression OP_DEC + + 507 object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer + 508 | NEW new_expr_type object_or_collection_initializer + + 509 array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer + 510 | NEW new_expr_type rank_specifiers opt_array_initializer + 511 | NEW rank_specifiers array_initializer + 512 | NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET + 513 | NEW new_expr_type error + + 514 $$62 : + + 515 new_expr_type : $$62 simple_type + + 516 anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE + + 517 anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt + 518 | anonymous_type_parameters COMMA + + 519 anonymous_type_parameters_opt : + 520 | anonymous_type_parameters + + 521 anonymous_type_parameters : anonymous_type_parameter + 522 | anonymous_type_parameters COMMA anonymous_type_parameter + + 523 anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer + 524 | IDENTIFIER + 525 | member_access + 526 | error + + 527 opt_rank_specifier : + 528 | rank_specifiers + + 529 opt_rank_specifier_or_nullable : opt_nullable + 530 | opt_nullable rank_specifiers + + 531 rank_specifiers : rank_specifier + 532 | rank_specifier rank_specifiers + + 533 rank_specifier : OPEN_BRACKET CLOSE_BRACKET + 534 | OPEN_BRACKET dim_separators CLOSE_BRACKET + + 535 dim_separators : COMMA + 536 | dim_separators COMMA + + 537 opt_array_initializer : + 538 | array_initializer + + 539 array_initializer : OPEN_BRACE CLOSE_BRACE + 540 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE + + 541 variable_initializer_list : variable_initializer + 542 | variable_initializer_list COMMA variable_initializer + 543 | error + + 544 $$63 : + + 545 typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression CLOSE_PARENS + + 546 typeof_type_expression : type_and_void + 547 | unbound_type_name + 548 | error + + 549 unbound_type_name : IDENTIFIER generic_dimension + 550 | qualified_alias_member IDENTIFIER generic_dimension + 551 | unbound_type_name DOT IDENTIFIER + 552 | unbound_type_name DOT IDENTIFIER generic_dimension + 553 | namespace_or_type_name DOT IDENTIFIER generic_dimension + + 554 generic_dimension : GENERIC_DIMENSION + + 555 qualified_alias_member : IDENTIFIER DOUBLE_COLON + + 556 sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS + + 557 checked_expression : CHECKED open_parens_any expression CLOSE_PARENS + + 558 unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS + + 559 pointer_member_access : primary_expression OP_PTR IDENTIFIER + + 560 $$64 : + + 561 anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 block + + 562 opt_anonymous_method_signature : + 563 | anonymous_method_signature + + 564 $$65 : + + 565 anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list CLOSE_PARENS + + 566 default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS + + 567 unary_expression : primary_expression + 568 | BANG prefixed_unary_expression + 569 | TILDE prefixed_unary_expression + 570 | cast_expression + + 571 cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression + 572 | OPEN_PARENS builtin_types CLOSE_PARENS prefixed_unary_expression + + 573 prefixed_unary_expression : unary_expression + 574 | PLUS prefixed_unary_expression + 575 | MINUS prefixed_unary_expression + 576 | OP_INC prefixed_unary_expression + 577 | OP_DEC prefixed_unary_expression + 578 | STAR prefixed_unary_expression + 579 | BITWISE_AND prefixed_unary_expression + + 580 multiplicative_expression : prefixed_unary_expression + 581 | multiplicative_expression STAR prefixed_unary_expression + 582 | multiplicative_expression DIV prefixed_unary_expression + 583 | multiplicative_expression PERCENT prefixed_unary_expression + + 584 additive_expression : multiplicative_expression + 585 | additive_expression PLUS multiplicative_expression + 586 | additive_expression MINUS multiplicative_expression + 587 | parenthesized_expression MINUS multiplicative_expression + 588 | additive_expression AS type + 589 | additive_expression IS type + + 590 shift_expression : additive_expression + 591 | shift_expression OP_SHIFT_LEFT additive_expression + 592 | shift_expression OP_SHIFT_RIGHT additive_expression + + 593 relational_expression : shift_expression + 594 | relational_expression OP_LT shift_expression + 595 | relational_expression OP_GT shift_expression + 596 | relational_expression OP_LE shift_expression + 597 | relational_expression OP_GE shift_expression + + 598 equality_expression : relational_expression + 599 | equality_expression OP_EQ relational_expression + 600 | equality_expression OP_NE relational_expression + + 601 and_expression : equality_expression + 602 | and_expression BITWISE_AND equality_expression + + 603 exclusive_or_expression : and_expression + 604 | exclusive_or_expression CARRET and_expression + + 605 inclusive_or_expression : exclusive_or_expression + 606 | inclusive_or_expression BITWISE_OR exclusive_or_expression + + 607 conditional_and_expression : inclusive_or_expression + 608 | conditional_and_expression OP_AND inclusive_or_expression + + 609 conditional_or_expression : conditional_and_expression + 610 | conditional_or_expression OP_OR conditional_and_expression + + 611 null_coalescing_expression : conditional_or_expression + 612 | conditional_or_expression OP_COALESCING null_coalescing_expression + + 613 conditional_expression : null_coalescing_expression + 614 | null_coalescing_expression INTERR expression COLON expression + + 615 assignment_expression : prefixed_unary_expression ASSIGN expression + 616 | prefixed_unary_expression OP_MULT_ASSIGN expression + 617 | prefixed_unary_expression OP_DIV_ASSIGN expression + 618 | prefixed_unary_expression OP_MOD_ASSIGN expression + 619 | prefixed_unary_expression OP_ADD_ASSIGN expression + 620 | prefixed_unary_expression OP_SUB_ASSIGN expression + 621 | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression + 622 | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression + 623 | prefixed_unary_expression OP_AND_ASSIGN expression + 624 | prefixed_unary_expression OP_OR_ASSIGN expression + 625 | prefixed_unary_expression OP_XOR_ASSIGN expression + + 626 lambda_parameter_list : lambda_parameter + 627 | lambda_parameter_list COMMA lambda_parameter + + 628 lambda_parameter : parameter_modifier parameter_type IDENTIFIER + 629 | parameter_type IDENTIFIER + 630 | IDENTIFIER + + 631 opt_lambda_parameter_list : + 632 | lambda_parameter_list + + 633 $$66 : + + 634 lambda_expression_body : $$66 expression + 635 | block + + 636 $$67 : + + 637 lambda_expression : IDENTIFIER ARROW $$67 lambda_expression_body + + 638 $$68 : + + 639 $$69 : + + 640 lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body + + 641 expression : assignment_expression + 642 | non_assignment_expression + + 643 non_assignment_expression : conditional_expression + 644 | lambda_expression + 645 | query_expression + + 646 constant_expression : expression + + 647 boolean_expression : expression + + 648 $$70 : + + 649 $$71 : + + 650 $$72 : + + 651 $$73 : + + 652 class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon + + 653 opt_partial : + 654 | PARTIAL + + 655 opt_modifiers : + 656 | modifiers + + 657 modifiers : modifier + 658 | modifiers modifier + + 659 modifier : NEW + 660 | PUBLIC + 661 | PROTECTED + 662 | INTERNAL + 663 | PRIVATE + 664 | ABSTRACT + 665 | SEALED + 666 | STATIC + 667 | READONLY + 668 | VIRTUAL + 669 | OVERRIDE + 670 | EXTERN + 671 | VOLATILE + 672 | UNSAFE + + 673 opt_class_base : + 674 | COLON type_list + + 675 opt_type_parameter_constraints_clauses : + 676 | type_parameter_constraints_clauses + + 677 type_parameter_constraints_clauses : type_parameter_constraints_clause + 678 | type_parameter_constraints_clauses type_parameter_constraints_clause + + 679 type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints + + 680 type_parameter_constraints : type_parameter_constraint + 681 | type_parameter_constraints COMMA type_parameter_constraint + + 682 type_parameter_constraint : type + 683 | NEW OPEN_PARENS CLOSE_PARENS + 684 | CLASS + 685 | STRUCT + + 686 opt_type_parameter_variance : + 687 | type_parameter_variance + + 688 type_parameter_variance : OUT + 689 | IN + + 690 $$74 : + + 691 block : OPEN_BRACE $$74 opt_statement_list block_end + + 692 block_end : CLOSE_BRACE + 693 | COMPLETE_COMPLETION + + 694 $$75 : + + 695 block_prepared : OPEN_BRACE $$75 opt_statement_list CLOSE_BRACE + + 696 opt_statement_list : + 697 | statement_list + + 698 statement_list : statement + 699 | statement_list statement + + 700 statement : declaration_statement + 701 | valid_declaration_statement + 702 | labeled_statement + + 703 interactive_statement_list : interactive_statement + 704 | interactive_statement_list interactive_statement + + 705 interactive_statement : declaration_statement + 706 | interactive_valid_declaration_statement + 707 | labeled_statement + + 708 valid_declaration_statement : block + 709 | empty_statement + 710 | expression_statement + 711 | selection_statement + 712 | iteration_statement + 713 | jump_statement + 714 | try_statement + 715 | checked_statement + 716 | unchecked_statement + 717 | lock_statement + 718 | using_statement + 719 | unsafe_statement + 720 | fixed_statement + + 721 interactive_valid_declaration_statement : block + 722 | empty_statement + 723 | interactive_expression_statement + 724 | selection_statement + 725 | iteration_statement + 726 | jump_statement + 727 | try_statement + 728 | checked_statement + 729 | unchecked_statement + 730 | lock_statement + 731 | using_statement + 732 | unsafe_statement + 733 | fixed_statement + + 734 embedded_statement : valid_declaration_statement + 735 | declaration_statement + 736 | labeled_statement + + 737 empty_statement : SEMICOLON + + 738 $$76 : + + 739 labeled_statement : IDENTIFIER COLON $$76 statement + + 740 declaration_statement : local_variable_declaration SEMICOLON + 741 | local_constant_declaration SEMICOLON + + 742 variable_type : primary_expression_no_array_creation opt_rank_specifier_or_nullable + 743 | builtin_types opt_rank_specifier_or_nullable + 744 | VOID opt_rank_specifier + + 745 local_variable_pointer_type : primary_expression_no_array_creation STAR + 746 | builtin_types STAR + 747 | VOID STAR + 748 | local_variable_pointer_type STAR + + 749 local_variable_type : variable_type + 750 | local_variable_pointer_type opt_rank_specifier + + 751 local_variable_declaration : local_variable_type local_variable_declarators + + 752 local_constant_declaration : CONST variable_type local_constant_declarators + + 753 local_constant_declarators : local_constant_declarator + 754 | local_constant_declarators COMMA local_constant_declarator + + 755 local_constant_declarator : IDENTIFIER ASSIGN constant_initializer_expr + 756 | IDENTIFIER error + + 757 expression_statement : statement_expression SEMICOLON + 758 | statement_expression COMPLETE_COMPLETION + + 759 interactive_expression_statement : interactive_statement_expression SEMICOLON + 760 | interactive_statement_expression COMPLETE_COMPLETION + + 761 statement_expression : expression + 762 | error + + 763 interactive_statement_expression : expression + 764 | error + + 765 selection_statement : if_statement + 766 | switch_statement + + 767 if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement + 768 | IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement + + 769 $$77 : + + 770 switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE + + 771 opt_switch_sections : + 772 | switch_sections + + 773 switch_sections : switch_section + 774 | switch_sections switch_section + + 775 $$78 : + + 776 switch_section : switch_labels $$78 statement_list + + 777 switch_labels : switch_label + 778 | switch_labels switch_label + + 779 switch_label : CASE constant_expression COLON + 780 | DEFAULT_COLON + + 781 iteration_statement : while_statement + 782 | do_statement + 783 | for_statement + 784 | foreach_statement + + 785 while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement + + 786 do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON + + 787 $$79 : + + 788 for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement + + 789 opt_for_initializer : + 790 | for_initializer + + 791 for_initializer : local_variable_declaration + 792 | statement_expression_list + + 793 opt_for_condition : + 794 | boolean_expression + + 795 opt_for_iterator : + 796 | for_iterator + + 797 for_iterator : statement_expression_list + + 798 statement_expression_list : statement_expression + 799 | statement_expression_list COMMA statement_expression + + 800 foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS + + 801 $$80 : + + 802 foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement + + 803 jump_statement : break_statement + 804 | continue_statement + 805 | goto_statement + 806 | return_statement + 807 | throw_statement + 808 | yield_statement + + 809 break_statement : BREAK SEMICOLON + + 810 continue_statement : CONTINUE SEMICOLON + + 811 goto_statement : GOTO IDENTIFIER SEMICOLON + 812 | GOTO CASE constant_expression SEMICOLON + 813 | GOTO DEFAULT SEMICOLON + + 814 return_statement : RETURN opt_expression SEMICOLON + + 815 throw_statement : THROW opt_expression SEMICOLON + + 816 yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON + 817 | IDENTIFIER BREAK SEMICOLON + + 818 opt_expression : + 819 | expression + + 820 try_statement : TRY block catch_clauses + 821 | TRY block FINALLY block + 822 | TRY block catch_clauses FINALLY block + 823 | TRY block error + + 824 catch_clauses : catch_clause + 825 | catch_clauses catch_clause + + 826 opt_identifier : + 827 | IDENTIFIER + + 828 $$81 : + + 829 catch_clause : CATCH opt_catch_args $$81 block + + 830 opt_catch_args : + 831 | catch_args + + 832 catch_args : open_parens_any type opt_identifier CLOSE_PARENS + 833 | open_parens_any CLOSE_PARENS + + 834 checked_statement : CHECKED block + + 835 unchecked_statement : UNCHECKED block + + 836 $$82 : + + 837 unsafe_statement : UNSAFE $$82 block + + 838 $$83 : + + 839 fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement + + 840 fixed_pointer_declarators : fixed_pointer_declarator + 841 | fixed_pointer_declarators COMMA fixed_pointer_declarator + + 842 fixed_pointer_declarator : IDENTIFIER ASSIGN expression + 843 | IDENTIFIER + + 844 lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement + + 845 $$84 : + + 846 using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement + + 847 $$85 : + + 848 using_statement : USING open_parens_any expression CLOSE_PARENS $$85 embedded_statement + + 849 query_expression : first_from_clause query_body + 850 | nested_from_clause query_body + 851 | first_from_clause COMPLETE_COMPLETION + 852 | nested_from_clause COMPLETE_COMPLETION + + 853 first_from_clause : FROM_FIRST IDENTIFIER IN expression + 854 | FROM_FIRST type IDENTIFIER IN expression + + 855 nested_from_clause : FROM IDENTIFIER IN expression + 856 | FROM type IDENTIFIER IN expression + + 857 $$86 : + + 858 from_clause : FROM IDENTIFIER IN $$86 expression + + 859 $$87 : + + 860 from_clause : FROM type IDENTIFIER IN $$87 expression + + 861 query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation + 862 | opt_query_body_clauses COMPLETE_COMPLETION + + 863 $$88 : + + 864 select_or_group_clause : SELECT $$88 expression + + 865 $$89 : + + 866 $$90 : + + 867 select_or_group_clause : GROUP $$89 expression $$90 BY expression + + 868 opt_query_body_clauses : + 869 | query_body_clauses + + 870 query_body_clauses : query_body_clause + 871 | query_body_clauses query_body_clause + + 872 query_body_clause : from_clause + 873 | let_clause + 874 | where_clause + 875 | join_clause + 876 | orderby_clause + + 877 $$91 : + + 878 let_clause : LET IDENTIFIER ASSIGN $$91 expression + + 879 $$92 : + + 880 where_clause : WHERE $$92 boolean_expression + + 881 $$93 : + + 882 $$94 : + + 883 $$95 : + + 884 join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into + + 885 $$96 : + + 886 $$97 : + + 887 $$98 : + + 888 join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into + + 889 opt_join_into : + 890 | INTO IDENTIFIER + + 891 $$99 : + + 892 orderby_clause : ORDERBY $$99 orderings + + 893 orderings : order_by + + 894 $$100 : + + 895 orderings : order_by COMMA $$100 orderings_then_by + + 896 orderings_then_by : then_by + + 897 $$101 : + + 898 orderings_then_by : orderings_then_by COMMA $$101 then_by + + 899 order_by : expression + 900 | expression ASCENDING + 901 | expression DESCENDING + + 902 then_by : expression + 903 | expression ASCENDING + 904 | expression DESCENDING + + 905 opt_query_continuation : + + 906 $$102 : + + 907 opt_query_continuation : INTO IDENTIFIER $$102 query_body + + 908 interactive_parsing : EVAL_STATEMENT_PARSER EOF + 909 | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives + + 910 $$103 : + + 911 interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list opt_COMPLETE_COMPLETION + + 912 $$104 : + + 913 interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 interactive_compilation_unit + + 914 interactive_compilation_unit : outer_declarations + 915 | outer_declarations global_attributes + 916 | global_attributes + 917 | + + 918 opt_COMPLETE_COMPLETION : + 919 | COMPLETE_COMPLETION + + 920 close_brace_or_complete_completion : CLOSE_BRACE + 921 | COMPLETE_COMPLETION + +state 0 + $accept : . compilation_unit $end (0) + opt_EOF : . (7) + opt_attributes : . (59) + + EOF shift 1 + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + EVAL_STATEMENT_PARSER shift 5 + EVAL_COMPILATION_UNIT_PARSER shift 6 + EVAL_USING_DECLARATIONS_UNIT_PARSER shift 7 + $end reduce 7 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + compilation_unit goto 8 + outer_declarations goto 9 + opt_EOF goto 10 + global_attributes goto 11 + interactive_parsing goto 12 + outer_declaration goto 13 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 1 + opt_EOF : EOF . (8) + + . reduce 8 + + +state 2 + using_alias_directive : USING . IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON (22) + using_alias_directive : USING . error (23) + using_namespace_directive : USING . namespace_name SEMICOLON (24) + + error shift 32 + IDENTIFIER shift 33 + . error + + namespace_or_type_name goto 34 + namespace_name goto 35 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 3 + extern_alias_directive : EXTERN_ALIAS . IDENTIFIER IDENTIFIER SEMICOLON (16) + extern_alias_directive : EXTERN_ALIAS . error (17) + + error shift 39 + IDENTIFIER shift 40 + . error + + +state 4 + attribute_section : OPEN_BRACKET . attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET (63) + attribute_section : OPEN_BRACKET . attribute_list opt_comma CLOSE_BRACKET (64) + + error shift 41 + EVENT shift 42 + RETURN shift 43 + IDENTIFIER shift 44 + . error + + namespace_or_type_name goto 45 + attribute_target_specifier goto 46 + attribute_list goto 47 + attribute_target goto 48 + attribute goto 49 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 5 + interactive_parsing : EVAL_STATEMENT_PARSER . EOF (908) + interactive_parsing : EVAL_STATEMENT_PARSER . $$103 interactive_statement_list opt_COMPLETE_COMPLETION (911) + $$103 : . (910) + + EOF shift 51 + error reduce 910 + BASE reduce 910 + BOOL reduce 910 + BREAK reduce 910 + BYTE reduce 910 + CHAR reduce 910 + CHECKED reduce 910 + CONST reduce 910 + CONTINUE reduce 910 + DECIMAL reduce 910 + DEFAULT reduce 910 + DELEGATE reduce 910 + DO reduce 910 + DOUBLE reduce 910 + FALSE reduce 910 + FIXED reduce 910 + FLOAT reduce 910 + FOR reduce 910 + FOREACH reduce 910 + GOTO reduce 910 + IF reduce 910 + INT reduce 910 + LOCK reduce 910 + LONG reduce 910 + NEW reduce 910 + NULL reduce 910 + OBJECT reduce 910 + RETURN reduce 910 + SBYTE reduce 910 + SHORT reduce 910 + SIZEOF reduce 910 + STRING reduce 910 + SWITCH reduce 910 + THIS reduce 910 + THROW reduce 910 + TRUE reduce 910 + TRY reduce 910 + TYPEOF reduce 910 + UINT reduce 910 + ULONG reduce 910 + UNCHECKED reduce 910 + UNSAFE reduce 910 + USHORT reduce 910 + USING reduce 910 + VOID reduce 910 + WHILE reduce 910 + FROM reduce 910 + FROM_FIRST reduce 910 + OPEN_BRACE reduce 910 + OPEN_PARENS reduce 910 + SEMICOLON reduce 910 + TILDE reduce 910 + PLUS reduce 910 + MINUS reduce 910 + BANG reduce 910 + BITWISE_AND reduce 910 + STAR reduce 910 + OP_INC reduce 910 + OP_DEC reduce 910 + LITERAL reduce 910 + IDENTIFIER reduce 910 + OPEN_PARENS_LAMBDA reduce 910 + OPEN_PARENS_CAST reduce 910 + + $$103 goto 52 + + +state 6 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER . $$104 interactive_compilation_unit (913) + $$104 : . (912) + + . reduce 912 + + $$104 goto 53 + + +state 7 + interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER . using_directives (909) + + USING shift 2 + . error + + using_directive goto 54 + using_directives goto 55 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 8 + $accept : compilation_unit . $end (0) + + $end accept + + +state 9 + compilation_unit : outer_declarations . opt_EOF (1) + compilation_unit : outer_declarations . global_attributes opt_EOF (2) + outer_declarations : outer_declarations . outer_declaration (10) + opt_EOF : . (7) + opt_attributes : . (59) + + EOF shift 1 + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 7 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + opt_EOF goto 56 + global_attributes goto 57 + outer_declaration goto 58 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 10 + compilation_unit : opt_EOF . (4) + + . reduce 4 + + +state 11 + compilation_unit : global_attributes . opt_EOF (3) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 59 + + +state 12 + compilation_unit : interactive_parsing . $$1 opt_EOF (6) + $$1 : . (5) + + . reduce 5 + + $$1 goto 60 + + +state 13 + outer_declarations : outer_declaration . (9) + + . reduce 9 + + +state 14 + outer_declaration : extern_alias_directive . (11) + + . reduce 11 + + +state 15 + outer_declaration : using_directive . (12) + + . reduce 12 + + +state 16 + outer_declaration : namespace_member_declaration . (13) + + . reduce 13 + + +state 17 + using_directive : using_alias_directive . (20) + + . reduce 20 + + +state 18 + using_directive : using_namespace_directive . (21) + + . reduce 21 + + +state 19 + namespace_member_declaration : namespace_declaration . (50) + + . reduce 50 + + +state 20 + namespace_declaration : opt_attributes . NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon (26) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NAMESPACE shift 64 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 76 + modifiers goto 77 + modifier goto 78 + + +state 21 + namespace_member_declaration : type_declaration . (49) + + . reduce 49 + + +state 22 + namespace_member_declaration : field_declaration . (51) + + . reduce 51 + + +state 23 + namespace_member_declaration : method_declaration . (52) + + . reduce 52 + + +state 24 + type_declaration : class_declaration . (53) + + . reduce 53 + + +state 25 + type_declaration : struct_declaration . (54) + + . reduce 54 + + +state 26 + type_declaration : interface_declaration . (55) + + . reduce 55 + + +state 27 + type_declaration : enum_declaration . (56) + + . reduce 56 + + +state 28 + type_declaration : delegate_declaration . (57) + + . reduce 57 + + +state 29 + global_attributes : attribute_sections . (58) + opt_attributes : attribute_sections . (60) + attribute_sections : attribute_sections . attribute_section (62) + + OPEN_BRACKET shift 4 + $end reduce 58 + EOF reduce 58 + ABSTRACT reduce 60 + BOOL reduce 60 + BYTE reduce 60 + CHAR reduce 60 + CLASS reduce 60 + DECIMAL reduce 60 + DELEGATE reduce 60 + DOUBLE reduce 60 + ENUM reduce 60 + EXTERN reduce 60 + FIXED reduce 60 + FLOAT reduce 60 + INT reduce 60 + INTERFACE reduce 60 + INTERNAL reduce 60 + LONG reduce 60 + NAMESPACE reduce 60 + NEW reduce 60 + OBJECT reduce 60 + OVERRIDE reduce 60 + PRIVATE reduce 60 + PROTECTED reduce 60 + PUBLIC reduce 60 + READONLY reduce 60 + SBYTE reduce 60 + SEALED reduce 60 + SHORT reduce 60 + STATIC reduce 60 + STRING reduce 60 + STRUCT reduce 60 + UINT reduce 60 + ULONG reduce 60 + UNSAFE reduce 60 + USHORT reduce 60 + VIRTUAL reduce 60 + VOID reduce 60 + VOLATILE reduce 60 + PARTIAL reduce 60 + IDENTIFIER reduce 60 + + attribute_section goto 79 + + +state 30 + attribute_sections : attribute_section . (61) + + . reduce 61 + + +state 31 + method_declaration : method_header . $$19 method_body (176) + $$19 : . (175) + + . reduce 175 + + $$19 goto 80 + + +state 32 + using_alias_directive : USING error . (23) + + . reduce 23 + + +state 33 + using_alias_directive : USING IDENTIFIER . ASSIGN namespace_or_type_name SEMICOLON (22) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + ASSIGN shift 82 + DOUBLE_COLON shift 83 + DOT reduce 363 + SEMICOLON reduce 363 + + opt_type_argument_list goto 84 + + +state 34 + namespace_name : namespace_or_type_name . (34) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + SEMICOLON reduce 34 + + +state 35 + using_namespace_directive : USING namespace_name . SEMICOLON (24) + + SEMICOLON shift 86 + . error + + +state 36 + namespace_or_type_name : member_name . (358) + + . reduce 358 + + +state 37 + namespace_or_type_name : qualified_alias_member . IDENTIFIER opt_type_argument_list (359) + + IDENTIFIER shift 87 + . error + + +state 38 + member_name : type_name . (360) + + . reduce 360 + + +state 39 + extern_alias_directive : EXTERN_ALIAS error . (17) + + . reduce 17 + + +state 40 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER . IDENTIFIER SEMICOLON (16) + + IDENTIFIER shift 88 + . error + + +state 41 + attribute_target : error . (69) + + . reduce 69 + + +state 42 + attribute_target : EVENT . (67) + + . reduce 67 + + +state 43 + attribute_target : RETURN . (68) + + . reduce 68 + + +state 44 + attribute_target : IDENTIFIER . (66) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 66 + + opt_type_argument_list goto 84 + + +state 45 + attribute_name : namespace_or_type_name . (74) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + CLOSE_BRACKET reduce 74 + OPEN_PARENS reduce 74 + COMMA reduce 74 + + +state 46 + attribute_section : OPEN_BRACKET attribute_target_specifier . attribute_list opt_comma CLOSE_BRACKET (63) + + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 45 + attribute_list goto 90 + attribute goto 49 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 47 + attribute_section : OPEN_BRACKET attribute_list . opt_comma CLOSE_BRACKET (64) + attribute_list : attribute_list . COMMA attribute (71) + opt_comma : . (32) + + COMMA shift 91 + CLOSE_BRACKET reduce 32 + + opt_comma goto 92 + + +state 48 + attribute_target_specifier : attribute_target . COLON (65) + + COLON shift 93 + . error + + +state 49 + attribute_list : attribute . (70) + + . reduce 70 + + +state 50 + attribute : attribute_name . $$5 opt_attribute_arguments (73) + $$5 : . (72) + + . reduce 72 + + $$5 goto 94 + + +state 51 + interactive_parsing : EVAL_STATEMENT_PARSER EOF . (908) + + . reduce 908 + + +state 52 + interactive_parsing : EVAL_STATEMENT_PARSER $$103 . interactive_statement_list opt_COMPLETE_COMPLETION (911) + + error shift 95 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 158 + block goto 159 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 204 + labeled_statement goto 205 + interactive_statement_list goto 206 + interactive_statement goto 207 + interactive_valid_declaration_statement goto 208 + empty_statement goto 209 + selection_statement goto 210 + iteration_statement goto 211 + jump_statement goto 212 + try_statement goto 213 + checked_statement goto 214 + unchecked_statement goto 215 + lock_statement goto 216 + using_statement goto 217 + unsafe_statement goto 218 + fixed_statement goto 219 + interactive_expression_statement goto 220 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + interactive_statement_expression goto 226 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 53 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 . interactive_compilation_unit (913) + opt_attributes : . (59) + interactive_compilation_unit : . (917) + + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 917 + EOF reduce 917 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + outer_declarations goto 241 + global_attributes goto 242 + outer_declaration goto 13 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + interactive_compilation_unit goto 243 + + +state 54 + using_directives : using_directive . (18) + + . reduce 18 + + +state 55 + using_directives : using_directives . using_directive (19) + interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives . (909) + + USING shift 2 + $end reduce 909 + EOF reduce 909 + + using_directive goto 244 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 56 + compilation_unit : outer_declarations opt_EOF . (1) + + . reduce 1 + + +state 57 + compilation_unit : outer_declarations global_attributes . opt_EOF (2) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 245 + + +state 58 + outer_declarations : outer_declarations outer_declaration . (10) + + . reduce 10 + + +state 59 + compilation_unit : global_attributes opt_EOF . (3) + + . reduce 3 + + +state 60 + compilation_unit : interactive_parsing $$1 . opt_EOF (6) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 246 + + +state 61 + modifier : ABSTRACT . (664) + + . reduce 664 + + +state 62 + modifier : EXTERN . (670) + + . reduce 670 + + +state 63 + modifier : INTERNAL . (662) + + . reduce 662 + + +state 64 + namespace_declaration : opt_attributes NAMESPACE . qualified_identifier $$2 namespace_body opt_semicolon (26) + + error shift 247 + IDENTIFIER shift 248 + . error + + qualified_identifier goto 249 + + +state 65 + modifier : NEW . (659) + + . reduce 659 + + +state 66 + modifier : OVERRIDE . (669) + + . reduce 669 + + +state 67 + modifier : PRIVATE . (663) + + . reduce 663 + + +state 68 + modifier : PROTECTED . (661) + + . reduce 661 + + +state 69 + modifier : PUBLIC . (660) + + . reduce 660 + + +state 70 + modifier : READONLY . (667) + + . reduce 667 + + +state 71 + modifier : SEALED . (665) + + . reduce 665 + + +state 72 + modifier : STATIC . (666) + + . reduce 666 + + +state 73 + modifier : UNSAFE . (672) + + . reduce 672 + + +state 74 + modifier : VIRTUAL . (668) + + . reduce 668 + + +state 75 + modifier : VOLATILE . (671) + + . reduce 671 + + +state 76 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + FIXED shift 252 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + PARTIAL shift 254 + IDENTIFIER shift 89 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 257 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 77 + opt_modifiers : modifiers . (656) + modifiers : modifiers . modifier (658) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 656 + BOOL reduce 656 + BYTE reduce 656 + CHAR reduce 656 + CLASS reduce 656 + CONST reduce 656 + DECIMAL reduce 656 + DELEGATE reduce 656 + DOUBLE reduce 656 + ENUM reduce 656 + EVENT reduce 656 + EXPLICIT reduce 656 + FIXED reduce 656 + FLOAT reduce 656 + IMPLICIT reduce 656 + INT reduce 656 + INTERFACE reduce 656 + LONG reduce 656 + OBJECT reduce 656 + REMOVE reduce 656 + SBYTE reduce 656 + SHORT reduce 656 + STRING reduce 656 + STRUCT reduce 656 + UINT reduce 656 + ULONG reduce 656 + USHORT reduce 656 + VOID reduce 656 + PARTIAL reduce 656 + GET reduce 656 + SET reduce 656 + TILDE reduce 656 + IDENTIFIER reduce 656 + + modifier goto 262 + + +state 78 + modifiers : modifier . (657) + + . reduce 657 + + +state 79 + attribute_sections : attribute_sections attribute_section . (62) + + . reduce 62 + + +state 80 + method_declaration : method_header $$19 . method_body (176) + + OPEN_BRACE shift 143 + SEMICOLON shift 263 + . error + + method_body goto 264 + block goto 265 + + +state 81 + opt_type_argument_list : OP_GENERICS_LT . type_arguments OP_GENERICS_GT (364) + opt_type_argument_list : OP_GENERICS_LT . error (365) + + error shift 266 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 268 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_arguments goto 270 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 82 + using_alias_directive : USING IDENTIFIER ASSIGN . namespace_or_type_name SEMICOLON (22) + + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 271 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 83 + qualified_alias_member : IDENTIFIER DOUBLE_COLON . (555) + + . reduce 555 + + +state 84 + type_name : IDENTIFIER opt_type_argument_list . (362) + + . reduce 362 + + +state 85 + member_name : namespace_or_type_name DOT . IDENTIFIER opt_type_argument_list (361) + + IDENTIFIER shift 272 + . error + + +state 86 + using_namespace_directive : USING namespace_name SEMICOLON . (24) + + . reduce 24 + + +state 87 + namespace_or_type_name : qualified_alias_member IDENTIFIER . opt_type_argument_list (359) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 273 + + +state 88 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER . SEMICOLON (16) + + SEMICOLON shift 274 + . error + + +state 89 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 84 + + +state 90 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list . opt_comma CLOSE_BRACKET (63) + attribute_list : attribute_list . COMMA attribute (71) + opt_comma : . (32) + + COMMA shift 91 + CLOSE_BRACKET reduce 32 + + opt_comma goto 275 + + +state 91 + opt_comma : COMMA . (33) + attribute_list : attribute_list COMMA . attribute (71) + + IDENTIFIER shift 89 + CLOSE_BRACKET reduce 33 + + namespace_or_type_name goto 45 + attribute goto 276 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 92 + attribute_section : OPEN_BRACKET attribute_list opt_comma . CLOSE_BRACKET (64) + + CLOSE_BRACKET shift 277 + . error + + +state 93 + attribute_target_specifier : attribute_target COLON . (65) + + . reduce 65 + + +state 94 + attribute : attribute_name $$5 . opt_attribute_arguments (73) + opt_attribute_arguments : . (75) + + OPEN_PARENS shift 278 + CLOSE_BRACKET reduce 75 + COMMA reduce 75 + + opt_attribute_arguments goto 279 + + +state 95 + interactive_statement_expression : error . (764) + + . reduce 764 + + +state 96 + member_access : BASE . DOT IDENTIFIER opt_type_argument_list (454) + base_access : BASE . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (503) + base_access : BASE . OPEN_BRACKET error (504) + + OPEN_BRACKET shift 280 + DOT shift 281 + OPEN_BRACKET_EXPR shift 282 + . error + + +state 97 + builtin_types : BOOL . (405) + + . reduce 405 + + +state 98 + break_statement : BREAK . SEMICOLON (809) + + SEMICOLON shift 283 + . error + + +state 99 + integral_type : BYTE . (411) + + . reduce 411 + + +state 100 + integral_type : CHAR . (418) + + . reduce 418 + + +state 101 + checked_expression : CHECKED . open_parens_any expression CLOSE_PARENS (557) + checked_statement : CHECKED . block (834) + + OPEN_BRACE shift 143 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + block goto 286 + open_parens_any goto 287 + + +state 102 + local_constant_declaration : CONST . variable_type local_constant_declarators (752) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 290 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 292 + . error + + qualified_alias_member goto 160 + builtin_types goto 293 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 295 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + variable_type goto 297 + + +state 103 + continue_statement : CONTINUE . SEMICOLON (810) + + SEMICOLON shift 298 + . error + + +state 104 + builtin_types : DECIMAL . (406) + + . reduce 406 + + +state 105 + default_value_expression : DEFAULT . open_parens_any type CLOSE_PARENS (566) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 299 + + +state 106 + anonymous_method_expression : DELEGATE . opt_anonymous_method_signature $$64 block (561) + opt_anonymous_method_signature : . (562) + + OPEN_PARENS shift 300 + OPEN_BRACE reduce 562 + + opt_anonymous_method_signature goto 301 + anonymous_method_signature goto 302 + + +state 107 + do_statement : DO . embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 321 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 108 + builtin_types : DOUBLE . (408) + + . reduce 408 + + +state 109 + boolean_literal : FALSE . (445) + + . reduce 445 + + +state 110 + fixed_statement : FIXED . open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 323 + + +state 111 + builtin_types : FLOAT . (407) + + . reduce 407 + + +state 112 + for_statement : FOR . open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 324 + + +state 113 + foreach_statement : FOREACH . open_parens_any type IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH . open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 325 + + +state 114 + goto_statement : GOTO . IDENTIFIER SEMICOLON (811) + goto_statement : GOTO . CASE constant_expression SEMICOLON (812) + goto_statement : GOTO . DEFAULT SEMICOLON (813) + + CASE shift 326 + DEFAULT shift 327 + IDENTIFIER shift 328 + . error + + +state 115 + if_statement : IF . open_parens_any boolean_expression CLOSE_PARENS embedded_statement (767) + if_statement : IF . open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 329 + + +state 116 + integral_type : INT . (414) + + . reduce 414 + + +state 117 + lock_statement : LOCK . open_parens_any expression CLOSE_PARENS embedded_statement (844) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 330 + + +state 118 + integral_type : LONG . (416) + + . reduce 416 + + +state 119 + object_or_delegate_creation_expression : NEW . new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + object_or_delegate_creation_expression : NEW . new_expr_type object_or_collection_initializer (508) + array_creation_expression : NEW . new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + array_creation_expression : NEW . new_expr_type rank_specifiers opt_array_initializer (510) + array_creation_expression : NEW . rank_specifiers array_initializer (511) + array_creation_expression : NEW . new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + array_creation_expression : NEW . new_expr_type error (513) + anonymous_type_expression : NEW . OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE (516) + $$62 : . (514) + + OPEN_BRACE shift 331 + OPEN_BRACKET shift 332 + BOOL reduce 514 + BYTE reduce 514 + CHAR reduce 514 + DECIMAL reduce 514 + DOUBLE reduce 514 + FLOAT reduce 514 + INT reduce 514 + LONG reduce 514 + OBJECT reduce 514 + SBYTE reduce 514 + SHORT reduce 514 + STRING reduce 514 + UINT reduce 514 + ULONG reduce 514 + USHORT reduce 514 + VOID reduce 514 + IDENTIFIER reduce 514 + + rank_specifiers goto 333 + new_expr_type goto 334 + $$62 goto 335 + rank_specifier goto 336 + + +state 120 + literal : NULL . (443) + + . reduce 443 + + +state 121 + builtin_types : OBJECT . (403) + + . reduce 403 + + +state 122 + return_statement : RETURN . opt_expression SEMICOLON (814) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 339 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 123 + integral_type : SBYTE . (410) + + . reduce 410 + + +state 124 + integral_type : SHORT . (412) + + . reduce 412 + + +state 125 + sizeof_expression : SIZEOF . open_parens_any type CLOSE_PARENS (556) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 342 + + +state 126 + builtin_types : STRING . (404) + + . reduce 404 + + +state 127 + switch_statement : SWITCH . open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 343 + + +state 128 + this_access : THIS . (502) + + . reduce 502 + + +state 129 + throw_statement : THROW . opt_expression SEMICOLON (815) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 344 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 130 + boolean_literal : TRUE . (444) + + . reduce 444 + + +state 131 + try_statement : TRY . block catch_clauses (820) + try_statement : TRY . block FINALLY block (821) + try_statement : TRY . block catch_clauses FINALLY block (822) + try_statement : TRY . block error (823) + + OPEN_BRACE shift 143 + . error + + block goto 345 + + +state 132 + typeof_expression : TYPEOF . $$63 open_parens_any typeof_type_expression CLOSE_PARENS (545) + $$63 : . (544) + + . reduce 544 + + $$63 goto 346 + + +state 133 + integral_type : UINT . (415) + + . reduce 415 + + +state 134 + integral_type : ULONG . (417) + + . reduce 417 + + +state 135 + unchecked_expression : UNCHECKED . open_parens_any expression CLOSE_PARENS (558) + unchecked_statement : UNCHECKED . block (835) + + OPEN_BRACE shift 143 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + block goto 347 + open_parens_any goto 348 + + +state 136 + unsafe_statement : UNSAFE . $$82 block (837) + $$82 : . (836) + + . reduce 836 + + $$82 goto 349 + + +state 137 + integral_type : USHORT . (413) + + . reduce 413 + + +state 138 + using_statement : USING . open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement (846) + using_statement : USING . open_parens_any expression CLOSE_PARENS $$85 embedded_statement (848) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 350 + + +state 139 + variable_type : VOID . opt_rank_specifier (744) + local_variable_pointer_type : VOID . STAR (747) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + STAR shift 351 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 353 + rank_specifier goto 336 + + +state 140 + while_statement : WHILE . open_parens_any boolean_expression CLOSE_PARENS embedded_statement (785) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 354 + + +state 141 + nested_from_clause : FROM . IDENTIFIER IN expression (855) + nested_from_clause : FROM . type IDENTIFIER IN expression (856) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 355 + . error + + namespace_or_type_name goto 255 + type goto 356 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 142 + first_from_clause : FROM_FIRST . IDENTIFIER IN expression (853) + first_from_clause : FROM_FIRST . type IDENTIFIER IN expression (854) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 357 + . error + + namespace_or_type_name goto 255 + type goto 358 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 143 + block : OPEN_BRACE . $$74 opt_statement_list block_end (691) + $$74 : . (690) + + . reduce 690 + + $$74 goto 359 + + +state 144 + parenthesized_expression : OPEN_PARENS . expression CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS . expression COMPLETE_COMPLETION (451) + cast_expression : OPEN_PARENS . builtin_types CLOSE_PARENS prefixed_unary_expression (572) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 360 + qualified_alias_member goto 160 + builtin_types goto 361 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 145 + empty_statement : SEMICOLON . (737) + + . reduce 737 + + +state 146 + unary_expression : TILDE . prefixed_unary_expression (569) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 362 + cast_expression goto 188 + + +state 147 + prefixed_unary_expression : PLUS . prefixed_unary_expression (574) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 363 + cast_expression goto 188 + + +state 148 + prefixed_unary_expression : MINUS . prefixed_unary_expression (575) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 364 + cast_expression goto 188 + + +state 149 + unary_expression : BANG . prefixed_unary_expression (568) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 365 + cast_expression goto 188 + + +state 150 + prefixed_unary_expression : BITWISE_AND . prefixed_unary_expression (579) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 366 + cast_expression goto 188 + + +state 151 + prefixed_unary_expression : STAR . prefixed_unary_expression (578) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 367 + cast_expression goto 188 + + +state 152 + prefixed_unary_expression : OP_INC . prefixed_unary_expression (576) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 368 + cast_expression goto 188 + + +state 153 + prefixed_unary_expression : OP_DEC . prefixed_unary_expression (577) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 369 + cast_expression goto 188 + + +state 154 + literal : LITERAL . (442) + + . reduce 442 + + +state 155 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + labeled_statement : IDENTIFIER . COLON $$76 statement (739) + yield_statement : IDENTIFIER . RETURN opt_expression SEMICOLON (816) + yield_statement : IDENTIFIER . BREAK SEMICOLON (817) + opt_type_argument_list : . (363) + + BREAK shift 370 + RETURN shift 371 + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 373 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 156 + lambda_expression : OPEN_PARENS_LAMBDA . $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + $$68 : . (638) + + . reduce 638 + + $$68 goto 376 + + +state 157 + cast_expression : OPEN_PARENS_CAST . type CLOSE_PARENS prefixed_unary_expression (571) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 377 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 158 + interactive_statement_expression : expression . (763) + + . reduce 763 + + +state 159 + interactive_valid_declaration_statement : block . (721) + + . reduce 721 + + +state 160 + member_access : qualified_alias_member . IDENTIFIER opt_type_argument_list (455) + + IDENTIFIER shift 378 + . error + + +state 161 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + variable_type : builtin_types . opt_rank_specifier_or_nullable (743) + local_variable_pointer_type : builtin_types . STAR (746) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 380 + STAR shift 381 + OPEN_BRACKET reduce 356 + IDENTIFIER reduce 356 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 383 + + +state 162 + builtin_types : integral_type . (409) + + . reduce 409 + + +state 163 + member_access : primary_expression . DOT IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression . DOT GENERATE_COMPLETION (456) + member_access : primary_expression . DOT IDENTIFIER GENERATE_COMPLETION (457) + invocation_expression : primary_expression . open_parens_any opt_argument_list close_parens (460) + element_access : primary_expression . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (494) + post_increment_expression : primary_expression . OP_INC (505) + post_decrement_expression : primary_expression . OP_DEC (506) + pointer_member_access : primary_expression . OP_PTR IDENTIFIER (559) + unary_expression : primary_expression . (567) + + OPEN_PARENS shift 284 + DOT shift 384 + OP_INC shift 385 + OP_DEC shift 386 + OP_PTR shift 387 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 388 + error reduce 567 + AS reduce 567 + IS reduce 567 + WHERE reduce 567 + FROM reduce 567 + JOIN reduce 567 + ON reduce 567 + EQUALS reduce 567 + SELECT reduce 567 + GROUP reduce 567 + BY reduce 567 + LET reduce 567 + ORDERBY reduce 567 + ASCENDING reduce 567 + DESCENDING reduce 567 + INTO reduce 567 + CLOSE_BRACE reduce 567 + CLOSE_BRACKET reduce 567 + CLOSE_PARENS reduce 567 + COMMA reduce 567 + COLON reduce 567 + SEMICOLON reduce 567 + PLUS reduce 567 + MINUS reduce 567 + ASSIGN reduce 567 + OP_LT reduce 567 + OP_GT reduce 567 + BITWISE_AND reduce 567 + BITWISE_OR reduce 567 + STAR reduce 567 + PERCENT reduce 567 + DIV reduce 567 + CARRET reduce 567 + INTERR reduce 567 + OP_SHIFT_LEFT reduce 567 + OP_SHIFT_RIGHT reduce 567 + OP_LE reduce 567 + OP_GE reduce 567 + OP_EQ reduce 567 + OP_NE reduce 567 + OP_AND reduce 567 + OP_OR reduce 567 + OP_MULT_ASSIGN reduce 567 + OP_DIV_ASSIGN reduce 567 + OP_MOD_ASSIGN reduce 567 + OP_ADD_ASSIGN reduce 567 + OP_SUB_ASSIGN reduce 567 + OP_SHIFT_LEFT_ASSIGN reduce 567 + OP_SHIFT_RIGHT_ASSIGN reduce 567 + OP_AND_ASSIGN reduce 567 + OP_XOR_ASSIGN reduce 567 + OP_OR_ASSIGN reduce 567 + OP_COALESCING reduce 567 + COMPLETE_COMPLETION reduce 567 + + open_parens_any goto 389 + + +164: shift/reduce conflict (shift 390, reduce 419) on STAR +state 164 + primary_expression : primary_expression_no_array_creation . (419) + variable_type : primary_expression_no_array_creation . opt_rank_specifier_or_nullable (742) + local_variable_pointer_type : primary_expression_no_array_creation . STAR (745) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + STAR shift 390 + AS reduce 419 + IS reduce 419 + OPEN_BRACKET reduce 356 + OPEN_PARENS reduce 419 + CLOSE_PARENS reduce 419 + DOT reduce 419 + COMMA reduce 419 + SEMICOLON reduce 419 + PLUS reduce 419 + MINUS reduce 419 + ASSIGN reduce 419 + OP_LT reduce 419 + OP_GT reduce 419 + BITWISE_AND reduce 419 + BITWISE_OR reduce 419 + PERCENT reduce 419 + DIV reduce 419 + CARRET reduce 419 + INTERR reduce 419 + OP_INC reduce 419 + OP_DEC reduce 419 + OP_SHIFT_LEFT reduce 419 + OP_SHIFT_RIGHT reduce 419 + OP_LE reduce 419 + OP_GE reduce 419 + OP_EQ reduce 419 + OP_NE reduce 419 + OP_AND reduce 419 + OP_OR reduce 419 + OP_MULT_ASSIGN reduce 419 + OP_DIV_ASSIGN reduce 419 + OP_MOD_ASSIGN reduce 419 + OP_ADD_ASSIGN reduce 419 + OP_SUB_ASSIGN reduce 419 + OP_SHIFT_LEFT_ASSIGN reduce 419 + OP_SHIFT_RIGHT_ASSIGN reduce 419 + OP_AND_ASSIGN reduce 419 + OP_XOR_ASSIGN reduce 419 + OP_OR_ASSIGN reduce 419 + OP_PTR reduce 419 + OP_COALESCING reduce 419 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 419 + OPEN_BRACKET_EXPR reduce 419 + COMPLETE_COMPLETION reduce 419 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 391 + + +state 165 + primary_expression : array_creation_expression . (420) + + . reduce 420 + + +state 166 + primary_expression_no_array_creation : literal . (421) + + . reduce 421 + + +167: shift/reduce conflict (shift 392, reduce 424) on MINUS +state 167 + primary_expression_no_array_creation : parenthesized_expression . (424) + additive_expression : parenthesized_expression . MINUS multiplicative_expression (587) + + MINUS shift 392 + error reduce 424 + AS reduce 424 + IS reduce 424 + WHERE reduce 424 + FROM reduce 424 + JOIN reduce 424 + ON reduce 424 + EQUALS reduce 424 + SELECT reduce 424 + GROUP reduce 424 + BY reduce 424 + LET reduce 424 + ORDERBY reduce 424 + ASCENDING reduce 424 + DESCENDING reduce 424 + INTO reduce 424 + INTERR_NULLABLE reduce 424 + CLOSE_BRACE reduce 424 + OPEN_BRACKET reduce 424 + CLOSE_BRACKET reduce 424 + OPEN_PARENS reduce 424 + CLOSE_PARENS reduce 424 + DOT reduce 424 + COMMA reduce 424 + COLON reduce 424 + SEMICOLON reduce 424 + PLUS reduce 424 + ASSIGN reduce 424 + OP_LT reduce 424 + OP_GT reduce 424 + BITWISE_AND reduce 424 + BITWISE_OR reduce 424 + STAR reduce 424 + PERCENT reduce 424 + DIV reduce 424 + CARRET reduce 424 + INTERR reduce 424 + OP_INC reduce 424 + OP_DEC reduce 424 + OP_SHIFT_LEFT reduce 424 + OP_SHIFT_RIGHT reduce 424 + OP_LE reduce 424 + OP_GE reduce 424 + OP_EQ reduce 424 + OP_NE reduce 424 + OP_AND reduce 424 + OP_OR reduce 424 + OP_MULT_ASSIGN reduce 424 + OP_DIV_ASSIGN reduce 424 + OP_MOD_ASSIGN reduce 424 + OP_ADD_ASSIGN reduce 424 + OP_SUB_ASSIGN reduce 424 + OP_SHIFT_LEFT_ASSIGN reduce 424 + OP_SHIFT_RIGHT_ASSIGN reduce 424 + OP_AND_ASSIGN reduce 424 + OP_XOR_ASSIGN reduce 424 + OP_OR_ASSIGN reduce 424 + OP_PTR reduce 424 + OP_COALESCING reduce 424 + IDENTIFIER reduce 424 + OPEN_PARENS_CAST reduce 424 + OPEN_BRACKET_EXPR reduce 424 + COMPLETE_COMPLETION reduce 424 + + +state 168 + primary_expression_no_array_creation : default_value_expression . (425) + + . reduce 425 + + +state 169 + primary_expression_no_array_creation : member_access . (426) + + . reduce 426 + + +state 170 + primary_expression_no_array_creation : invocation_expression . (427) + + . reduce 427 + + +state 171 + primary_expression_no_array_creation : element_access . (428) + + . reduce 428 + + +state 172 + primary_expression_no_array_creation : this_access . (429) + + . reduce 429 + + +state 173 + primary_expression_no_array_creation : base_access . (430) + + . reduce 430 + + +state 174 + primary_expression_no_array_creation : post_increment_expression . (431) + + . reduce 431 + + +state 175 + primary_expression_no_array_creation : post_decrement_expression . (432) + + . reduce 432 + + +state 176 + primary_expression_no_array_creation : object_or_delegate_creation_expression . (433) + + . reduce 433 + + +state 177 + primary_expression_no_array_creation : anonymous_type_expression . (434) + + . reduce 434 + + +state 178 + primary_expression_no_array_creation : typeof_expression . (435) + + . reduce 435 + + +state 179 + primary_expression_no_array_creation : sizeof_expression . (436) + + . reduce 436 + + +state 180 + primary_expression_no_array_creation : checked_expression . (437) + + . reduce 437 + + +state 181 + primary_expression_no_array_creation : unchecked_expression . (438) + + . reduce 438 + + +state 182 + primary_expression_no_array_creation : pointer_member_access . (439) + + . reduce 439 + + +state 183 + primary_expression_no_array_creation : anonymous_method_expression . (440) + + . reduce 440 + + +state 184 + literal : boolean_literal . (441) + + . reduce 441 + + +state 185 + expression : non_assignment_expression . (642) + + . reduce 642 + + +state 186 + prefixed_unary_expression : unary_expression . (573) + + . reduce 573 + + +state 187 + multiplicative_expression : prefixed_unary_expression . (580) + assignment_expression : prefixed_unary_expression . ASSIGN expression (615) + assignment_expression : prefixed_unary_expression . OP_MULT_ASSIGN expression (616) + assignment_expression : prefixed_unary_expression . OP_DIV_ASSIGN expression (617) + assignment_expression : prefixed_unary_expression . OP_MOD_ASSIGN expression (618) + assignment_expression : prefixed_unary_expression . OP_ADD_ASSIGN expression (619) + assignment_expression : prefixed_unary_expression . OP_SUB_ASSIGN expression (620) + assignment_expression : prefixed_unary_expression . OP_SHIFT_LEFT_ASSIGN expression (621) + assignment_expression : prefixed_unary_expression . OP_SHIFT_RIGHT_ASSIGN expression (622) + assignment_expression : prefixed_unary_expression . OP_AND_ASSIGN expression (623) + assignment_expression : prefixed_unary_expression . OP_OR_ASSIGN expression (624) + assignment_expression : prefixed_unary_expression . OP_XOR_ASSIGN expression (625) + + ASSIGN shift 393 + OP_MULT_ASSIGN shift 394 + OP_DIV_ASSIGN shift 395 + OP_MOD_ASSIGN shift 396 + OP_ADD_ASSIGN shift 397 + OP_SUB_ASSIGN shift 398 + OP_SHIFT_LEFT_ASSIGN shift 399 + OP_SHIFT_RIGHT_ASSIGN shift 400 + OP_AND_ASSIGN shift 401 + OP_XOR_ASSIGN shift 402 + OP_OR_ASSIGN shift 403 + error reduce 580 + AS reduce 580 + IS reduce 580 + WHERE reduce 580 + FROM reduce 580 + JOIN reduce 580 + ON reduce 580 + EQUALS reduce 580 + SELECT reduce 580 + GROUP reduce 580 + BY reduce 580 + LET reduce 580 + ORDERBY reduce 580 + ASCENDING reduce 580 + DESCENDING reduce 580 + INTO reduce 580 + CLOSE_BRACE reduce 580 + CLOSE_BRACKET reduce 580 + CLOSE_PARENS reduce 580 + COMMA reduce 580 + COLON reduce 580 + SEMICOLON reduce 580 + PLUS reduce 580 + MINUS reduce 580 + OP_LT reduce 580 + OP_GT reduce 580 + BITWISE_AND reduce 580 + BITWISE_OR reduce 580 + STAR reduce 580 + PERCENT reduce 580 + DIV reduce 580 + CARRET reduce 580 + INTERR reduce 580 + OP_SHIFT_LEFT reduce 580 + OP_SHIFT_RIGHT reduce 580 + OP_LE reduce 580 + OP_GE reduce 580 + OP_EQ reduce 580 + OP_NE reduce 580 + OP_AND reduce 580 + OP_OR reduce 580 + OP_COALESCING reduce 580 + COMPLETE_COMPLETION reduce 580 + + +state 188 + unary_expression : cast_expression . (570) + + . reduce 570 + + +state 189 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : multiplicative_expression . (584) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 584 + AS reduce 584 + IS reduce 584 + WHERE reduce 584 + FROM reduce 584 + JOIN reduce 584 + ON reduce 584 + EQUALS reduce 584 + SELECT reduce 584 + GROUP reduce 584 + BY reduce 584 + LET reduce 584 + ORDERBY reduce 584 + ASCENDING reduce 584 + DESCENDING reduce 584 + INTO reduce 584 + CLOSE_BRACE reduce 584 + CLOSE_BRACKET reduce 584 + CLOSE_PARENS reduce 584 + COMMA reduce 584 + COLON reduce 584 + SEMICOLON reduce 584 + PLUS reduce 584 + MINUS reduce 584 + OP_LT reduce 584 + OP_GT reduce 584 + BITWISE_AND reduce 584 + BITWISE_OR reduce 584 + CARRET reduce 584 + INTERR reduce 584 + OP_SHIFT_LEFT reduce 584 + OP_SHIFT_RIGHT reduce 584 + OP_LE reduce 584 + OP_GE reduce 584 + OP_EQ reduce 584 + OP_NE reduce 584 + OP_AND reduce 584 + OP_OR reduce 584 + OP_COALESCING reduce 584 + COMPLETE_COMPLETION reduce 584 + + +state 190 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : additive_expression . (590) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 590 + WHERE reduce 590 + FROM reduce 590 + JOIN reduce 590 + ON reduce 590 + EQUALS reduce 590 + SELECT reduce 590 + GROUP reduce 590 + BY reduce 590 + LET reduce 590 + ORDERBY reduce 590 + ASCENDING reduce 590 + DESCENDING reduce 590 + INTO reduce 590 + CLOSE_BRACE reduce 590 + CLOSE_BRACKET reduce 590 + CLOSE_PARENS reduce 590 + COMMA reduce 590 + COLON reduce 590 + SEMICOLON reduce 590 + OP_LT reduce 590 + OP_GT reduce 590 + BITWISE_AND reduce 590 + BITWISE_OR reduce 590 + CARRET reduce 590 + INTERR reduce 590 + OP_SHIFT_LEFT reduce 590 + OP_SHIFT_RIGHT reduce 590 + OP_LE reduce 590 + OP_GE reduce 590 + OP_EQ reduce 590 + OP_NE reduce 590 + OP_AND reduce 590 + OP_OR reduce 590 + OP_COALESCING reduce 590 + COMPLETE_COMPLETION reduce 590 + + +state 191 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : shift_expression . (593) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 593 + WHERE reduce 593 + FROM reduce 593 + JOIN reduce 593 + ON reduce 593 + EQUALS reduce 593 + SELECT reduce 593 + GROUP reduce 593 + BY reduce 593 + LET reduce 593 + ORDERBY reduce 593 + ASCENDING reduce 593 + DESCENDING reduce 593 + INTO reduce 593 + CLOSE_BRACE reduce 593 + CLOSE_BRACKET reduce 593 + CLOSE_PARENS reduce 593 + COMMA reduce 593 + COLON reduce 593 + SEMICOLON reduce 593 + OP_LT reduce 593 + OP_GT reduce 593 + BITWISE_AND reduce 593 + BITWISE_OR reduce 593 + CARRET reduce 593 + INTERR reduce 593 + OP_LE reduce 593 + OP_GE reduce 593 + OP_EQ reduce 593 + OP_NE reduce 593 + OP_AND reduce 593 + OP_OR reduce 593 + OP_COALESCING reduce 593 + COMPLETE_COMPLETION reduce 593 + + +state 192 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : relational_expression . (598) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 598 + WHERE reduce 598 + FROM reduce 598 + JOIN reduce 598 + ON reduce 598 + EQUALS reduce 598 + SELECT reduce 598 + GROUP reduce 598 + BY reduce 598 + LET reduce 598 + ORDERBY reduce 598 + ASCENDING reduce 598 + DESCENDING reduce 598 + INTO reduce 598 + CLOSE_BRACE reduce 598 + CLOSE_BRACKET reduce 598 + CLOSE_PARENS reduce 598 + COMMA reduce 598 + COLON reduce 598 + SEMICOLON reduce 598 + BITWISE_AND reduce 598 + BITWISE_OR reduce 598 + CARRET reduce 598 + INTERR reduce 598 + OP_EQ reduce 598 + OP_NE reduce 598 + OP_AND reduce 598 + OP_OR reduce 598 + OP_COALESCING reduce 598 + COMPLETE_COMPLETION reduce 598 + + +state 193 + equality_expression : equality_expression . OP_EQ relational_expression (599) + equality_expression : equality_expression . OP_NE relational_expression (600) + and_expression : equality_expression . (601) + + OP_EQ shift 417 + OP_NE shift 418 + error reduce 601 + WHERE reduce 601 + FROM reduce 601 + JOIN reduce 601 + ON reduce 601 + EQUALS reduce 601 + SELECT reduce 601 + GROUP reduce 601 + BY reduce 601 + LET reduce 601 + ORDERBY reduce 601 + ASCENDING reduce 601 + DESCENDING reduce 601 + INTO reduce 601 + CLOSE_BRACE reduce 601 + CLOSE_BRACKET reduce 601 + CLOSE_PARENS reduce 601 + COMMA reduce 601 + COLON reduce 601 + SEMICOLON reduce 601 + BITWISE_AND reduce 601 + BITWISE_OR reduce 601 + CARRET reduce 601 + INTERR reduce 601 + OP_AND reduce 601 + OP_OR reduce 601 + OP_COALESCING reduce 601 + COMPLETE_COMPLETION reduce 601 + + +state 194 + and_expression : and_expression . BITWISE_AND equality_expression (602) + exclusive_or_expression : and_expression . (603) + + BITWISE_AND shift 419 + error reduce 603 + WHERE reduce 603 + FROM reduce 603 + JOIN reduce 603 + ON reduce 603 + EQUALS reduce 603 + SELECT reduce 603 + GROUP reduce 603 + BY reduce 603 + LET reduce 603 + ORDERBY reduce 603 + ASCENDING reduce 603 + DESCENDING reduce 603 + INTO reduce 603 + CLOSE_BRACE reduce 603 + CLOSE_BRACKET reduce 603 + CLOSE_PARENS reduce 603 + COMMA reduce 603 + COLON reduce 603 + SEMICOLON reduce 603 + BITWISE_OR reduce 603 + CARRET reduce 603 + INTERR reduce 603 + OP_AND reduce 603 + OP_OR reduce 603 + OP_COALESCING reduce 603 + COMPLETE_COMPLETION reduce 603 + + +state 195 + exclusive_or_expression : exclusive_or_expression . CARRET and_expression (604) + inclusive_or_expression : exclusive_or_expression . (605) + + CARRET shift 420 + error reduce 605 + WHERE reduce 605 + FROM reduce 605 + JOIN reduce 605 + ON reduce 605 + EQUALS reduce 605 + SELECT reduce 605 + GROUP reduce 605 + BY reduce 605 + LET reduce 605 + ORDERBY reduce 605 + ASCENDING reduce 605 + DESCENDING reduce 605 + INTO reduce 605 + CLOSE_BRACE reduce 605 + CLOSE_BRACKET reduce 605 + CLOSE_PARENS reduce 605 + COMMA reduce 605 + COLON reduce 605 + SEMICOLON reduce 605 + BITWISE_OR reduce 605 + INTERR reduce 605 + OP_AND reduce 605 + OP_OR reduce 605 + OP_COALESCING reduce 605 + COMPLETE_COMPLETION reduce 605 + + +state 196 + inclusive_or_expression : inclusive_or_expression . BITWISE_OR exclusive_or_expression (606) + conditional_and_expression : inclusive_or_expression . (607) + + BITWISE_OR shift 421 + error reduce 607 + WHERE reduce 607 + FROM reduce 607 + JOIN reduce 607 + ON reduce 607 + EQUALS reduce 607 + SELECT reduce 607 + GROUP reduce 607 + BY reduce 607 + LET reduce 607 + ORDERBY reduce 607 + ASCENDING reduce 607 + DESCENDING reduce 607 + INTO reduce 607 + CLOSE_BRACE reduce 607 + CLOSE_BRACKET reduce 607 + CLOSE_PARENS reduce 607 + COMMA reduce 607 + COLON reduce 607 + SEMICOLON reduce 607 + INTERR reduce 607 + OP_AND reduce 607 + OP_OR reduce 607 + OP_COALESCING reduce 607 + COMPLETE_COMPLETION reduce 607 + + +state 197 + conditional_and_expression : conditional_and_expression . OP_AND inclusive_or_expression (608) + conditional_or_expression : conditional_and_expression . (609) + + OP_AND shift 422 + error reduce 609 + WHERE reduce 609 + FROM reduce 609 + JOIN reduce 609 + ON reduce 609 + EQUALS reduce 609 + SELECT reduce 609 + GROUP reduce 609 + BY reduce 609 + LET reduce 609 + ORDERBY reduce 609 + ASCENDING reduce 609 + DESCENDING reduce 609 + INTO reduce 609 + CLOSE_BRACE reduce 609 + CLOSE_BRACKET reduce 609 + CLOSE_PARENS reduce 609 + COMMA reduce 609 + COLON reduce 609 + SEMICOLON reduce 609 + INTERR reduce 609 + OP_OR reduce 609 + OP_COALESCING reduce 609 + COMPLETE_COMPLETION reduce 609 + + +state 198 + conditional_or_expression : conditional_or_expression . OP_OR conditional_and_expression (610) + null_coalescing_expression : conditional_or_expression . (611) + null_coalescing_expression : conditional_or_expression . OP_COALESCING null_coalescing_expression (612) + + OP_OR shift 423 + OP_COALESCING shift 424 + error reduce 611 + WHERE reduce 611 + FROM reduce 611 + JOIN reduce 611 + ON reduce 611 + EQUALS reduce 611 + SELECT reduce 611 + GROUP reduce 611 + BY reduce 611 + LET reduce 611 + ORDERBY reduce 611 + ASCENDING reduce 611 + DESCENDING reduce 611 + INTO reduce 611 + CLOSE_BRACE reduce 611 + CLOSE_BRACKET reduce 611 + CLOSE_PARENS reduce 611 + COMMA reduce 611 + COLON reduce 611 + SEMICOLON reduce 611 + INTERR reduce 611 + COMPLETE_COMPLETION reduce 611 + + +state 199 + conditional_expression : null_coalescing_expression . (613) + conditional_expression : null_coalescing_expression . INTERR expression COLON expression (614) + + INTERR shift 425 + error reduce 613 + WHERE reduce 613 + FROM reduce 613 + JOIN reduce 613 + ON reduce 613 + EQUALS reduce 613 + SELECT reduce 613 + GROUP reduce 613 + BY reduce 613 + LET reduce 613 + ORDERBY reduce 613 + ASCENDING reduce 613 + DESCENDING reduce 613 + INTO reduce 613 + CLOSE_BRACE reduce 613 + CLOSE_BRACKET reduce 613 + CLOSE_PARENS reduce 613 + COMMA reduce 613 + COLON reduce 613 + SEMICOLON reduce 613 + COMPLETE_COMPLETION reduce 613 + + +state 200 + non_assignment_expression : conditional_expression . (643) + + . reduce 643 + + +state 201 + expression : assignment_expression . (641) + + . reduce 641 + + +state 202 + non_assignment_expression : lambda_expression . (644) + + . reduce 644 + + +state 203 + non_assignment_expression : query_expression . (645) + + . reduce 645 + + +state 204 + interactive_statement : declaration_statement . (705) + + . reduce 705 + + +state 205 + interactive_statement : labeled_statement . (707) + + . reduce 707 + + +state 206 + interactive_statement_list : interactive_statement_list . interactive_statement (704) + interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list . opt_COMPLETE_COMPLETION (911) + opt_COMPLETE_COMPLETION : . (918) + + error shift 95 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + COMPLETE_COMPLETION shift 426 + $end reduce 918 + EOF reduce 918 + + expression goto 158 + block goto 159 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + opt_COMPLETE_COMPLETION goto 427 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 204 + labeled_statement goto 205 + interactive_statement goto 428 + interactive_valid_declaration_statement goto 208 + empty_statement goto 209 + selection_statement goto 210 + iteration_statement goto 211 + jump_statement goto 212 + try_statement goto 213 + checked_statement goto 214 + unchecked_statement goto 215 + lock_statement goto 216 + using_statement goto 217 + unsafe_statement goto 218 + fixed_statement goto 219 + interactive_expression_statement goto 220 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + interactive_statement_expression goto 226 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 207 + interactive_statement_list : interactive_statement . (703) + + . reduce 703 + + +state 208 + interactive_statement : interactive_valid_declaration_statement . (706) + + . reduce 706 + + +state 209 + interactive_valid_declaration_statement : empty_statement . (722) + + . reduce 722 + + +state 210 + interactive_valid_declaration_statement : selection_statement . (724) + + . reduce 724 + + +state 211 + interactive_valid_declaration_statement : iteration_statement . (725) + + . reduce 725 + + +state 212 + interactive_valid_declaration_statement : jump_statement . (726) + + . reduce 726 + + +state 213 + interactive_valid_declaration_statement : try_statement . (727) + + . reduce 727 + + +state 214 + interactive_valid_declaration_statement : checked_statement . (728) + + . reduce 728 + + +state 215 + interactive_valid_declaration_statement : unchecked_statement . (729) + + . reduce 729 + + +state 216 + interactive_valid_declaration_statement : lock_statement . (730) + + . reduce 730 + + +state 217 + interactive_valid_declaration_statement : using_statement . (731) + + . reduce 731 + + +state 218 + interactive_valid_declaration_statement : unsafe_statement . (732) + + . reduce 732 + + +state 219 + interactive_valid_declaration_statement : fixed_statement . (733) + + . reduce 733 + + +state 220 + interactive_valid_declaration_statement : interactive_expression_statement . (723) + + . reduce 723 + + +state 221 + declaration_statement : local_variable_declaration . SEMICOLON (740) + + SEMICOLON shift 429 + . error + + +state 222 + declaration_statement : local_constant_declaration . SEMICOLON (741) + + SEMICOLON shift 430 + . error + + +state 223 + local_variable_type : variable_type . (749) + + . reduce 749 + + +state 224 + local_variable_pointer_type : local_variable_pointer_type . STAR (748) + local_variable_type : local_variable_pointer_type . opt_rank_specifier (750) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + STAR shift 431 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 432 + rank_specifier goto 336 + + +state 225 + local_variable_declaration : local_variable_type . local_variable_declarators (751) + + IDENTIFIER shift 433 + . error + + local_variable_declarators goto 434 + local_variable_declarator goto 435 + + +state 226 + interactive_expression_statement : interactive_statement_expression . SEMICOLON (759) + interactive_expression_statement : interactive_statement_expression . COMPLETE_COMPLETION (760) + + SEMICOLON shift 436 + COMPLETE_COMPLETION shift 437 + . error + + +state 227 + selection_statement : if_statement . (765) + + . reduce 765 + + +state 228 + selection_statement : switch_statement . (766) + + . reduce 766 + + +state 229 + iteration_statement : while_statement . (781) + + . reduce 781 + + +state 230 + iteration_statement : do_statement . (782) + + . reduce 782 + + +state 231 + iteration_statement : for_statement . (783) + + . reduce 783 + + +state 232 + iteration_statement : foreach_statement . (784) + + . reduce 784 + + +state 233 + jump_statement : break_statement . (803) + + . reduce 803 + + +state 234 + jump_statement : continue_statement . (804) + + . reduce 804 + + +state 235 + jump_statement : goto_statement . (805) + + . reduce 805 + + +state 236 + jump_statement : return_statement . (806) + + . reduce 806 + + +state 237 + jump_statement : throw_statement . (807) + + . reduce 807 + + +state 238 + jump_statement : yield_statement . (808) + + . reduce 808 + + +239: shift/reduce conflict (shift 443, reduce 868) on COMPLETE_COMPLETION +state 239 + query_expression : first_from_clause . query_body (849) + query_expression : first_from_clause . COMPLETE_COMPLETION (851) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + COMPLETE_COMPLETION shift 443 + SELECT reduce 868 + GROUP reduce 868 + + query_body goto 444 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +240: shift/reduce conflict (shift 453, reduce 868) on COMPLETE_COMPLETION +state 240 + query_expression : nested_from_clause . query_body (850) + query_expression : nested_from_clause . COMPLETE_COMPLETION (852) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + COMPLETE_COMPLETION shift 453 + SELECT reduce 868 + GROUP reduce 868 + + query_body goto 454 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 241 + outer_declarations : outer_declarations . outer_declaration (10) + interactive_compilation_unit : outer_declarations . (914) + interactive_compilation_unit : outer_declarations . global_attributes (915) + opt_attributes : . (59) + + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 914 + EOF reduce 914 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + global_attributes goto 455 + outer_declaration goto 58 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 242 + interactive_compilation_unit : global_attributes . (916) + + . reduce 916 + + +state 243 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 interactive_compilation_unit . (913) + + . reduce 913 + + +state 244 + using_directives : using_directives using_directive . (19) + + . reduce 19 + + +state 245 + compilation_unit : outer_declarations global_attributes opt_EOF . (2) + + . reduce 2 + + +state 246 + compilation_unit : interactive_parsing $$1 opt_EOF . (6) + + . reduce 6 + + +state 247 + qualified_identifier : error . (29) + + . reduce 29 + + +state 248 + qualified_identifier : IDENTIFIER . (27) + + . reduce 27 + + +state 249 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier . $$2 namespace_body opt_semicolon (26) + qualified_identifier : qualified_identifier . DOT IDENTIFIER (28) + $$2 : . (25) + + DOT shift 456 + OPEN_BRACE reduce 25 + + $$2 goto 457 + + +state 250 + delegate_declaration : opt_attributes opt_modifiers DELEGATE . member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + member_type goto 458 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 251 + enum_declaration : opt_attributes opt_modifiers ENUM . type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 460 + + +state 252 + field_declaration : opt_attributes opt_modifiers FIXED . simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers FIXED . simple_type error SEMICOLON (143) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 462 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 253 + type_and_void : VOID . (385) + type_expression : VOID . STAR (398) + + STAR shift 464 + ABSTRACT reduce 385 + EXTERN reduce 385 + INTERNAL reduce 385 + NEW reduce 385 + OVERRIDE reduce 385 + PRIVATE reduce 385 + PROTECTED reduce 385 + PUBLIC reduce 385 + READONLY reduce 385 + SEALED reduce 385 + STATIC reduce 385 + UNSAFE reduce 385 + VIRTUAL reduce 385 + VOLATILE reduce 385 + CLOSE_PARENS reduce 385 + IDENTIFIER reduce 385 + + +state 254 + method_header : opt_attributes opt_modifiers PARTIAL . VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + opt_partial : PARTIAL . (654) + + VOID shift 465 + CLASS reduce 654 + INTERFACE reduce 654 + STRUCT reduce 654 + + +state 255 + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + type_expression : namespace_or_type_name . opt_nullable (395) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 85 + error reduce 356 + ABSTRACT reduce 356 + AS reduce 356 + EXTERN reduce 356 + IN reduce 356 + INTERNAL reduce 356 + IS reduce 356 + NEW reduce 356 + OPERATOR reduce 356 + OVERRIDE reduce 356 + PRIVATE reduce 356 + PROTECTED reduce 356 + PUBLIC reduce 356 + READONLY reduce 356 + SEALED reduce 356 + STATIC reduce 356 + THIS reduce 356 + UNSAFE reduce 356 + VIRTUAL reduce 356 + VOLATILE reduce 356 + WHERE reduce 356 + FROM reduce 356 + JOIN reduce 356 + ON reduce 356 + EQUALS reduce 356 + SELECT reduce 356 + GROUP reduce 356 + BY reduce 356 + LET reduce 356 + ORDERBY reduce 356 + ASCENDING reduce 356 + DESCENDING reduce 356 + INTO reduce 356 + OP_GENERICS_GT reduce 356 + OPEN_BRACE reduce 356 + CLOSE_BRACE reduce 356 + OPEN_BRACKET reduce 356 + CLOSE_BRACKET reduce 356 + OPEN_PARENS reduce 356 + CLOSE_PARENS reduce 356 + COMMA reduce 356 + COLON reduce 356 + SEMICOLON reduce 356 + PLUS reduce 356 + MINUS reduce 356 + OP_LT reduce 356 + OP_GT reduce 356 + BITWISE_AND reduce 356 + BITWISE_OR reduce 356 + STAR reduce 356 + CARRET reduce 356 + INTERR reduce 356 + OP_SHIFT_LEFT reduce 356 + OP_SHIFT_RIGHT reduce 356 + OP_LE reduce 356 + OP_GE reduce 356 + OP_EQ reduce 356 + OP_NE reduce 356 + OP_AND reduce 356 + OP_OR reduce 356 + OP_COALESCING reduce 356 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 356 + OPEN_BRACKET_EXPR reduce 356 + COMPLETE_COMPLETION reduce 356 + + opt_nullable goto 466 + + +state 256 + struct_declaration : opt_attributes opt_modifiers opt_partial . STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers opt_partial . STRUCT error (110) + interface_declaration : opt_attributes opt_modifiers opt_partial . INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers opt_partial . INTERFACE error (243) + class_declaration : opt_attributes opt_modifiers opt_partial . CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + CLASS shift 467 + INTERFACE shift 468 + STRUCT shift 469 + . error + + +state 257 + field_declaration : opt_attributes opt_modifiers member_type . IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + method_header : opt_attributes opt_modifiers member_type . method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers member_type . modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 470 + . error + + type_declaration_name goto 471 + method_declaration_name goto 472 + modifiers goto 473 + qualified_alias_member goto 474 + explicit_interface goto 475 + modifier goto 78 + + +state 258 + type_and_void : type_expression_or_array . (384) + + . reduce 384 + + +state 259 + member_type : type_and_void . (386) + + . reduce 386 + + +state 260 + type_expression_or_array : type_expression . (393) + type_expression_or_array : type_expression . rank_specifiers (394) + type_expression : type_expression . STAR (397) + + OPEN_BRACKET shift 332 + STAR shift 476 + error reduce 393 + ABSTRACT reduce 393 + AS reduce 393 + EXTERN reduce 393 + IN reduce 393 + INTERNAL reduce 393 + IS reduce 393 + NEW reduce 393 + OPERATOR reduce 393 + OVERRIDE reduce 393 + PRIVATE reduce 393 + PROTECTED reduce 393 + PUBLIC reduce 393 + READONLY reduce 393 + SEALED reduce 393 + STATIC reduce 393 + THIS reduce 393 + UNSAFE reduce 393 + VIRTUAL reduce 393 + VOLATILE reduce 393 + WHERE reduce 393 + FROM reduce 393 + JOIN reduce 393 + ON reduce 393 + EQUALS reduce 393 + SELECT reduce 393 + GROUP reduce 393 + BY reduce 393 + LET reduce 393 + ORDERBY reduce 393 + ASCENDING reduce 393 + DESCENDING reduce 393 + INTO reduce 393 + OP_GENERICS_GT reduce 393 + OPEN_BRACE reduce 393 + CLOSE_BRACE reduce 393 + CLOSE_BRACKET reduce 393 + OPEN_PARENS reduce 393 + CLOSE_PARENS reduce 393 + COMMA reduce 393 + COLON reduce 393 + SEMICOLON reduce 393 + PLUS reduce 393 + MINUS reduce 393 + OP_LT reduce 393 + OP_GT reduce 393 + BITWISE_AND reduce 393 + BITWISE_OR reduce 393 + CARRET reduce 393 + INTERR reduce 393 + OP_SHIFT_LEFT reduce 393 + OP_SHIFT_RIGHT reduce 393 + OP_LE reduce 393 + OP_GE reduce 393 + OP_EQ reduce 393 + OP_NE reduce 393 + OP_AND reduce 393 + OP_OR reduce 393 + OP_COALESCING reduce 393 + IDENTIFIER reduce 393 + COMPLETE_COMPLETION reduce 393 + + rank_specifiers goto 477 + rank_specifier goto 336 + + +state 261 + type_expression : builtin_types . opt_nullable (396) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + error reduce 356 + ABSTRACT reduce 356 + AS reduce 356 + EXTERN reduce 356 + IN reduce 356 + INTERNAL reduce 356 + IS reduce 356 + NEW reduce 356 + OPERATOR reduce 356 + OVERRIDE reduce 356 + PRIVATE reduce 356 + PROTECTED reduce 356 + PUBLIC reduce 356 + READONLY reduce 356 + SEALED reduce 356 + STATIC reduce 356 + THIS reduce 356 + UNSAFE reduce 356 + VIRTUAL reduce 356 + VOLATILE reduce 356 + WHERE reduce 356 + FROM reduce 356 + JOIN reduce 356 + ON reduce 356 + EQUALS reduce 356 + SELECT reduce 356 + GROUP reduce 356 + BY reduce 356 + LET reduce 356 + ORDERBY reduce 356 + ASCENDING reduce 356 + DESCENDING reduce 356 + INTO reduce 356 + OP_GENERICS_GT reduce 356 + OPEN_BRACE reduce 356 + CLOSE_BRACE reduce 356 + OPEN_BRACKET reduce 356 + CLOSE_BRACKET reduce 356 + OPEN_PARENS reduce 356 + CLOSE_PARENS reduce 356 + COMMA reduce 356 + COLON reduce 356 + SEMICOLON reduce 356 + PLUS reduce 356 + MINUS reduce 356 + OP_LT reduce 356 + OP_GT reduce 356 + BITWISE_AND reduce 356 + BITWISE_OR reduce 356 + STAR reduce 356 + CARRET reduce 356 + INTERR reduce 356 + OP_SHIFT_LEFT reduce 356 + OP_SHIFT_RIGHT reduce 356 + OP_LE reduce 356 + OP_GE reduce 356 + OP_EQ reduce 356 + OP_NE reduce 356 + OP_AND reduce 356 + OP_OR reduce 356 + OP_COALESCING reduce 356 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 356 + OPEN_BRACKET_EXPR reduce 356 + COMPLETE_COMPLETION reduce 356 + + opt_nullable goto 478 + + +state 262 + modifiers : modifiers modifier . (658) + + . reduce 658 + + +state 263 + method_body : SEMICOLON . (185) + + . reduce 185 + + +state 264 + method_declaration : method_header $$19 method_body . (176) + + . reduce 176 + + +state 265 + method_body : block . (184) + + . reduce 184 + + +state 266 + opt_type_argument_list : OP_GENERICS_LT error . (365) + + . reduce 365 + + +state 267 + type : VOID . (388) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 388 + AS reduce 388 + IN reduce 388 + IS reduce 388 + WHERE reduce 388 + FROM reduce 388 + JOIN reduce 388 + ON reduce 388 + EQUALS reduce 388 + SELECT reduce 388 + GROUP reduce 388 + BY reduce 388 + LET reduce 388 + ORDERBY reduce 388 + ASCENDING reduce 388 + DESCENDING reduce 388 + INTO reduce 388 + OP_GENERICS_GT reduce 388 + OPEN_BRACE reduce 388 + CLOSE_BRACE reduce 388 + CLOSE_BRACKET reduce 388 + OPEN_PARENS reduce 388 + CLOSE_PARENS reduce 388 + COMMA reduce 388 + COLON reduce 388 + SEMICOLON reduce 388 + PLUS reduce 388 + MINUS reduce 388 + OP_LT reduce 388 + OP_GT reduce 388 + BITWISE_AND reduce 388 + BITWISE_OR reduce 388 + CARRET reduce 388 + INTERR reduce 388 + OP_SHIFT_LEFT reduce 388 + OP_SHIFT_RIGHT reduce 388 + OP_LE reduce 388 + OP_GE reduce 388 + OP_EQ reduce 388 + OP_NE reduce 388 + OP_AND reduce 388 + OP_OR reduce 388 + OP_COALESCING reduce 388 + IDENTIFIER reduce 388 + COMPLETE_COMPLETION reduce 388 + + +state 268 + type_arguments : type . (366) + + . reduce 366 + + +state 269 + type : type_expression_or_array . (387) + + . reduce 387 + + +state 270 + opt_type_argument_list : OP_GENERICS_LT type_arguments . OP_GENERICS_GT (364) + type_arguments : type_arguments . COMMA type (367) + + OP_GENERICS_GT shift 479 + COMMA shift 480 + . error + + +state 271 + using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name . SEMICOLON (22) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + SEMICOLON shift 481 + . error + + +state 272 + member_name : namespace_or_type_name DOT IDENTIFIER . opt_type_argument_list (361) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 482 + + +state 273 + namespace_or_type_name : qualified_alias_member IDENTIFIER opt_type_argument_list . (359) + + . reduce 359 + + +state 274 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON . (16) + + . reduce 16 + + +state 275 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma . CLOSE_BRACKET (63) + + CLOSE_BRACKET shift 483 + . error + + +state 276 + attribute_list : attribute_list COMMA attribute . (71) + + . reduce 71 + + +state 277 + attribute_section : OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET . (64) + + . reduce 64 + + +state 278 + opt_attribute_arguments : OPEN_PARENS . attribute_arguments CLOSE_PARENS (76) + attribute_arguments : . (77) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 484 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 77 + COMMA reduce 77 + + attribute_arguments goto 485 + positional_or_named_argument goto 486 + named_attribute_argument goto 487 + expression goto 488 + named_argument goto 489 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 279 + attribute : attribute_name $$5 opt_attribute_arguments . (73) + + . reduce 73 + + +state 280 + base_access : BASE OPEN_BRACKET . error (504) + + error shift 490 + . error + + +state 281 + member_access : BASE DOT . IDENTIFIER opt_type_argument_list (454) + + IDENTIFIER shift 491 + . error + + +state 282 + base_access : BASE OPEN_BRACKET_EXPR . expression_list_arguments CLOSE_BRACKET (503) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_arguments goto 495 + expression_list_argument goto 496 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 283 + break_statement : BREAK SEMICOLON . (809) + + . reduce 809 + + +state 284 + open_parens_any : OPEN_PARENS . (446) + + . reduce 446 + + +state 285 + open_parens_any : OPEN_PARENS_CAST . (447) + + . reduce 447 + + +state 286 + checked_statement : CHECKED block . (834) + + . reduce 834 + + +state 287 + checked_expression : CHECKED open_parens_any . expression CLOSE_PARENS (557) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 497 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 288 + checked_expression : CHECKED . open_parens_any expression CLOSE_PARENS (557) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 287 + + +state 289 + unchecked_expression : UNCHECKED . open_parens_any expression CLOSE_PARENS (558) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 348 + + +state 290 + variable_type : VOID . opt_rank_specifier (744) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 353 + rank_specifier goto 336 + + +state 291 + parenthesized_expression : OPEN_PARENS . expression CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS . expression COMPLETE_COMPLETION (451) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 360 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 292 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 293 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + variable_type : builtin_types . opt_rank_specifier_or_nullable (743) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 380 + OPEN_BRACKET reduce 356 + IDENTIFIER reduce 356 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 383 + + +state 294 + member_access : primary_expression . DOT IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression . DOT GENERATE_COMPLETION (456) + member_access : primary_expression . DOT IDENTIFIER GENERATE_COMPLETION (457) + invocation_expression : primary_expression . open_parens_any opt_argument_list close_parens (460) + element_access : primary_expression . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (494) + post_increment_expression : primary_expression . OP_INC (505) + post_decrement_expression : primary_expression . OP_DEC (506) + pointer_member_access : primary_expression . OP_PTR IDENTIFIER (559) + + OPEN_PARENS shift 284 + DOT shift 384 + OP_INC shift 385 + OP_DEC shift 386 + OP_PTR shift 387 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 388 + . error + + open_parens_any goto 389 + + +state 295 + primary_expression : primary_expression_no_array_creation . (419) + variable_type : primary_expression_no_array_creation . opt_rank_specifier_or_nullable (742) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + OPEN_BRACKET reduce 356 + OPEN_PARENS reduce 419 + DOT reduce 419 + OP_INC reduce 419 + OP_DEC reduce 419 + OP_PTR reduce 419 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 419 + OPEN_BRACKET_EXPR reduce 419 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 391 + + +state 296 + primary_expression_no_array_creation : parenthesized_expression . (424) + + . reduce 424 + + +state 297 + local_constant_declaration : CONST variable_type . local_constant_declarators (752) + + IDENTIFIER shift 498 + . error + + local_constant_declarators goto 499 + local_constant_declarator goto 500 + + +state 298 + continue_statement : CONTINUE SEMICOLON . (810) + + . reduce 810 + + +state 299 + default_value_expression : DEFAULT open_parens_any . type CLOSE_PARENS (566) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 501 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 300 + anonymous_method_signature : OPEN_PARENS . $$65 opt_formal_parameter_list CLOSE_PARENS (565) + $$65 : . (564) + + . reduce 564 + + $$65 goto 502 + + +state 301 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature . $$64 block (561) + $$64 : . (560) + + . reduce 560 + + $$64 goto 503 + + +state 302 + opt_anonymous_method_signature : anonymous_method_signature . (563) + + . reduce 563 + + +state 303 + statement_expression : error . (762) + + . reduce 762 + + +state 304 + statement_expression : expression . (761) + + . reduce 761 + + +state 305 + valid_declaration_statement : block . (708) + + . reduce 708 + + +state 306 + embedded_statement : declaration_statement . (735) + + . reduce 735 + + +state 307 + embedded_statement : valid_declaration_statement . (734) + + . reduce 734 + + +state 308 + embedded_statement : labeled_statement . (736) + + . reduce 736 + + +state 309 + valid_declaration_statement : empty_statement . (709) + + . reduce 709 + + +state 310 + valid_declaration_statement : expression_statement . (710) + + . reduce 710 + + +state 311 + valid_declaration_statement : selection_statement . (711) + + . reduce 711 + + +state 312 + valid_declaration_statement : iteration_statement . (712) + + . reduce 712 + + +state 313 + valid_declaration_statement : jump_statement . (713) + + . reduce 713 + + +state 314 + valid_declaration_statement : try_statement . (714) + + . reduce 714 + + +state 315 + valid_declaration_statement : checked_statement . (715) + + . reduce 715 + + +state 316 + valid_declaration_statement : unchecked_statement . (716) + + . reduce 716 + + +state 317 + valid_declaration_statement : lock_statement . (717) + + . reduce 717 + + +state 318 + valid_declaration_statement : using_statement . (718) + + . reduce 718 + + +state 319 + valid_declaration_statement : unsafe_statement . (719) + + . reduce 719 + + +state 320 + valid_declaration_statement : fixed_statement . (720) + + . reduce 720 + + +state 321 + do_statement : DO embedded_statement . WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + WHILE shift 504 + . error + + +state 322 + expression_statement : statement_expression . SEMICOLON (757) + expression_statement : statement_expression . COMPLETE_COMPLETION (758) + + SEMICOLON shift 505 + COMPLETE_COMPLETION shift 506 + . error + + +state 323 + fixed_statement : FIXED open_parens_any . type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 507 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 324 + for_statement : FOR open_parens_any . opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_initializer : . (789) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 139 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 789 + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + local_variable_declaration goto 508 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 509 + opt_for_initializer goto 510 + for_initializer goto 511 + statement_expression_list goto 512 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 325 + foreach_statement : FOREACH open_parens_any . type IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH open_parens_any . type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 513 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 326 + goto_statement : GOTO CASE . constant_expression SEMICOLON (812) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 515 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 327 + goto_statement : GOTO DEFAULT . SEMICOLON (813) + + SEMICOLON shift 516 + . error + + +state 328 + goto_statement : GOTO IDENTIFIER . SEMICOLON (811) + + SEMICOLON shift 517 + . error + + +state 329 + if_statement : IF open_parens_any . boolean_expression CLOSE_PARENS embedded_statement (767) + if_statement : IF open_parens_any . boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 519 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 330 + lock_statement : LOCK open_parens_any . expression CLOSE_PARENS embedded_statement (844) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 520 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 331 + anonymous_type_expression : NEW OPEN_BRACE . anonymous_type_parameters_opt_comma CLOSE_BRACE (516) + anonymous_type_parameters_opt : . (519) + + error shift 521 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 522 + CLOSE_BRACE reduce 519 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 523 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + anonymous_type_parameters_opt_comma goto 524 + anonymous_type_parameters_opt goto 525 + anonymous_type_parameters goto 526 + anonymous_type_parameter goto 527 + + +state 332 + rank_specifier : OPEN_BRACKET . CLOSE_BRACKET (533) + rank_specifier : OPEN_BRACKET . dim_separators CLOSE_BRACKET (534) + + CLOSE_BRACKET shift 528 + COMMA shift 529 + . error + + dim_separators goto 530 + + +state 333 + array_creation_expression : NEW rank_specifiers . array_initializer (511) + + OPEN_BRACE shift 531 + . error + + array_initializer goto 532 + + +state 334 + object_or_delegate_creation_expression : NEW new_expr_type . open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + object_or_delegate_creation_expression : NEW new_expr_type . object_or_collection_initializer (508) + array_creation_expression : NEW new_expr_type . OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + array_creation_expression : NEW new_expr_type . rank_specifiers opt_array_initializer (510) + array_creation_expression : NEW new_expr_type . OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + array_creation_expression : NEW new_expr_type . error (513) + + error shift 533 + OPEN_BRACE shift 534 + OPEN_BRACKET shift 535 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 536 + . error + + rank_specifiers goto 537 + open_parens_any goto 538 + object_or_collection_initializer goto 539 + rank_specifier goto 336 + + +state 335 + new_expr_type : $$62 . simple_type (515) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 540 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 336 + rank_specifiers : rank_specifier . (531) + rank_specifiers : rank_specifier . rank_specifiers (532) + + OPEN_BRACKET shift 332 + error reduce 531 + ABSTRACT reduce 531 + AS reduce 531 + EXTERN reduce 531 + IN reduce 531 + INTERNAL reduce 531 + IS reduce 531 + NEW reduce 531 + OPERATOR reduce 531 + OVERRIDE reduce 531 + PRIVATE reduce 531 + PROTECTED reduce 531 + PUBLIC reduce 531 + READONLY reduce 531 + SEALED reduce 531 + STATIC reduce 531 + THIS reduce 531 + UNSAFE reduce 531 + VIRTUAL reduce 531 + VOLATILE reduce 531 + WHERE reduce 531 + FROM reduce 531 + JOIN reduce 531 + ON reduce 531 + EQUALS reduce 531 + SELECT reduce 531 + GROUP reduce 531 + BY reduce 531 + LET reduce 531 + ORDERBY reduce 531 + ASCENDING reduce 531 + DESCENDING reduce 531 + INTO reduce 531 + OP_GENERICS_GT reduce 531 + OPEN_BRACE reduce 531 + CLOSE_BRACE reduce 531 + CLOSE_BRACKET reduce 531 + OPEN_PARENS reduce 531 + CLOSE_PARENS reduce 531 + DOT reduce 531 + COMMA reduce 531 + COLON reduce 531 + SEMICOLON reduce 531 + PLUS reduce 531 + MINUS reduce 531 + ASSIGN reduce 531 + OP_LT reduce 531 + OP_GT reduce 531 + BITWISE_AND reduce 531 + BITWISE_OR reduce 531 + STAR reduce 531 + PERCENT reduce 531 + DIV reduce 531 + CARRET reduce 531 + INTERR reduce 531 + OP_INC reduce 531 + OP_DEC reduce 531 + OP_SHIFT_LEFT reduce 531 + OP_SHIFT_RIGHT reduce 531 + OP_LE reduce 531 + OP_GE reduce 531 + OP_EQ reduce 531 + OP_NE reduce 531 + OP_AND reduce 531 + OP_OR reduce 531 + OP_MULT_ASSIGN reduce 531 + OP_DIV_ASSIGN reduce 531 + OP_MOD_ASSIGN reduce 531 + OP_ADD_ASSIGN reduce 531 + OP_SUB_ASSIGN reduce 531 + OP_SHIFT_LEFT_ASSIGN reduce 531 + OP_SHIFT_RIGHT_ASSIGN reduce 531 + OP_AND_ASSIGN reduce 531 + OP_XOR_ASSIGN reduce 531 + OP_OR_ASSIGN reduce 531 + OP_PTR reduce 531 + OP_COALESCING reduce 531 + IDENTIFIER reduce 531 + OPEN_PARENS_CAST reduce 531 + OPEN_BRACKET_EXPR reduce 531 + COMPLETE_COMPLETION reduce 531 + + rank_specifiers goto 541 + rank_specifier goto 336 + + +state 337 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 338 + opt_expression : expression . (819) + + . reduce 819 + + +state 339 + return_statement : RETURN opt_expression . SEMICOLON (814) + + SEMICOLON shift 542 + . error + + +state 340 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + + DOT shift 380 + . error + + +state 341 + primary_expression : primary_expression_no_array_creation . (419) + + . reduce 419 + + +state 342 + sizeof_expression : SIZEOF open_parens_any . type CLOSE_PARENS (556) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 543 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 343 + switch_statement : SWITCH open_parens_any . $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + $$77 : . (769) + + . reduce 769 + + $$77 goto 544 + + +state 344 + throw_statement : THROW opt_expression . SEMICOLON (815) + + SEMICOLON shift 545 + . error + + +state 345 + try_statement : TRY block . catch_clauses (820) + try_statement : TRY block . FINALLY block (821) + try_statement : TRY block . catch_clauses FINALLY block (822) + try_statement : TRY block . error (823) + + error shift 546 + CATCH shift 547 + FINALLY shift 548 + . error + + catch_clauses goto 549 + catch_clause goto 550 + + +state 346 + typeof_expression : TYPEOF $$63 . open_parens_any typeof_type_expression CLOSE_PARENS (545) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 551 + + +state 347 + unchecked_statement : UNCHECKED block . (835) + + . reduce 835 + + +state 348 + unchecked_expression : UNCHECKED open_parens_any . expression CLOSE_PARENS (558) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 552 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 349 + unsafe_statement : UNSAFE $$82 . block (837) + + OPEN_BRACE shift 143 + . error + + block goto 553 + + +state 350 + using_statement : USING open_parens_any . local_variable_declaration CLOSE_PARENS $$84 embedded_statement (846) + using_statement : USING open_parens_any . expression CLOSE_PARENS $$85 embedded_statement (848) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 139 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 554 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + local_variable_declaration goto 555 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 351 + local_variable_pointer_type : VOID STAR . (747) + + . reduce 747 + + +state 352 + opt_rank_specifier : rank_specifiers . (528) + + . reduce 528 + + +state 353 + variable_type : VOID opt_rank_specifier . (744) + + . reduce 744 + + +state 354 + while_statement : WHILE open_parens_any . boolean_expression CLOSE_PARENS embedded_statement (785) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 556 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 355 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + nested_from_clause : FROM IDENTIFIER . IN expression (855) + opt_type_argument_list : . (363) + + IN shift 557 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 356 + nested_from_clause : FROM type . IDENTIFIER IN expression (856) + + IDENTIFIER shift 558 + . error + + +state 357 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + first_from_clause : FROM_FIRST IDENTIFIER . IN expression (853) + opt_type_argument_list : . (363) + + IN shift 559 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 358 + first_from_clause : FROM_FIRST type . IDENTIFIER IN expression (854) + + IDENTIFIER shift 560 + . error + + +state 359 + block : OPEN_BRACE $$74 . opt_statement_list block_end (691) + opt_statement_list : . (696) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 696 + COMPLETE_COMPLETION reduce 696 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + opt_statement_list goto 561 + statement_list goto 562 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 360 + parenthesized_expression : OPEN_PARENS expression . CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS expression . COMPLETE_COMPLETION (451) + + CLOSE_PARENS shift 567 + COMPLETE_COMPLETION shift 568 + . error + + +state 361 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + cast_expression : OPEN_PARENS builtin_types . CLOSE_PARENS prefixed_unary_expression (572) + + CLOSE_PARENS shift 569 + DOT shift 380 + . error + + +state 362 + unary_expression : TILDE prefixed_unary_expression . (569) + + . reduce 569 + + +state 363 + prefixed_unary_expression : PLUS prefixed_unary_expression . (574) + + . reduce 574 + + +state 364 + prefixed_unary_expression : MINUS prefixed_unary_expression . (575) + + . reduce 575 + + +state 365 + unary_expression : BANG prefixed_unary_expression . (568) + + . reduce 568 + + +state 366 + prefixed_unary_expression : BITWISE_AND prefixed_unary_expression . (579) + + . reduce 579 + + +state 367 + prefixed_unary_expression : STAR prefixed_unary_expression . (578) + + . reduce 578 + + +state 368 + prefixed_unary_expression : OP_INC prefixed_unary_expression . (576) + + . reduce 576 + + +state 369 + prefixed_unary_expression : OP_DEC prefixed_unary_expression . (577) + + . reduce 577 + + +state 370 + yield_statement : IDENTIFIER BREAK . SEMICOLON (817) + + SEMICOLON shift 570 + . error + + +state 371 + yield_statement : IDENTIFIER RETURN . opt_expression SEMICOLON (816) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 571 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 372 + lambda_expression : IDENTIFIER ARROW . $$67 lambda_expression_body (637) + $$67 : . (636) + + . reduce 636 + + $$67 goto 572 + + +state 373 + labeled_statement : IDENTIFIER COLON . $$76 statement (739) + $$76 : . (738) + + . reduce 738 + + $$76 goto 573 + + +state 374 + primary_expression_no_array_creation : IDENTIFIER GENERATE_COMPLETION . (423) + + . reduce 423 + + +state 375 + primary_expression_no_array_creation : IDENTIFIER opt_type_argument_list . (422) + + . reduce 422 + + +state 376 + lambda_expression : OPEN_PARENS_LAMBDA $$68 . opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + opt_lambda_parameter_list : . (631) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + OUT shift 574 + REF shift 575 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + THIS shift 576 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 578 + CLOSE_PARENS reduce 631 + + namespace_or_type_name goto 255 + parameter_type goto 579 + parameter_modifier goto 580 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + lambda_parameter_list goto 582 + lambda_parameter goto 583 + opt_lambda_parameter_list goto 584 + + +state 377 + cast_expression : OPEN_PARENS_CAST type . CLOSE_PARENS prefixed_unary_expression (571) + + CLOSE_PARENS shift 585 + . error + + +state 378 + member_access : qualified_alias_member IDENTIFIER . opt_type_argument_list (455) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 586 + + +state 379 + opt_nullable : INTERR_NULLABLE . (357) + + . reduce 357 + + +state 380 + member_access : builtin_types DOT . IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types DOT . GENERATE_COMPLETION (458) + member_access : builtin_types DOT . IDENTIFIER GENERATE_COMPLETION (459) + + IDENTIFIER shift 587 + GENERATE_COMPLETION shift 588 + . error + + +state 381 + local_variable_pointer_type : builtin_types STAR . (746) + + . reduce 746 + + +state 382 + opt_rank_specifier_or_nullable : opt_nullable . (529) + opt_rank_specifier_or_nullable : opt_nullable . rank_specifiers (530) + + OPEN_BRACKET shift 332 + IDENTIFIER reduce 529 + + rank_specifiers goto 589 + rank_specifier goto 336 + + +state 383 + variable_type : builtin_types opt_rank_specifier_or_nullable . (743) + + . reduce 743 + + +state 384 + member_access : primary_expression DOT . IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression DOT . GENERATE_COMPLETION (456) + member_access : primary_expression DOT . IDENTIFIER GENERATE_COMPLETION (457) + + IDENTIFIER shift 590 + GENERATE_COMPLETION shift 591 + . error + + +state 385 + post_increment_expression : primary_expression OP_INC . (505) + + . reduce 505 + + +state 386 + post_decrement_expression : primary_expression OP_DEC . (506) + + . reduce 506 + + +state 387 + pointer_member_access : primary_expression OP_PTR . IDENTIFIER (559) + + IDENTIFIER shift 592 + . error + + +state 388 + element_access : primary_expression OPEN_BRACKET_EXPR . expression_list_arguments CLOSE_BRACKET (494) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_arguments goto 593 + expression_list_argument goto 496 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 389 + invocation_expression : primary_expression open_parens_any . opt_argument_list close_parens (460) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + COMPLETE_COMPLETION reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 600 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 390 + local_variable_pointer_type : primary_expression_no_array_creation STAR . (745) + + . reduce 745 + + +state 391 + variable_type : primary_expression_no_array_creation opt_rank_specifier_or_nullable . (742) + + . reduce 742 + + +state 392 + additive_expression : parenthesized_expression MINUS . multiplicative_expression (587) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 606 + + +state 393 + assignment_expression : prefixed_unary_expression ASSIGN . expression (615) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 607 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 394 + assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN . expression (616) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 608 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 395 + assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN . expression (617) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 609 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 396 + assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN . expression (618) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 610 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 397 + assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN . expression (619) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 611 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 398 + assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN . expression (620) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 612 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 399 + assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN . expression (621) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 613 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 400 + assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN . expression (622) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 614 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 401 + assignment_expression : prefixed_unary_expression OP_AND_ASSIGN . expression (623) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 615 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 402 + assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN . expression (625) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 616 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 403 + assignment_expression : prefixed_unary_expression OP_OR_ASSIGN . expression (624) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 617 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 404 + multiplicative_expression : multiplicative_expression STAR . prefixed_unary_expression (581) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 618 + cast_expression goto 188 + + +state 405 + multiplicative_expression : multiplicative_expression PERCENT . prefixed_unary_expression (583) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 619 + cast_expression goto 188 + + +state 406 + multiplicative_expression : multiplicative_expression DIV . prefixed_unary_expression (582) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 620 + cast_expression goto 188 + + +state 407 + additive_expression : additive_expression AS . type (588) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 621 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 408 + additive_expression : additive_expression IS . type (589) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 622 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 409 + additive_expression : additive_expression PLUS . multiplicative_expression (585) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 623 + + +state 410 + additive_expression : additive_expression MINUS . multiplicative_expression (586) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 624 + + +state 411 + shift_expression : shift_expression OP_SHIFT_LEFT . additive_expression (591) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 625 + + +state 412 + shift_expression : shift_expression OP_SHIFT_RIGHT . additive_expression (592) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 626 + + +state 413 + relational_expression : relational_expression OP_LT . shift_expression (594) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 627 + + +state 414 + relational_expression : relational_expression OP_GT . shift_expression (595) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 628 + + +state 415 + relational_expression : relational_expression OP_LE . shift_expression (596) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 629 + + +state 416 + relational_expression : relational_expression OP_GE . shift_expression (597) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 630 + + +state 417 + equality_expression : equality_expression OP_EQ . relational_expression (599) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 631 + + +state 418 + equality_expression : equality_expression OP_NE . relational_expression (600) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 632 + + +state 419 + and_expression : and_expression BITWISE_AND . equality_expression (602) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 633 + + +state 420 + exclusive_or_expression : exclusive_or_expression CARRET . and_expression (604) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 634 + + +state 421 + inclusive_or_expression : inclusive_or_expression BITWISE_OR . exclusive_or_expression (606) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 635 + + +state 422 + conditional_and_expression : conditional_and_expression OP_AND . inclusive_or_expression (608) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 636 + + +state 423 + conditional_or_expression : conditional_or_expression OP_OR . conditional_and_expression (610) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 637 + + +state 424 + null_coalescing_expression : conditional_or_expression OP_COALESCING . null_coalescing_expression (612) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 638 + + +state 425 + conditional_expression : null_coalescing_expression INTERR . expression COLON expression (614) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 639 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 426 + opt_COMPLETE_COMPLETION : COMPLETE_COMPLETION . (919) + + . reduce 919 + + +state 427 + interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list opt_COMPLETE_COMPLETION . (911) + + . reduce 911 + + +state 428 + interactive_statement_list : interactive_statement_list interactive_statement . (704) + + . reduce 704 + + +state 429 + declaration_statement : local_variable_declaration SEMICOLON . (740) + + . reduce 740 + + +state 430 + declaration_statement : local_constant_declaration SEMICOLON . (741) + + . reduce 741 + + +state 431 + local_variable_pointer_type : local_variable_pointer_type STAR . (748) + + . reduce 748 + + +state 432 + local_variable_type : local_variable_pointer_type opt_rank_specifier . (750) + + . reduce 750 + + +state 433 + local_variable_declarator : IDENTIFIER . ASSIGN local_variable_initializer (164) + local_variable_declarator : IDENTIFIER . (165) + local_variable_declarator : IDENTIFIER . variable_bad_array (166) + + ASSIGN shift 640 + OPEN_BRACKET_EXPR shift 641 + CLOSE_PARENS reduce 165 + COMMA reduce 165 + SEMICOLON reduce 165 + + variable_bad_array goto 642 + + +state 434 + local_variable_declarators : local_variable_declarators . COMMA local_variable_declarator (163) + local_variable_declaration : local_variable_type local_variable_declarators . (751) + + COMMA shift 643 + CLOSE_PARENS reduce 751 + SEMICOLON reduce 751 + + +state 435 + local_variable_declarators : local_variable_declarator . (162) + + . reduce 162 + + +state 436 + interactive_expression_statement : interactive_statement_expression SEMICOLON . (759) + + . reduce 759 + + +state 437 + interactive_expression_statement : interactive_statement_expression COMPLETE_COMPLETION . (760) + + . reduce 760 + + +state 438 + where_clause : WHERE . $$92 boolean_expression (880) + $$92 : . (879) + + . reduce 879 + + $$92 goto 644 + + +state 439 + from_clause : FROM . IDENTIFIER IN $$86 expression (858) + from_clause : FROM . type IDENTIFIER IN $$87 expression (860) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 645 + . error + + namespace_or_type_name goto 255 + type goto 646 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 440 + join_clause : JOIN . IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + join_clause : JOIN . type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 647 + . error + + namespace_or_type_name goto 255 + type goto 648 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 441 + let_clause : LET . IDENTIFIER ASSIGN $$91 expression (878) + + IDENTIFIER shift 649 + . error + + +state 442 + orderby_clause : ORDERBY . $$99 orderings (892) + $$99 : . (891) + + . reduce 891 + + $$99 goto 650 + + +state 443 + query_expression : first_from_clause COMPLETE_COMPLETION . (851) + + . reduce 851 + + +state 444 + query_expression : first_from_clause query_body . (849) + + . reduce 849 + + +state 445 + query_body_clause : from_clause . (872) + + . reduce 872 + + +state 446 + query_body : opt_query_body_clauses . select_or_group_clause opt_query_continuation (861) + query_body : opt_query_body_clauses . COMPLETE_COMPLETION (862) + + SELECT shift 651 + GROUP shift 652 + COMPLETE_COMPLETION shift 653 + . error + + select_or_group_clause goto 654 + + +state 447 + opt_query_body_clauses : query_body_clauses . (869) + query_body_clauses : query_body_clauses . query_body_clause (871) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + SELECT reduce 869 + GROUP reduce 869 + COMPLETE_COMPLETION reduce 869 + + from_clause goto 445 + query_body_clause goto 655 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 448 + query_body_clauses : query_body_clause . (870) + + . reduce 870 + + +state 449 + query_body_clause : let_clause . (873) + + . reduce 873 + + +state 450 + query_body_clause : where_clause . (874) + + . reduce 874 + + +state 451 + query_body_clause : join_clause . (875) + + . reduce 875 + + +state 452 + query_body_clause : orderby_clause . (876) + + . reduce 876 + + +state 453 + query_expression : nested_from_clause COMPLETE_COMPLETION . (852) + + . reduce 852 + + +state 454 + query_expression : nested_from_clause query_body . (850) + + . reduce 850 + + +state 455 + interactive_compilation_unit : outer_declarations global_attributes . (915) + + . reduce 915 + + +state 456 + qualified_identifier : qualified_identifier DOT . IDENTIFIER (28) + + IDENTIFIER shift 656 + . error + + +state 457 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 . namespace_body opt_semicolon (26) + + OPEN_BRACE shift 657 + . error + + namespace_body goto 658 + + +state 458 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type . type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 659 + + +state 459 + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + $$61 : . (368) + + . reduce 368 + + $$61 goto 660 + + +state 460 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name . opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + opt_enum_base : . (341) + + COLON shift 661 + OPEN_BRACE reduce 341 + + opt_enum_base goto 662 + + +state 461 + simple_type : VOID . (390) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 390 + OPEN_BRACE reduce 390 + OPEN_BRACKET reduce 390 + OPEN_PARENS reduce 390 + CLOSE_PARENS reduce 390 + COMMA reduce 390 + SEMICOLON reduce 390 + IDENTIFIER reduce 390 + OPEN_PARENS_CAST reduce 390 + OPEN_BRACKET_EXPR reduce 390 + + +state 462 + field_declaration : opt_attributes opt_modifiers FIXED simple_type . IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers FIXED simple_type . error SEMICOLON (143) + + error shift 663 + IDENTIFIER shift 664 + . error + + +state 463 + simple_type : type_expression . (389) + type_expression : type_expression . STAR (397) + + STAR shift 476 + error reduce 389 + OPEN_BRACE reduce 389 + OPEN_BRACKET reduce 389 + OPEN_PARENS reduce 389 + CLOSE_PARENS reduce 389 + COMMA reduce 389 + SEMICOLON reduce 389 + IDENTIFIER reduce 389 + OPEN_PARENS_CAST reduce 389 + OPEN_BRACKET_EXPR reduce 389 + + +state 464 + type_expression : VOID STAR . (398) + + . reduce 398 + + +state 465 + method_header : opt_attributes opt_modifiers PARTIAL VOID . method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 666 + qualified_alias_member goto 474 + explicit_interface goto 475 + + +state 466 + type_expression : namespace_or_type_name opt_nullable . (395) + + . reduce 395 + + +state 467 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS . $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$70 : . (648) + + . reduce 648 + + $$70 goto 667 + + +state 468 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE . $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE . error (243) + $$33 : . (238) + + error shift 668 + IDENTIFIER reduce 238 + + $$33 goto 669 + + +state 469 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT . $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT . error (110) + $$7 : . (105) + + error shift 670 + IDENTIFIER reduce 105 + + $$7 goto 671 + + +state 470 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER . $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + explicit_interface : IDENTIFIER . opt_type_argument_list DOT (375) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + $$14 : . (139) + opt_type_argument_list : . (363) + $$61 : . (368) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + OP_GENERICS_LT_DECL reduce 368 + OPEN_BRACE reduce 368 + OPEN_PARENS reduce 368 + DOT reduce 363 + COMMA reduce 139 + SEMICOLON reduce 139 + ASSIGN reduce 139 + + $$14 goto 672 + opt_type_argument_list goto 673 + $$61 goto 660 + + +state 471 + method_declaration_name : type_declaration_name . (371) + + . reduce 371 + + +state 472 + method_header : opt_attributes opt_modifiers member_type method_declaration_name . OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + + OPEN_PARENS shift 674 + . error + + +state 473 + method_header : opt_attributes opt_modifiers member_type modifiers . method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + modifiers : modifiers . modifier (658) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 675 + qualified_alias_member goto 474 + explicit_interface goto 475 + modifier goto 262 + + +state 474 + explicit_interface : qualified_alias_member . IDENTIFIER opt_type_argument_list DOT (376) + + IDENTIFIER shift 676 + . error + + +state 475 + method_declaration_name : explicit_interface . IDENTIFIER opt_type_parameter_list (372) + explicit_interface : explicit_interface . IDENTIFIER opt_type_argument_list DOT (377) + + IDENTIFIER shift 677 + . error + + +state 476 + type_expression : type_expression STAR . (397) + + . reduce 397 + + +state 477 + type_expression_or_array : type_expression rank_specifiers . (394) + + . reduce 394 + + +state 478 + type_expression : builtin_types opt_nullable . (396) + + . reduce 396 + + +state 479 + opt_type_argument_list : OP_GENERICS_LT type_arguments OP_GENERICS_GT . (364) + + . reduce 364 + + +state 480 + type_arguments : type_arguments COMMA . type (367) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 678 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 481 + using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON . (22) + + . reduce 22 + + +state 482 + member_name : namespace_or_type_name DOT IDENTIFIER opt_type_argument_list . (361) + + . reduce 361 + + +state 483 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET . (63) + + . reduce 63 + + +484: shift/reduce conflict (shift 680, reduce 363) on ASSIGN +state 484 + named_attribute_argument : IDENTIFIER . ASSIGN $$6 expression (85) + named_argument : IDENTIFIER . COLON opt_named_modifier expression (86) + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 679 + ASSIGN shift 680 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + + opt_type_argument_list goto 375 + + +state 485 + opt_attribute_arguments : OPEN_PARENS attribute_arguments . CLOSE_PARENS (76) + attribute_arguments : attribute_arguments . COMMA positional_or_named_argument (80) + attribute_arguments : attribute_arguments . COMMA named_attribute_argument (81) + + CLOSE_PARENS shift 681 + COMMA shift 682 + . error + + +state 486 + attribute_arguments : positional_or_named_argument . (78) + + . reduce 78 + + +state 487 + attribute_arguments : named_attribute_argument . (79) + + . reduce 79 + + +state 488 + positional_or_named_argument : expression . (82) + + . reduce 82 + + +state 489 + positional_or_named_argument : named_argument . (83) + + . reduce 83 + + +state 490 + base_access : BASE OPEN_BRACKET error . (504) + + . reduce 504 + + +state 491 + member_access : BASE DOT IDENTIFIER . opt_type_argument_list (454) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 683 + + +state 492 + named_argument : IDENTIFIER . COLON opt_named_modifier expression (86) + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 679 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 493 + expression_list_argument : expression . (500) + + . reduce 500 + + +state 494 + expression_list_argument : named_argument . (501) + + . reduce 501 + + +state 495 + expression_list_arguments : expression_list_arguments . COMMA expression_list_argument (499) + base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments . CLOSE_BRACKET (503) + + CLOSE_BRACKET shift 684 + COMMA shift 685 + . error + + +state 496 + expression_list_arguments : expression_list_argument . (498) + + . reduce 498 + + +state 497 + checked_expression : CHECKED open_parens_any expression . CLOSE_PARENS (557) + + CLOSE_PARENS shift 686 + . error + + +state 498 + local_constant_declarator : IDENTIFIER . ASSIGN constant_initializer_expr (755) + local_constant_declarator : IDENTIFIER . error (756) + + error shift 687 + ASSIGN shift 688 + . error + + +state 499 + local_constant_declaration : CONST variable_type local_constant_declarators . (752) + local_constant_declarators : local_constant_declarators . COMMA local_constant_declarator (754) + + COMMA shift 689 + SEMICOLON reduce 752 + + +state 500 + local_constant_declarators : local_constant_declarator . (753) + + . reduce 753 + + +state 501 + default_value_expression : DEFAULT open_parens_any type . CLOSE_PARENS (566) + + CLOSE_PARENS shift 690 + . error + + +state 502 + anonymous_method_signature : OPEN_PARENS $$65 . opt_formal_parameter_list CLOSE_PARENS (565) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 694 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 503 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 . block (561) + + OPEN_BRACE shift 143 + . error + + block goto 700 + + +state 504 + do_statement : DO embedded_statement WHILE . open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 701 + + +state 505 + expression_statement : statement_expression SEMICOLON . (757) + + . reduce 757 + + +state 506 + expression_statement : statement_expression COMPLETE_COMPLETION . (758) + + . reduce 758 + + +state 507 + fixed_statement : FIXED open_parens_any type_and_void . fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + IDENTIFIER shift 702 + . error + + fixed_pointer_declarators goto 703 + fixed_pointer_declarator goto 704 + + +state 508 + for_initializer : local_variable_declaration . (791) + + . reduce 791 + + +state 509 + statement_expression_list : statement_expression . (798) + + . reduce 798 + + +state 510 + for_statement : FOR open_parens_any opt_for_initializer . SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + SEMICOLON shift 705 + . error + + +state 511 + opt_for_initializer : for_initializer . (790) + + . reduce 790 + + +state 512 + for_initializer : statement_expression_list . (792) + statement_expression_list : statement_expression_list . COMMA statement_expression (799) + + COMMA shift 706 + SEMICOLON reduce 792 + + +state 513 + foreach_statement : FOREACH open_parens_any type . IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH open_parens_any type . IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + IN shift 707 + IDENTIFIER shift 708 + . error + + +state 514 + constant_expression : expression . (646) + + . reduce 646 + + +state 515 + goto_statement : GOTO CASE constant_expression . SEMICOLON (812) + + SEMICOLON shift 709 + . error + + +state 516 + goto_statement : GOTO DEFAULT SEMICOLON . (813) + + . reduce 813 + + +state 517 + goto_statement : GOTO IDENTIFIER SEMICOLON . (811) + + . reduce 811 + + +state 518 + boolean_expression : expression . (647) + + . reduce 647 + + +state 519 + if_statement : IF open_parens_any boolean_expression . CLOSE_PARENS embedded_statement (767) + if_statement : IF open_parens_any boolean_expression . CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + CLOSE_PARENS shift 710 + . error + + +state 520 + lock_statement : LOCK open_parens_any expression . CLOSE_PARENS embedded_statement (844) + + CLOSE_PARENS shift 711 + . error + + +state 521 + anonymous_type_parameter : error . (526) + + . reduce 526 + + +state 522 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + anonymous_type_parameter : IDENTIFIER . ASSIGN variable_initializer (523) + anonymous_type_parameter : IDENTIFIER . (524) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + ASSIGN shift 712 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + CLOSE_BRACE reduce 524 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 524 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_PTR reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + + opt_type_argument_list goto 375 + + +state 523 + primary_expression_no_array_creation : member_access . (426) + anonymous_type_parameter : member_access . (525) + + CLOSE_BRACE reduce 525 + OPEN_PARENS reduce 426 + DOT reduce 426 + COMMA reduce 525 + OP_INC reduce 426 + OP_DEC reduce 426 + OP_PTR reduce 426 + OPEN_PARENS_CAST reduce 426 + OPEN_BRACKET_EXPR reduce 426 + + +state 524 + anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma . CLOSE_BRACE (516) + + CLOSE_BRACE shift 713 + . error + + +state 525 + anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt . (517) + + . reduce 517 + + +state 526 + anonymous_type_parameters_opt_comma : anonymous_type_parameters . COMMA (518) + anonymous_type_parameters_opt : anonymous_type_parameters . (520) + anonymous_type_parameters : anonymous_type_parameters . COMMA anonymous_type_parameter (522) + + COMMA shift 714 + CLOSE_BRACE reduce 520 + + +state 527 + anonymous_type_parameters : anonymous_type_parameter . (521) + + . reduce 521 + + +state 528 + rank_specifier : OPEN_BRACKET CLOSE_BRACKET . (533) + + . reduce 533 + + +state 529 + dim_separators : COMMA . (535) + + . reduce 535 + + +state 530 + rank_specifier : OPEN_BRACKET dim_separators . CLOSE_BRACKET (534) + dim_separators : dim_separators . COMMA (536) + + CLOSE_BRACKET shift 715 + COMMA shift 716 + . error + + +state 531 + array_initializer : OPEN_BRACE . CLOSE_BRACE (539) + array_initializer : OPEN_BRACE . variable_initializer_list opt_comma CLOSE_BRACE (540) + + error shift 717 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + CLOSE_BRACE shift 718 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 721 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_initializer_list goto 722 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 532 + array_creation_expression : NEW rank_specifiers array_initializer . (511) + + . reduce 511 + + +state 533 + array_creation_expression : NEW new_expr_type error . (513) + + . reduce 513 + + +state 534 + object_or_collection_initializer : OPEN_BRACE . opt_member_initializer_list close_brace_or_complete_completion (463) + object_or_collection_initializer : OPEN_BRACE . member_initializer_list COMMA CLOSE_BRACE (464) + opt_member_initializer_list : . (465) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 723 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 724 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + GENERATE_COMPLETION shift 725 + CLOSE_BRACE reduce 465 + COMPLETE_COMPLETION reduce 465 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + opt_member_initializer_list goto 726 + member_initializer_list goto 727 + member_initializer goto 728 + non_assignment_expression goto 729 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 535 + array_creation_expression : NEW new_expr_type OPEN_BRACKET . CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + rank_specifier : OPEN_BRACKET . CLOSE_BRACKET (533) + rank_specifier : OPEN_BRACKET . dim_separators CLOSE_BRACKET (534) + + CLOSE_BRACKET shift 730 + COMMA shift 529 + . error + + dim_separators goto 530 + + +state 536 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR . expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 731 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list goto 732 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 537 + array_creation_expression : NEW new_expr_type rank_specifiers . opt_array_initializer (510) + opt_array_initializer : . (537) + + OPEN_BRACE shift 531 + error reduce 537 + AS reduce 537 + IS reduce 537 + WHERE reduce 537 + FROM reduce 537 + JOIN reduce 537 + ON reduce 537 + EQUALS reduce 537 + SELECT reduce 537 + GROUP reduce 537 + BY reduce 537 + LET reduce 537 + ORDERBY reduce 537 + ASCENDING reduce 537 + DESCENDING reduce 537 + INTO reduce 537 + CLOSE_BRACE reduce 537 + CLOSE_BRACKET reduce 537 + OPEN_PARENS reduce 537 + CLOSE_PARENS reduce 537 + DOT reduce 537 + COMMA reduce 537 + COLON reduce 537 + SEMICOLON reduce 537 + PLUS reduce 537 + MINUS reduce 537 + ASSIGN reduce 537 + OP_LT reduce 537 + OP_GT reduce 537 + BITWISE_AND reduce 537 + BITWISE_OR reduce 537 + STAR reduce 537 + PERCENT reduce 537 + DIV reduce 537 + CARRET reduce 537 + INTERR reduce 537 + OP_INC reduce 537 + OP_DEC reduce 537 + OP_SHIFT_LEFT reduce 537 + OP_SHIFT_RIGHT reduce 537 + OP_LE reduce 537 + OP_GE reduce 537 + OP_EQ reduce 537 + OP_NE reduce 537 + OP_AND reduce 537 + OP_OR reduce 537 + OP_MULT_ASSIGN reduce 537 + OP_DIV_ASSIGN reduce 537 + OP_MOD_ASSIGN reduce 537 + OP_ADD_ASSIGN reduce 537 + OP_SUB_ASSIGN reduce 537 + OP_SHIFT_LEFT_ASSIGN reduce 537 + OP_SHIFT_RIGHT_ASSIGN reduce 537 + OP_AND_ASSIGN reduce 537 + OP_XOR_ASSIGN reduce 537 + OP_OR_ASSIGN reduce 537 + OP_PTR reduce 537 + OP_COALESCING reduce 537 + OPEN_PARENS_CAST reduce 537 + OPEN_BRACKET_EXPR reduce 537 + COMPLETE_COMPLETION reduce 537 + + array_initializer goto 733 + opt_array_initializer goto 734 + + +state 538 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any . opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 735 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 539 + object_or_delegate_creation_expression : NEW new_expr_type object_or_collection_initializer . (508) + + . reduce 508 + + +state 540 + new_expr_type : $$62 simple_type . (515) + + . reduce 515 + + +state 541 + rank_specifiers : rank_specifier rank_specifiers . (532) + + . reduce 532 + + +state 542 + return_statement : RETURN opt_expression SEMICOLON . (814) + + . reduce 814 + + +state 543 + sizeof_expression : SIZEOF open_parens_any type . CLOSE_PARENS (556) + + CLOSE_PARENS shift 736 + . error + + +state 544 + switch_statement : SWITCH open_parens_any $$77 . expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 737 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 545 + throw_statement : THROW opt_expression SEMICOLON . (815) + + . reduce 815 + + +state 546 + try_statement : TRY block error . (823) + + . reduce 823 + + +state 547 + catch_clause : CATCH . opt_catch_args $$81 block (829) + opt_catch_args : . (830) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + OPEN_BRACE reduce 830 + + open_parens_any goto 738 + opt_catch_args goto 739 + catch_args goto 740 + + +state 548 + try_statement : TRY block FINALLY . block (821) + + OPEN_BRACE shift 143 + . error + + block goto 741 + + +state 549 + try_statement : TRY block catch_clauses . (820) + try_statement : TRY block catch_clauses . FINALLY block (822) + catch_clauses : catch_clauses . catch_clause (825) + + CATCH shift 547 + FINALLY shift 742 + $end reduce 820 + error reduce 820 + EOF reduce 820 + BASE reduce 820 + BOOL reduce 820 + BREAK reduce 820 + BYTE reduce 820 + CASE reduce 820 + CHAR reduce 820 + CHECKED reduce 820 + CONST reduce 820 + CONTINUE reduce 820 + DECIMAL reduce 820 + DEFAULT reduce 820 + DELEGATE reduce 820 + DO reduce 820 + DOUBLE reduce 820 + ELSE reduce 820 + FALSE reduce 820 + FIXED reduce 820 + FLOAT reduce 820 + FOR reduce 820 + FOREACH reduce 820 + GOTO reduce 820 + IF reduce 820 + INT reduce 820 + LOCK reduce 820 + LONG reduce 820 + NEW reduce 820 + NULL reduce 820 + OBJECT reduce 820 + RETURN reduce 820 + SBYTE reduce 820 + SHORT reduce 820 + SIZEOF reduce 820 + STRING reduce 820 + SWITCH reduce 820 + THIS reduce 820 + THROW reduce 820 + TRUE reduce 820 + TRY reduce 820 + TYPEOF reduce 820 + UINT reduce 820 + ULONG reduce 820 + UNCHECKED reduce 820 + UNSAFE reduce 820 + USHORT reduce 820 + USING reduce 820 + VOID reduce 820 + WHILE reduce 820 + FROM reduce 820 + FROM_FIRST reduce 820 + OPEN_BRACE reduce 820 + CLOSE_BRACE reduce 820 + OPEN_PARENS reduce 820 + SEMICOLON reduce 820 + TILDE reduce 820 + PLUS reduce 820 + MINUS reduce 820 + BANG reduce 820 + BITWISE_AND reduce 820 + STAR reduce 820 + OP_INC reduce 820 + OP_DEC reduce 820 + LITERAL reduce 820 + IDENTIFIER reduce 820 + OPEN_PARENS_LAMBDA reduce 820 + OPEN_PARENS_CAST reduce 820 + DEFAULT_COLON reduce 820 + COMPLETE_COMPLETION reduce 820 + + catch_clause goto 743 + + +state 550 + catch_clauses : catch_clause . (824) + + . reduce 824 + + +state 551 + typeof_expression : TYPEOF $$63 open_parens_any . typeof_type_expression CLOSE_PARENS (545) + + error shift 744 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 745 + . error + + namespace_or_type_name goto 746 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 747 + type_name goto 38 + type_and_void goto 748 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + typeof_type_expression goto 749 + unbound_type_name goto 750 + + +state 552 + unchecked_expression : UNCHECKED open_parens_any expression . CLOSE_PARENS (558) + + CLOSE_PARENS shift 751 + . error + + +state 553 + unsafe_statement : UNSAFE $$82 block . (837) + + . reduce 837 + + +state 554 + using_statement : USING open_parens_any expression . CLOSE_PARENS $$85 embedded_statement (848) + + CLOSE_PARENS shift 752 + . error + + +state 555 + using_statement : USING open_parens_any local_variable_declaration . CLOSE_PARENS $$84 embedded_statement (846) + + CLOSE_PARENS shift 753 + . error + + +state 556 + while_statement : WHILE open_parens_any boolean_expression . CLOSE_PARENS embedded_statement (785) + + CLOSE_PARENS shift 754 + . error + + +state 557 + nested_from_clause : FROM IDENTIFIER IN . expression (855) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 755 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 558 + nested_from_clause : FROM type IDENTIFIER . IN expression (856) + + IN shift 756 + . error + + +state 559 + first_from_clause : FROM_FIRST IDENTIFIER IN . expression (853) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 757 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 560 + first_from_clause : FROM_FIRST type IDENTIFIER . IN expression (854) + + IN shift 758 + . error + + +state 561 + block : OPEN_BRACE $$74 opt_statement_list . block_end (691) + + CLOSE_BRACE shift 759 + COMPLETE_COMPLETION shift 760 + . error + + block_end goto 761 + + +state 562 + opt_statement_list : statement_list . (697) + statement_list : statement_list . statement (699) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 697 + COMPLETE_COMPLETION reduce 697 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 762 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 563 + statement_list : statement . (698) + + . reduce 698 + + +state 564 + statement : declaration_statement . (700) + + . reduce 700 + + +state 565 + statement : valid_declaration_statement . (701) + + . reduce 701 + + +state 566 + statement : labeled_statement . (702) + + . reduce 702 + + +state 567 + parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS . (450) + + . reduce 450 + + +state 568 + parenthesized_expression : OPEN_PARENS expression COMPLETE_COMPLETION . (451) + + . reduce 451 + + +state 569 + cast_expression : OPEN_PARENS builtin_types CLOSE_PARENS . prefixed_unary_expression (572) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 763 + cast_expression goto 188 + + +state 570 + yield_statement : IDENTIFIER BREAK SEMICOLON . (817) + + . reduce 817 + + +state 571 + yield_statement : IDENTIFIER RETURN opt_expression . SEMICOLON (816) + + SEMICOLON shift 764 + . error + + +state 572 + lambda_expression : IDENTIFIER ARROW $$67 . lambda_expression_body (637) + $$66 : . (633) + + OPEN_BRACE shift 143 + BASE reduce 633 + BOOL reduce 633 + BYTE reduce 633 + CHAR reduce 633 + CHECKED reduce 633 + DECIMAL reduce 633 + DEFAULT reduce 633 + DELEGATE reduce 633 + DOUBLE reduce 633 + FALSE reduce 633 + FLOAT reduce 633 + INT reduce 633 + LONG reduce 633 + NEW reduce 633 + NULL reduce 633 + OBJECT reduce 633 + SBYTE reduce 633 + SHORT reduce 633 + SIZEOF reduce 633 + STRING reduce 633 + THIS reduce 633 + TRUE reduce 633 + TYPEOF reduce 633 + UINT reduce 633 + ULONG reduce 633 + UNCHECKED reduce 633 + USHORT reduce 633 + FROM reduce 633 + FROM_FIRST reduce 633 + OPEN_PARENS reduce 633 + TILDE reduce 633 + PLUS reduce 633 + MINUS reduce 633 + BANG reduce 633 + BITWISE_AND reduce 633 + STAR reduce 633 + OP_INC reduce 633 + OP_DEC reduce 633 + LITERAL reduce 633 + IDENTIFIER reduce 633 + OPEN_PARENS_LAMBDA reduce 633 + OPEN_PARENS_CAST reduce 633 + + block goto 765 + lambda_expression_body goto 766 + $$66 goto 767 + + +state 573 + labeled_statement : IDENTIFIER COLON $$76 . statement (739) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 768 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 574 + parameter_modifier : OUT . (209) + + . reduce 209 + + +state 575 + parameter_modifier : REF . (208) + + . reduce 208 + + +state 576 + parameter_modifier : THIS . (210) + + . reduce 210 + + +state 577 + parameter_type : VOID . (392) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 392 + IDENTIFIER reduce 392 + + +state 578 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_parameter : IDENTIFIER . (630) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 630 + DOT reduce 363 + COMMA reduce 630 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 579 + lambda_parameter : parameter_type . IDENTIFIER (629) + + IDENTIFIER shift 769 + . error + + +state 580 + lambda_parameter : parameter_modifier . parameter_type IDENTIFIER (628) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + parameter_type goto 770 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 581 + parameter_type : type_expression_or_array . (391) + + . reduce 391 + + +state 582 + lambda_parameter_list : lambda_parameter_list . COMMA lambda_parameter (627) + opt_lambda_parameter_list : lambda_parameter_list . (632) + + COMMA shift 771 + CLOSE_PARENS reduce 632 + + +state 583 + lambda_parameter_list : lambda_parameter . (626) + + . reduce 626 + + +state 584 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list . CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + + CLOSE_PARENS shift 772 + . error + + +state 585 + cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS . prefixed_unary_expression (571) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 773 + cast_expression goto 188 + + +state 586 + member_access : qualified_alias_member IDENTIFIER opt_type_argument_list . (455) + + . reduce 455 + + +state 587 + member_access : builtin_types DOT IDENTIFIER . opt_type_argument_list (453) + member_access : builtin_types DOT IDENTIFIER . GENERATE_COMPLETION (459) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERATE_COMPLETION shift 774 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 775 + + +state 588 + member_access : builtin_types DOT GENERATE_COMPLETION . (458) + + . reduce 458 + + +state 589 + opt_rank_specifier_or_nullable : opt_nullable rank_specifiers . (530) + + . reduce 530 + + +state 590 + member_access : primary_expression DOT IDENTIFIER . opt_type_argument_list (452) + member_access : primary_expression DOT IDENTIFIER . GENERATE_COMPLETION (457) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERATE_COMPLETION shift 776 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 777 + + +state 591 + member_access : primary_expression DOT GENERATE_COMPLETION . (456) + + . reduce 456 + + +state 592 + pointer_member_access : primary_expression OP_PTR IDENTIFIER . (559) + + . reduce 559 + + +state 593 + element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments . CLOSE_BRACKET (494) + expression_list_arguments : expression_list_arguments . COMMA expression_list_argument (499) + + CLOSE_BRACKET shift 778 + COMMA shift 685 + . error + + +state 594 + non_simple_argument : OUT . variable_reference (489) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 779 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_reference goto 780 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 595 + non_simple_argument : REF . variable_reference (488) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 779 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_reference goto 781 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 596 + non_simple_argument : ARGLIST . OPEN_PARENS argument_list CLOSE_PARENS (490) + non_simple_argument : ARGLIST . OPEN_PARENS CLOSE_PARENS (491) + non_simple_argument : ARGLIST . (492) + + OPEN_PARENS shift 782 + CLOSE_PARENS reduce 492 + COMMA reduce 492 + COMPLETE_COMPLETION reduce 492 + + +state 597 + argument_list : COMMA . error (483) + + error shift 783 + . error + + +state 598 + argument : expression . (484) + + . reduce 484 + + +state 599 + argument_or_named_argument : named_argument . (487) + + . reduce 487 + + +state 600 + invocation_expression : primary_expression open_parens_any opt_argument_list . close_parens (460) + + CLOSE_PARENS shift 784 + COMPLETE_COMPLETION shift 785 + . error + + close_parens goto 786 + + +state 601 + opt_argument_list : argument_list . (478) + argument_list : argument_list . COMMA argument (480) + argument_list : argument_list . COMMA named_argument (481) + argument_list : argument_list . COMMA (482) + + COMMA shift 787 + CLOSE_PARENS reduce 478 + COMPLETE_COMPLETION reduce 478 + + +state 602 + argument_list : argument_or_named_argument . (479) + + . reduce 479 + + +state 603 + argument_or_named_argument : argument . (486) + + . reduce 486 + + +state 604 + argument : non_simple_argument . (485) + + . reduce 485 + + +state 605 + multiplicative_expression : prefixed_unary_expression . (580) + + . reduce 580 + + +state 606 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : parenthesized_expression MINUS multiplicative_expression . (587) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 587 + AS reduce 587 + IS reduce 587 + WHERE reduce 587 + FROM reduce 587 + JOIN reduce 587 + ON reduce 587 + EQUALS reduce 587 + SELECT reduce 587 + GROUP reduce 587 + BY reduce 587 + LET reduce 587 + ORDERBY reduce 587 + ASCENDING reduce 587 + DESCENDING reduce 587 + INTO reduce 587 + CLOSE_BRACE reduce 587 + CLOSE_BRACKET reduce 587 + CLOSE_PARENS reduce 587 + COMMA reduce 587 + COLON reduce 587 + SEMICOLON reduce 587 + PLUS reduce 587 + MINUS reduce 587 + OP_LT reduce 587 + OP_GT reduce 587 + BITWISE_AND reduce 587 + BITWISE_OR reduce 587 + CARRET reduce 587 + INTERR reduce 587 + OP_SHIFT_LEFT reduce 587 + OP_SHIFT_RIGHT reduce 587 + OP_LE reduce 587 + OP_GE reduce 587 + OP_EQ reduce 587 + OP_NE reduce 587 + OP_AND reduce 587 + OP_OR reduce 587 + OP_COALESCING reduce 587 + COMPLETE_COMPLETION reduce 587 + + +state 607 + assignment_expression : prefixed_unary_expression ASSIGN expression . (615) + + . reduce 615 + + +state 608 + assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN expression . (616) + + . reduce 616 + + +state 609 + assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN expression . (617) + + . reduce 617 + + +state 610 + assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN expression . (618) + + . reduce 618 + + +state 611 + assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN expression . (619) + + . reduce 619 + + +state 612 + assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN expression . (620) + + . reduce 620 + + +state 613 + assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression . (621) + + . reduce 621 + + +state 614 + assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression . (622) + + . reduce 622 + + +state 615 + assignment_expression : prefixed_unary_expression OP_AND_ASSIGN expression . (623) + + . reduce 623 + + +state 616 + assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN expression . (625) + + . reduce 625 + + +state 617 + assignment_expression : prefixed_unary_expression OP_OR_ASSIGN expression . (624) + + . reduce 624 + + +state 618 + multiplicative_expression : multiplicative_expression STAR prefixed_unary_expression . (581) + + . reduce 581 + + +state 619 + multiplicative_expression : multiplicative_expression PERCENT prefixed_unary_expression . (583) + + . reduce 583 + + +state 620 + multiplicative_expression : multiplicative_expression DIV prefixed_unary_expression . (582) + + . reduce 582 + + +state 621 + additive_expression : additive_expression AS type . (588) + + . reduce 588 + + +state 622 + additive_expression : additive_expression IS type . (589) + + . reduce 589 + + +state 623 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : additive_expression PLUS multiplicative_expression . (585) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 585 + AS reduce 585 + IS reduce 585 + WHERE reduce 585 + FROM reduce 585 + JOIN reduce 585 + ON reduce 585 + EQUALS reduce 585 + SELECT reduce 585 + GROUP reduce 585 + BY reduce 585 + LET reduce 585 + ORDERBY reduce 585 + ASCENDING reduce 585 + DESCENDING reduce 585 + INTO reduce 585 + CLOSE_BRACE reduce 585 + CLOSE_BRACKET reduce 585 + CLOSE_PARENS reduce 585 + COMMA reduce 585 + COLON reduce 585 + SEMICOLON reduce 585 + PLUS reduce 585 + MINUS reduce 585 + OP_LT reduce 585 + OP_GT reduce 585 + BITWISE_AND reduce 585 + BITWISE_OR reduce 585 + CARRET reduce 585 + INTERR reduce 585 + OP_SHIFT_LEFT reduce 585 + OP_SHIFT_RIGHT reduce 585 + OP_LE reduce 585 + OP_GE reduce 585 + OP_EQ reduce 585 + OP_NE reduce 585 + OP_AND reduce 585 + OP_OR reduce 585 + OP_COALESCING reduce 585 + COMPLETE_COMPLETION reduce 585 + + +state 624 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : additive_expression MINUS multiplicative_expression . (586) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 586 + AS reduce 586 + IS reduce 586 + WHERE reduce 586 + FROM reduce 586 + JOIN reduce 586 + ON reduce 586 + EQUALS reduce 586 + SELECT reduce 586 + GROUP reduce 586 + BY reduce 586 + LET reduce 586 + ORDERBY reduce 586 + ASCENDING reduce 586 + DESCENDING reduce 586 + INTO reduce 586 + CLOSE_BRACE reduce 586 + CLOSE_BRACKET reduce 586 + CLOSE_PARENS reduce 586 + COMMA reduce 586 + COLON reduce 586 + SEMICOLON reduce 586 + PLUS reduce 586 + MINUS reduce 586 + OP_LT reduce 586 + OP_GT reduce 586 + BITWISE_AND reduce 586 + BITWISE_OR reduce 586 + CARRET reduce 586 + INTERR reduce 586 + OP_SHIFT_LEFT reduce 586 + OP_SHIFT_RIGHT reduce 586 + OP_LE reduce 586 + OP_GE reduce 586 + OP_EQ reduce 586 + OP_NE reduce 586 + OP_AND reduce 586 + OP_OR reduce 586 + OP_COALESCING reduce 586 + COMPLETE_COMPLETION reduce 586 + + +state 625 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : shift_expression OP_SHIFT_LEFT additive_expression . (591) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 591 + WHERE reduce 591 + FROM reduce 591 + JOIN reduce 591 + ON reduce 591 + EQUALS reduce 591 + SELECT reduce 591 + GROUP reduce 591 + BY reduce 591 + LET reduce 591 + ORDERBY reduce 591 + ASCENDING reduce 591 + DESCENDING reduce 591 + INTO reduce 591 + CLOSE_BRACE reduce 591 + CLOSE_BRACKET reduce 591 + CLOSE_PARENS reduce 591 + COMMA reduce 591 + COLON reduce 591 + SEMICOLON reduce 591 + OP_LT reduce 591 + OP_GT reduce 591 + BITWISE_AND reduce 591 + BITWISE_OR reduce 591 + CARRET reduce 591 + INTERR reduce 591 + OP_SHIFT_LEFT reduce 591 + OP_SHIFT_RIGHT reduce 591 + OP_LE reduce 591 + OP_GE reduce 591 + OP_EQ reduce 591 + OP_NE reduce 591 + OP_AND reduce 591 + OP_OR reduce 591 + OP_COALESCING reduce 591 + COMPLETE_COMPLETION reduce 591 + + +state 626 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : shift_expression OP_SHIFT_RIGHT additive_expression . (592) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 592 + WHERE reduce 592 + FROM reduce 592 + JOIN reduce 592 + ON reduce 592 + EQUALS reduce 592 + SELECT reduce 592 + GROUP reduce 592 + BY reduce 592 + LET reduce 592 + ORDERBY reduce 592 + ASCENDING reduce 592 + DESCENDING reduce 592 + INTO reduce 592 + CLOSE_BRACE reduce 592 + CLOSE_BRACKET reduce 592 + CLOSE_PARENS reduce 592 + COMMA reduce 592 + COLON reduce 592 + SEMICOLON reduce 592 + OP_LT reduce 592 + OP_GT reduce 592 + BITWISE_AND reduce 592 + BITWISE_OR reduce 592 + CARRET reduce 592 + INTERR reduce 592 + OP_SHIFT_LEFT reduce 592 + OP_SHIFT_RIGHT reduce 592 + OP_LE reduce 592 + OP_GE reduce 592 + OP_EQ reduce 592 + OP_NE reduce 592 + OP_AND reduce 592 + OP_OR reduce 592 + OP_COALESCING reduce 592 + COMPLETE_COMPLETION reduce 592 + + +state 627 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_LT shift_expression . (594) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 594 + WHERE reduce 594 + FROM reduce 594 + JOIN reduce 594 + ON reduce 594 + EQUALS reduce 594 + SELECT reduce 594 + GROUP reduce 594 + BY reduce 594 + LET reduce 594 + ORDERBY reduce 594 + ASCENDING reduce 594 + DESCENDING reduce 594 + INTO reduce 594 + CLOSE_BRACE reduce 594 + CLOSE_BRACKET reduce 594 + CLOSE_PARENS reduce 594 + COMMA reduce 594 + COLON reduce 594 + SEMICOLON reduce 594 + OP_LT reduce 594 + OP_GT reduce 594 + BITWISE_AND reduce 594 + BITWISE_OR reduce 594 + CARRET reduce 594 + INTERR reduce 594 + OP_LE reduce 594 + OP_GE reduce 594 + OP_EQ reduce 594 + OP_NE reduce 594 + OP_AND reduce 594 + OP_OR reduce 594 + OP_COALESCING reduce 594 + COMPLETE_COMPLETION reduce 594 + + +state 628 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_GT shift_expression . (595) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 595 + WHERE reduce 595 + FROM reduce 595 + JOIN reduce 595 + ON reduce 595 + EQUALS reduce 595 + SELECT reduce 595 + GROUP reduce 595 + BY reduce 595 + LET reduce 595 + ORDERBY reduce 595 + ASCENDING reduce 595 + DESCENDING reduce 595 + INTO reduce 595 + CLOSE_BRACE reduce 595 + CLOSE_BRACKET reduce 595 + CLOSE_PARENS reduce 595 + COMMA reduce 595 + COLON reduce 595 + SEMICOLON reduce 595 + OP_LT reduce 595 + OP_GT reduce 595 + BITWISE_AND reduce 595 + BITWISE_OR reduce 595 + CARRET reduce 595 + INTERR reduce 595 + OP_LE reduce 595 + OP_GE reduce 595 + OP_EQ reduce 595 + OP_NE reduce 595 + OP_AND reduce 595 + OP_OR reduce 595 + OP_COALESCING reduce 595 + COMPLETE_COMPLETION reduce 595 + + +state 629 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_LE shift_expression . (596) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 596 + WHERE reduce 596 + FROM reduce 596 + JOIN reduce 596 + ON reduce 596 + EQUALS reduce 596 + SELECT reduce 596 + GROUP reduce 596 + BY reduce 596 + LET reduce 596 + ORDERBY reduce 596 + ASCENDING reduce 596 + DESCENDING reduce 596 + INTO reduce 596 + CLOSE_BRACE reduce 596 + CLOSE_BRACKET reduce 596 + CLOSE_PARENS reduce 596 + COMMA reduce 596 + COLON reduce 596 + SEMICOLON reduce 596 + OP_LT reduce 596 + OP_GT reduce 596 + BITWISE_AND reduce 596 + BITWISE_OR reduce 596 + CARRET reduce 596 + INTERR reduce 596 + OP_LE reduce 596 + OP_GE reduce 596 + OP_EQ reduce 596 + OP_NE reduce 596 + OP_AND reduce 596 + OP_OR reduce 596 + OP_COALESCING reduce 596 + COMPLETE_COMPLETION reduce 596 + + +state 630 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_GE shift_expression . (597) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 597 + WHERE reduce 597 + FROM reduce 597 + JOIN reduce 597 + ON reduce 597 + EQUALS reduce 597 + SELECT reduce 597 + GROUP reduce 597 + BY reduce 597 + LET reduce 597 + ORDERBY reduce 597 + ASCENDING reduce 597 + DESCENDING reduce 597 + INTO reduce 597 + CLOSE_BRACE reduce 597 + CLOSE_BRACKET reduce 597 + CLOSE_PARENS reduce 597 + COMMA reduce 597 + COLON reduce 597 + SEMICOLON reduce 597 + OP_LT reduce 597 + OP_GT reduce 597 + BITWISE_AND reduce 597 + BITWISE_OR reduce 597 + CARRET reduce 597 + INTERR reduce 597 + OP_LE reduce 597 + OP_GE reduce 597 + OP_EQ reduce 597 + OP_NE reduce 597 + OP_AND reduce 597 + OP_OR reduce 597 + OP_COALESCING reduce 597 + COMPLETE_COMPLETION reduce 597 + + +state 631 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : equality_expression OP_EQ relational_expression . (599) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 599 + WHERE reduce 599 + FROM reduce 599 + JOIN reduce 599 + ON reduce 599 + EQUALS reduce 599 + SELECT reduce 599 + GROUP reduce 599 + BY reduce 599 + LET reduce 599 + ORDERBY reduce 599 + ASCENDING reduce 599 + DESCENDING reduce 599 + INTO reduce 599 + CLOSE_BRACE reduce 599 + CLOSE_BRACKET reduce 599 + CLOSE_PARENS reduce 599 + COMMA reduce 599 + COLON reduce 599 + SEMICOLON reduce 599 + BITWISE_AND reduce 599 + BITWISE_OR reduce 599 + CARRET reduce 599 + INTERR reduce 599 + OP_EQ reduce 599 + OP_NE reduce 599 + OP_AND reduce 599 + OP_OR reduce 599 + OP_COALESCING reduce 599 + COMPLETE_COMPLETION reduce 599 + + +state 632 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : equality_expression OP_NE relational_expression . (600) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 600 + WHERE reduce 600 + FROM reduce 600 + JOIN reduce 600 + ON reduce 600 + EQUALS reduce 600 + SELECT reduce 600 + GROUP reduce 600 + BY reduce 600 + LET reduce 600 + ORDERBY reduce 600 + ASCENDING reduce 600 + DESCENDING reduce 600 + INTO reduce 600 + CLOSE_BRACE reduce 600 + CLOSE_BRACKET reduce 600 + CLOSE_PARENS reduce 600 + COMMA reduce 600 + COLON reduce 600 + SEMICOLON reduce 600 + BITWISE_AND reduce 600 + BITWISE_OR reduce 600 + CARRET reduce 600 + INTERR reduce 600 + OP_EQ reduce 600 + OP_NE reduce 600 + OP_AND reduce 600 + OP_OR reduce 600 + OP_COALESCING reduce 600 + COMPLETE_COMPLETION reduce 600 + + +state 633 + equality_expression : equality_expression . OP_EQ relational_expression (599) + equality_expression : equality_expression . OP_NE relational_expression (600) + and_expression : and_expression BITWISE_AND equality_expression . (602) + + OP_EQ shift 417 + OP_NE shift 418 + error reduce 602 + WHERE reduce 602 + FROM reduce 602 + JOIN reduce 602 + ON reduce 602 + EQUALS reduce 602 + SELECT reduce 602 + GROUP reduce 602 + BY reduce 602 + LET reduce 602 + ORDERBY reduce 602 + ASCENDING reduce 602 + DESCENDING reduce 602 + INTO reduce 602 + CLOSE_BRACE reduce 602 + CLOSE_BRACKET reduce 602 + CLOSE_PARENS reduce 602 + COMMA reduce 602 + COLON reduce 602 + SEMICOLON reduce 602 + BITWISE_AND reduce 602 + BITWISE_OR reduce 602 + CARRET reduce 602 + INTERR reduce 602 + OP_AND reduce 602 + OP_OR reduce 602 + OP_COALESCING reduce 602 + COMPLETE_COMPLETION reduce 602 + + +state 634 + and_expression : and_expression . BITWISE_AND equality_expression (602) + exclusive_or_expression : exclusive_or_expression CARRET and_expression . (604) + + BITWISE_AND shift 419 + error reduce 604 + WHERE reduce 604 + FROM reduce 604 + JOIN reduce 604 + ON reduce 604 + EQUALS reduce 604 + SELECT reduce 604 + GROUP reduce 604 + BY reduce 604 + LET reduce 604 + ORDERBY reduce 604 + ASCENDING reduce 604 + DESCENDING reduce 604 + INTO reduce 604 + CLOSE_BRACE reduce 604 + CLOSE_BRACKET reduce 604 + CLOSE_PARENS reduce 604 + COMMA reduce 604 + COLON reduce 604 + SEMICOLON reduce 604 + BITWISE_OR reduce 604 + CARRET reduce 604 + INTERR reduce 604 + OP_AND reduce 604 + OP_OR reduce 604 + OP_COALESCING reduce 604 + COMPLETE_COMPLETION reduce 604 + + +state 635 + exclusive_or_expression : exclusive_or_expression . CARRET and_expression (604) + inclusive_or_expression : inclusive_or_expression BITWISE_OR exclusive_or_expression . (606) + + CARRET shift 420 + error reduce 606 + WHERE reduce 606 + FROM reduce 606 + JOIN reduce 606 + ON reduce 606 + EQUALS reduce 606 + SELECT reduce 606 + GROUP reduce 606 + BY reduce 606 + LET reduce 606 + ORDERBY reduce 606 + ASCENDING reduce 606 + DESCENDING reduce 606 + INTO reduce 606 + CLOSE_BRACE reduce 606 + CLOSE_BRACKET reduce 606 + CLOSE_PARENS reduce 606 + COMMA reduce 606 + COLON reduce 606 + SEMICOLON reduce 606 + BITWISE_OR reduce 606 + INTERR reduce 606 + OP_AND reduce 606 + OP_OR reduce 606 + OP_COALESCING reduce 606 + COMPLETE_COMPLETION reduce 606 + + +state 636 + inclusive_or_expression : inclusive_or_expression . BITWISE_OR exclusive_or_expression (606) + conditional_and_expression : conditional_and_expression OP_AND inclusive_or_expression . (608) + + BITWISE_OR shift 421 + error reduce 608 + WHERE reduce 608 + FROM reduce 608 + JOIN reduce 608 + ON reduce 608 + EQUALS reduce 608 + SELECT reduce 608 + GROUP reduce 608 + BY reduce 608 + LET reduce 608 + ORDERBY reduce 608 + ASCENDING reduce 608 + DESCENDING reduce 608 + INTO reduce 608 + CLOSE_BRACE reduce 608 + CLOSE_BRACKET reduce 608 + CLOSE_PARENS reduce 608 + COMMA reduce 608 + COLON reduce 608 + SEMICOLON reduce 608 + INTERR reduce 608 + OP_AND reduce 608 + OP_OR reduce 608 + OP_COALESCING reduce 608 + COMPLETE_COMPLETION reduce 608 + + +state 637 + conditional_and_expression : conditional_and_expression . OP_AND inclusive_or_expression (608) + conditional_or_expression : conditional_or_expression OP_OR conditional_and_expression . (610) + + OP_AND shift 422 + error reduce 610 + WHERE reduce 610 + FROM reduce 610 + JOIN reduce 610 + ON reduce 610 + EQUALS reduce 610 + SELECT reduce 610 + GROUP reduce 610 + BY reduce 610 + LET reduce 610 + ORDERBY reduce 610 + ASCENDING reduce 610 + DESCENDING reduce 610 + INTO reduce 610 + CLOSE_BRACE reduce 610 + CLOSE_BRACKET reduce 610 + CLOSE_PARENS reduce 610 + COMMA reduce 610 + COLON reduce 610 + SEMICOLON reduce 610 + INTERR reduce 610 + OP_OR reduce 610 + OP_COALESCING reduce 610 + COMPLETE_COMPLETION reduce 610 + + +state 638 + null_coalescing_expression : conditional_or_expression OP_COALESCING null_coalescing_expression . (612) + + . reduce 612 + + +state 639 + conditional_expression : null_coalescing_expression INTERR expression . COLON expression (614) + + COLON shift 788 + . error + + +state 640 + local_variable_declarator : IDENTIFIER ASSIGN . local_variable_initializer (164) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STACKALLOC shift 789 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 790 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 791 + array_initializer goto 792 + local_variable_initializer goto 793 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 641 + variable_bad_array : OPEN_BRACKET_EXPR . opt_expression CLOSE_BRACKET (172) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACKET reduce 818 + + expression goto 338 + opt_expression goto 794 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 642 + local_variable_declarator : IDENTIFIER variable_bad_array . (166) + + . reduce 166 + + +state 643 + local_variable_declarators : local_variable_declarators COMMA . local_variable_declarator (163) + + IDENTIFIER shift 433 + . error + + local_variable_declarator goto 795 + + +state 644 + where_clause : WHERE $$92 . boolean_expression (880) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 796 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 645 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + from_clause : FROM IDENTIFIER . IN $$86 expression (858) + opt_type_argument_list : . (363) + + IN shift 797 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 646 + from_clause : FROM type . IDENTIFIER IN $$87 expression (860) + + IDENTIFIER shift 798 + . error + + +state 647 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + join_clause : JOIN IDENTIFIER . IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + opt_type_argument_list : . (363) + + IN shift 799 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 648 + join_clause : JOIN type . IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + IDENTIFIER shift 800 + . error + + +state 649 + let_clause : LET IDENTIFIER . ASSIGN $$91 expression (878) + + ASSIGN shift 801 + . error + + +state 650 + orderby_clause : ORDERBY $$99 . orderings (892) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 802 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + orderings goto 803 + order_by goto 804 + + +state 651 + select_or_group_clause : SELECT . $$88 expression (864) + $$88 : . (863) + + . reduce 863 + + $$88 goto 805 + + +state 652 + select_or_group_clause : GROUP . $$89 expression $$90 BY expression (867) + $$89 : . (865) + + . reduce 865 + + $$89 goto 806 + + +state 653 + query_body : opt_query_body_clauses COMPLETE_COMPLETION . (862) + + . reduce 862 + + +654: shift/reduce conflict (shift 807, reduce 905) on INTO +state 654 + query_body : opt_query_body_clauses select_or_group_clause . opt_query_continuation (861) + opt_query_continuation : . (905) + + INTO shift 807 + error reduce 905 + WHERE reduce 905 + FROM reduce 905 + JOIN reduce 905 + ON reduce 905 + EQUALS reduce 905 + SELECT reduce 905 + GROUP reduce 905 + BY reduce 905 + LET reduce 905 + ORDERBY reduce 905 + ASCENDING reduce 905 + DESCENDING reduce 905 + CLOSE_BRACE reduce 905 + CLOSE_BRACKET reduce 905 + CLOSE_PARENS reduce 905 + COMMA reduce 905 + COLON reduce 905 + SEMICOLON reduce 905 + COMPLETE_COMPLETION reduce 905 + + opt_query_continuation goto 808 + + +state 655 + query_body_clauses : query_body_clauses query_body_clause . (871) + + . reduce 871 + + +state 656 + qualified_identifier : qualified_identifier DOT IDENTIFIER . (28) + + . reduce 28 + + +state 657 + namespace_body : OPEN_BRACE . $$3 namespace_body_body (36) + $$3 : . (35) + + . reduce 35 + + $$3 goto 809 + + +state 658 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body . opt_semicolon (26) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 811 + + +state 659 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name . OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + OPEN_PARENS shift 812 + . error + + +state 660 + type_declaration_name : IDENTIFIER $$61 . opt_type_parameter_list (369) + opt_type_parameter_list : . (378) + + OP_GENERICS_LT_DECL shift 813 + WHERE reduce 378 + OPEN_BRACE reduce 378 + OPEN_PARENS reduce 378 + COMMA reduce 378 + COLON reduce 378 + SEMICOLON reduce 378 + ASSIGN reduce 378 + + opt_type_parameter_list goto 814 + + +state 661 + opt_enum_base : COLON . type (342) + opt_enum_base : COLON . error (343) + + error shift 815 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 816 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 662 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base . $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + $$54 : . (337) + + . reduce 337 + + $$54 goto 817 + + +state 663 + field_declaration : opt_attributes opt_modifiers FIXED simple_type error . SEMICOLON (143) + + SEMICOLON shift 818 + . error + + +state 664 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER . $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + $$15 : . (141) + + . reduce 141 + + $$15 goto 819 + + +state 665 + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + explicit_interface : IDENTIFIER . opt_type_argument_list DOT (375) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + $$61 : . (368) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + OP_GENERICS_LT_DECL reduce 368 + OPEN_BRACE reduce 368 + OPEN_PARENS reduce 368 + DOT reduce 363 + COMMA reduce 368 + SEMICOLON reduce 368 + ASSIGN reduce 368 + + opt_type_argument_list goto 673 + $$61 goto 660 + + +state 666 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name . OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + OPEN_PARENS shift 820 + . error + + +state 667 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 . type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 821 + + +state 668 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE error . (243) + + . reduce 243 + + +state 669 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 . type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 822 + + +state 670 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error . (110) + + . reduce 110 + + +state 671 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 . type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 823 + + +state 672 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 . opt_field_initializer opt_field_declarators SEMICOLON (140) + opt_field_initializer : . (144) + + ASSIGN shift 824 + COMMA reduce 144 + SEMICOLON reduce 144 + + opt_field_initializer goto 825 + + +state 673 + explicit_interface : IDENTIFIER opt_type_argument_list . DOT (375) + + DOT shift 826 + . error + + +state 674 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS . $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + $$20 : . (177) + + . reduce 177 + + $$20 goto 827 + + +state 675 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name . OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + + OPEN_PARENS shift 828 + . error + + +state 676 + explicit_interface : qualified_alias_member IDENTIFIER . opt_type_argument_list DOT (376) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOT reduce 363 + + opt_type_argument_list goto 829 + + +state 677 + method_declaration_name : explicit_interface IDENTIFIER . opt_type_parameter_list (372) + explicit_interface : explicit_interface IDENTIFIER . opt_type_argument_list DOT (377) + opt_type_argument_list : . (363) + opt_type_parameter_list : . (378) + + OP_GENERICS_LT shift 81 + OP_GENERICS_LT_DECL shift 813 + OPEN_BRACE reduce 378 + OPEN_PARENS reduce 378 + DOT reduce 363 + COMMA reduce 378 + SEMICOLON reduce 378 + ASSIGN reduce 378 + + opt_type_argument_list goto 830 + opt_type_parameter_list goto 831 + + +state 678 + type_arguments : type_arguments COMMA type . (367) + + . reduce 367 + + +state 679 + named_argument : IDENTIFIER COLON . opt_named_modifier expression (86) + opt_named_modifier : . (87) + + OUT shift 832 + REF shift 833 + BASE reduce 87 + BOOL reduce 87 + BYTE reduce 87 + CHAR reduce 87 + CHECKED reduce 87 + DECIMAL reduce 87 + DEFAULT reduce 87 + DELEGATE reduce 87 + DOUBLE reduce 87 + FALSE reduce 87 + FLOAT reduce 87 + INT reduce 87 + LONG reduce 87 + NEW reduce 87 + NULL reduce 87 + OBJECT reduce 87 + SBYTE reduce 87 + SHORT reduce 87 + SIZEOF reduce 87 + STRING reduce 87 + THIS reduce 87 + TRUE reduce 87 + TYPEOF reduce 87 + UINT reduce 87 + ULONG reduce 87 + UNCHECKED reduce 87 + USHORT reduce 87 + FROM reduce 87 + FROM_FIRST reduce 87 + OPEN_PARENS reduce 87 + TILDE reduce 87 + PLUS reduce 87 + MINUS reduce 87 + BANG reduce 87 + BITWISE_AND reduce 87 + STAR reduce 87 + OP_INC reduce 87 + OP_DEC reduce 87 + LITERAL reduce 87 + IDENTIFIER reduce 87 + OPEN_PARENS_LAMBDA reduce 87 + OPEN_PARENS_CAST reduce 87 + + opt_named_modifier goto 834 + + +state 680 + named_attribute_argument : IDENTIFIER ASSIGN . $$6 expression (85) + $$6 : . (84) + + . reduce 84 + + $$6 goto 835 + + +state 681 + opt_attribute_arguments : OPEN_PARENS attribute_arguments CLOSE_PARENS . (76) + + . reduce 76 + + +state 682 + attribute_arguments : attribute_arguments COMMA . positional_or_named_argument (80) + attribute_arguments : attribute_arguments COMMA . named_attribute_argument (81) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 484 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + positional_or_named_argument goto 836 + named_attribute_argument goto 837 + expression goto 488 + named_argument goto 489 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 683 + member_access : BASE DOT IDENTIFIER opt_type_argument_list . (454) + + . reduce 454 + + +state 684 + base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET . (503) + + . reduce 503 + + +state 685 + expression_list_arguments : expression_list_arguments COMMA . expression_list_argument (499) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_argument goto 838 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 686 + checked_expression : CHECKED open_parens_any expression CLOSE_PARENS . (557) + + . reduce 557 + + +state 687 + local_constant_declarator : IDENTIFIER error . (756) + + . reduce 756 + + +state 688 + local_constant_declarator : IDENTIFIER ASSIGN . constant_initializer_expr (755) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_initializer_expr goto 839 + constant_expression goto 840 + array_initializer goto 841 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 689 + local_constant_declarators : local_constant_declarators COMMA . local_constant_declarator (754) + + IDENTIFIER shift 498 + . error + + local_constant_declarator goto 842 + + +state 690 + default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS . (566) + + . reduce 566 + + +state 691 + arglist_modifier : ARGLIST . (217) + + . reduce 217 + + +state 692 + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER (199) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type error (201) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression (203) + parameter_array : opt_attributes . params_modifier type IDENTIFIER (211) + parameter_array : opt_attributes . params_modifier type IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes . params_modifier type error (213) + opt_parameter_modifier : . (204) + + OUT shift 574 + PARAMS shift 843 + REF shift 575 + THIS shift 576 + BOOL reduce 204 + BYTE reduce 204 + CHAR reduce 204 + DECIMAL reduce 204 + DOUBLE reduce 204 + FLOAT reduce 204 + INT reduce 204 + LONG reduce 204 + OBJECT reduce 204 + SBYTE reduce 204 + SHORT reduce 204 + STRING reduce 204 + UINT reduce 204 + ULONG reduce 204 + USHORT reduce 204 + VOID reduce 204 + IDENTIFIER reduce 204 + + opt_parameter_modifier goto 844 + parameter_modifiers goto 845 + parameter_modifier goto 846 + params_modifier goto 847 + + +state 693 + opt_attributes : attribute_sections . (60) + attribute_sections : attribute_sections . attribute_section (62) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 60 + ADD reduce 60 + BOOL reduce 60 + BYTE reduce 60 + CHAR reduce 60 + CLASS reduce 60 + CONST reduce 60 + DECIMAL reduce 60 + DELEGATE reduce 60 + DOUBLE reduce 60 + ENUM reduce 60 + EVENT reduce 60 + EXPLICIT reduce 60 + EXTERN reduce 60 + FIXED reduce 60 + FLOAT reduce 60 + IMPLICIT reduce 60 + IN reduce 60 + INT reduce 60 + INTERFACE reduce 60 + INTERNAL reduce 60 + LONG reduce 60 + NAMESPACE reduce 60 + NEW reduce 60 + OBJECT reduce 60 + OUT reduce 60 + OVERRIDE reduce 60 + PARAMS reduce 60 + PRIVATE reduce 60 + PROTECTED reduce 60 + PUBLIC reduce 60 + READONLY reduce 60 + REF reduce 60 + REMOVE reduce 60 + SBYTE reduce 60 + SEALED reduce 60 + SHORT reduce 60 + STATIC reduce 60 + STRING reduce 60 + STRUCT reduce 60 + THIS reduce 60 + UINT reduce 60 + ULONG reduce 60 + UNSAFE reduce 60 + USHORT reduce 60 + VIRTUAL reduce 60 + VOID reduce 60 + VOLATILE reduce 60 + PARTIAL reduce 60 + GET reduce 60 + SET reduce 60 + TILDE reduce 60 + IDENTIFIER reduce 60 + + attribute_section goto 79 + + +state 694 + anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list . CLOSE_PARENS (565) + + CLOSE_PARENS shift 848 + . error + + +state 695 + opt_formal_parameter_list : formal_parameter_list . (187) + + . reduce 187 + + +state 696 + formal_parameter_list : fixed_parameters . (188) + formal_parameter_list : fixed_parameters . COMMA parameter_array (189) + formal_parameter_list : fixed_parameters . COMMA arglist_modifier (190) + formal_parameter_list : fixed_parameters . COMMA parameter_array COMMA error (192) + formal_parameter_list : fixed_parameters . COMMA ARGLIST COMMA error (194) + fixed_parameters : fixed_parameters . COMMA fixed_parameter (198) + + COMMA shift 849 + CLOSE_BRACKET reduce 188 + CLOSE_PARENS reduce 188 + + +state 697 + formal_parameter_list : parameter_array . COMMA error (191) + formal_parameter_list : parameter_array . (195) + + COMMA shift 850 + CLOSE_BRACKET reduce 195 + CLOSE_PARENS reduce 195 + + +state 698 + formal_parameter_list : arglist_modifier . COMMA error (193) + formal_parameter_list : arglist_modifier . (196) + + COMMA shift 851 + CLOSE_BRACKET reduce 196 + CLOSE_PARENS reduce 196 + + +state 699 + fixed_parameters : fixed_parameter . (197) + + . reduce 197 + + +state 700 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 block . (561) + + . reduce 561 + + +state 701 + do_statement : DO embedded_statement WHILE open_parens_any . boolean_expression CLOSE_PARENS SEMICOLON (786) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 852 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 702 + fixed_pointer_declarator : IDENTIFIER . ASSIGN expression (842) + fixed_pointer_declarator : IDENTIFIER . (843) + + ASSIGN shift 853 + CLOSE_PARENS reduce 843 + COMMA reduce 843 + + +state 703 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators . CLOSE_PARENS $$83 embedded_statement (839) + fixed_pointer_declarators : fixed_pointer_declarators . COMMA fixed_pointer_declarator (841) + + CLOSE_PARENS shift 854 + COMMA shift 855 + . error + + +state 704 + fixed_pointer_declarators : fixed_pointer_declarator . (840) + + . reduce 840 + + +state 705 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON . $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + $$79 : . (787) + + . reduce 787 + + $$79 goto 856 + + +state 706 + statement_expression_list : statement_expression_list COMMA . statement_expression (799) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_expression goto 857 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 707 + foreach_statement : FOREACH open_parens_any type IN . expression CLOSE_PARENS (800) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 858 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 708 + foreach_statement : FOREACH open_parens_any type IDENTIFIER . IN expression CLOSE_PARENS $$80 embedded_statement (802) + + IN shift 859 + . error + + +state 709 + goto_statement : GOTO CASE constant_expression SEMICOLON . (812) + + . reduce 812 + + +state 710 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS . embedded_statement (767) + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS . embedded_statement ELSE embedded_statement (768) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 860 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 711 + lock_statement : LOCK open_parens_any expression CLOSE_PARENS . embedded_statement (844) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 861 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 712 + anonymous_type_parameter : IDENTIFIER ASSIGN . variable_initializer (523) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 862 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 713 + anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE . (516) + + . reduce 516 + + +state 714 + anonymous_type_parameters_opt_comma : anonymous_type_parameters COMMA . (518) + anonymous_type_parameters : anonymous_type_parameters COMMA . anonymous_type_parameter (522) + + error shift 521 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 522 + CLOSE_BRACE reduce 518 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 523 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + anonymous_type_parameter goto 863 + + +state 715 + rank_specifier : OPEN_BRACKET dim_separators CLOSE_BRACKET . (534) + + . reduce 534 + + +state 716 + dim_separators : dim_separators COMMA . (536) + + . reduce 536 + + +state 717 + variable_initializer_list : error . (543) + + . reduce 543 + + +state 718 + array_initializer : OPEN_BRACE CLOSE_BRACE . (539) + + . reduce 539 + + +state 719 + variable_initializer : expression . (173) + + . reduce 173 + + +state 720 + variable_initializer : array_initializer . (174) + + . reduce 174 + + +state 721 + variable_initializer_list : variable_initializer . (541) + + . reduce 541 + + +state 722 + array_initializer : OPEN_BRACE variable_initializer_list . opt_comma CLOSE_BRACE (540) + variable_initializer_list : variable_initializer_list . COMMA variable_initializer (542) + opt_comma : . (32) + + COMMA shift 864 + CLOSE_BRACE reduce 32 + + opt_comma goto 865 + + +state 723 + member_initializer : OPEN_BRACE . expression_list CLOSE_BRACE (473) + member_initializer : OPEN_BRACE . CLOSE_BRACE (474) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + CLOSE_BRACE shift 866 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 731 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list goto 867 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 724 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + member_initializer : IDENTIFIER . ASSIGN initializer_value (470) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + ASSIGN shift 868 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + CLOSE_BRACE reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 725 + member_initializer : GENERATE_COMPLETION . (471) + + . reduce 471 + + +state 726 + object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list . close_brace_or_complete_completion (463) + + CLOSE_BRACE shift 869 + COMPLETE_COMPLETION shift 870 + . error + + close_brace_or_complete_completion goto 871 + + +state 727 + object_or_collection_initializer : OPEN_BRACE member_initializer_list . COMMA CLOSE_BRACE (464) + opt_member_initializer_list : member_initializer_list . (466) + member_initializer_list : member_initializer_list . COMMA member_initializer (468) + member_initializer_list : member_initializer_list . error (469) + + error shift 872 + COMMA shift 873 + CLOSE_BRACE reduce 466 + COMPLETE_COMPLETION reduce 466 + + +state 728 + member_initializer_list : member_initializer . (467) + + . reduce 467 + + +729: shift/reduce conflict (shift 426, reduce 918) on COMPLETE_COMPLETION +state 729 + member_initializer : non_assignment_expression . opt_COMPLETE_COMPLETION (472) + opt_COMPLETE_COMPLETION : . (918) + + COMPLETE_COMPLETION shift 426 + error reduce 918 + CLOSE_BRACE reduce 918 + COMMA reduce 918 + + opt_COMPLETE_COMPLETION goto 874 + + +730: shift/reduce conflict (shift 875, reduce 533) on OPEN_BRACKET_EXPR +state 730 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET . OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + rank_specifier : OPEN_BRACKET CLOSE_BRACKET . (533) + + OPEN_BRACKET_EXPR shift 875 + error reduce 533 + AS reduce 533 + IS reduce 533 + WHERE reduce 533 + FROM reduce 533 + JOIN reduce 533 + ON reduce 533 + EQUALS reduce 533 + SELECT reduce 533 + GROUP reduce 533 + BY reduce 533 + LET reduce 533 + ORDERBY reduce 533 + ASCENDING reduce 533 + DESCENDING reduce 533 + INTO reduce 533 + OPEN_BRACE reduce 533 + CLOSE_BRACE reduce 533 + OPEN_BRACKET reduce 533 + CLOSE_BRACKET reduce 533 + OPEN_PARENS reduce 533 + CLOSE_PARENS reduce 533 + DOT reduce 533 + COMMA reduce 533 + COLON reduce 533 + SEMICOLON reduce 533 + PLUS reduce 533 + MINUS reduce 533 + ASSIGN reduce 533 + OP_LT reduce 533 + OP_GT reduce 533 + BITWISE_AND reduce 533 + BITWISE_OR reduce 533 + STAR reduce 533 + PERCENT reduce 533 + DIV reduce 533 + CARRET reduce 533 + INTERR reduce 533 + OP_INC reduce 533 + OP_DEC reduce 533 + OP_SHIFT_LEFT reduce 533 + OP_SHIFT_RIGHT reduce 533 + OP_LE reduce 533 + OP_GE reduce 533 + OP_EQ reduce 533 + OP_NE reduce 533 + OP_AND reduce 533 + OP_OR reduce 533 + OP_MULT_ASSIGN reduce 533 + OP_DIV_ASSIGN reduce 533 + OP_MOD_ASSIGN reduce 533 + OP_ADD_ASSIGN reduce 533 + OP_SUB_ASSIGN reduce 533 + OP_SHIFT_LEFT_ASSIGN reduce 533 + OP_SHIFT_RIGHT_ASSIGN reduce 533 + OP_AND_ASSIGN reduce 533 + OP_XOR_ASSIGN reduce 533 + OP_OR_ASSIGN reduce 533 + OP_PTR reduce 533 + OP_COALESCING reduce 533 + OPEN_PARENS_CAST reduce 533 + COMPLETE_COMPLETION reduce 533 + + +state 731 + expression_list : expression . (495) + + . reduce 495 + + +state 732 + expression_list : expression_list . COMMA expression (496) + expression_list : expression_list . error (497) + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list . CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + + error shift 876 + CLOSE_BRACKET shift 877 + COMMA shift 878 + . error + + +state 733 + opt_array_initializer : array_initializer . (538) + + . reduce 538 + + +state 734 + array_creation_expression : NEW new_expr_type rank_specifiers opt_array_initializer . (510) + + . reduce 510 + + +state 735 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list . CLOSE_PARENS opt_object_or_collection_initializer (507) + + CLOSE_PARENS shift 879 + . error + + +state 736 + sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS . (556) + + . reduce 556 + + +state 737 + switch_statement : SWITCH open_parens_any $$77 expression . CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + CLOSE_PARENS shift 880 + . error + + +state 738 + catch_args : open_parens_any . type opt_identifier CLOSE_PARENS (832) + catch_args : open_parens_any . CLOSE_PARENS (833) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + CLOSE_PARENS shift 881 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 882 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 739 + catch_clause : CATCH opt_catch_args . $$81 block (829) + $$81 : . (828) + + . reduce 828 + + $$81 goto 883 + + +state 740 + opt_catch_args : catch_args . (831) + + . reduce 831 + + +state 741 + try_statement : TRY block FINALLY block . (821) + + . reduce 821 + + +state 742 + try_statement : TRY block catch_clauses FINALLY . block (822) + + OPEN_BRACE shift 143 + . error + + block goto 884 + + +state 743 + catch_clauses : catch_clauses catch_clause . (825) + + . reduce 825 + + +state 744 + typeof_type_expression : error . (548) + + . reduce 548 + + +state 745 + type_name : IDENTIFIER . opt_type_argument_list (362) + unbound_type_name : IDENTIFIER . generic_dimension (549) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 84 + generic_dimension goto 886 + + +state 746 + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + type_expression : namespace_or_type_name . opt_nullable (395) + unbound_type_name : namespace_or_type_name . DOT IDENTIFIER generic_dimension (553) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 887 + OPEN_BRACKET reduce 356 + CLOSE_PARENS reduce 356 + STAR reduce 356 + + opt_nullable goto 466 + + +state 747 + namespace_or_type_name : qualified_alias_member . IDENTIFIER opt_type_argument_list (359) + unbound_type_name : qualified_alias_member . IDENTIFIER generic_dimension (550) + + IDENTIFIER shift 888 + . error + + +state 748 + typeof_type_expression : type_and_void . (546) + + . reduce 546 + + +state 749 + typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression . CLOSE_PARENS (545) + + CLOSE_PARENS shift 889 + . error + + +state 750 + typeof_type_expression : unbound_type_name . (547) + unbound_type_name : unbound_type_name . DOT IDENTIFIER (551) + unbound_type_name : unbound_type_name . DOT IDENTIFIER generic_dimension (552) + + DOT shift 890 + CLOSE_PARENS reduce 547 + + +state 751 + unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS . (558) + + . reduce 558 + + +state 752 + using_statement : USING open_parens_any expression CLOSE_PARENS . $$85 embedded_statement (848) + $$85 : . (847) + + . reduce 847 + + $$85 goto 891 + + +state 753 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS . $$84 embedded_statement (846) + $$84 : . (845) + + . reduce 845 + + $$84 goto 892 + + +state 754 + while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS . embedded_statement (785) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 893 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 755 + nested_from_clause : FROM IDENTIFIER IN expression . (855) + + . reduce 855 + + +state 756 + nested_from_clause : FROM type IDENTIFIER IN . expression (856) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 894 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 757 + first_from_clause : FROM_FIRST IDENTIFIER IN expression . (853) + + . reduce 853 + + +state 758 + first_from_clause : FROM_FIRST type IDENTIFIER IN . expression (854) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 895 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 759 + block_end : CLOSE_BRACE . (692) + + . reduce 692 + + +state 760 + block_end : COMPLETE_COMPLETION . (693) + + . reduce 693 + + +state 761 + block : OPEN_BRACE $$74 opt_statement_list block_end . (691) + + . reduce 691 + + +state 762 + statement_list : statement_list statement . (699) + + . reduce 699 + + +state 763 + cast_expression : OPEN_PARENS builtin_types CLOSE_PARENS prefixed_unary_expression . (572) + + . reduce 572 + + +state 764 + yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON . (816) + + . reduce 816 + + +state 765 + lambda_expression_body : block . (635) + + . reduce 635 + + +state 766 + lambda_expression : IDENTIFIER ARROW $$67 lambda_expression_body . (637) + + . reduce 637 + + +state 767 + lambda_expression_body : $$66 . expression (634) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 896 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 768 + labeled_statement : IDENTIFIER COLON $$76 statement . (739) + + . reduce 739 + + +state 769 + lambda_parameter : parameter_type IDENTIFIER . (629) + + . reduce 629 + + +state 770 + lambda_parameter : parameter_modifier parameter_type . IDENTIFIER (628) + + IDENTIFIER shift 897 + . error + + +state 771 + lambda_parameter_list : lambda_parameter_list COMMA . lambda_parameter (627) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + OUT shift 574 + REF shift 575 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + THIS shift 576 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 578 + . error + + namespace_or_type_name goto 255 + parameter_type goto 579 + parameter_modifier goto 580 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + lambda_parameter goto 898 + + +state 772 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS . ARROW $$69 lambda_expression_body (640) + + ARROW shift 899 + . error + + +state 773 + cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression . (571) + + . reduce 571 + + +state 774 + member_access : builtin_types DOT IDENTIFIER GENERATE_COMPLETION . (459) + + . reduce 459 + + +state 775 + member_access : builtin_types DOT IDENTIFIER opt_type_argument_list . (453) + + . reduce 453 + + +state 776 + member_access : primary_expression DOT IDENTIFIER GENERATE_COMPLETION . (457) + + . reduce 457 + + +state 777 + member_access : primary_expression DOT IDENTIFIER opt_type_argument_list . (452) + + . reduce 452 + + +state 778 + element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET . (494) + + . reduce 494 + + +state 779 + variable_reference : expression . (493) + + . reduce 493 + + +state 780 + non_simple_argument : OUT variable_reference . (489) + + . reduce 489 + + +state 781 + non_simple_argument : REF variable_reference . (488) + + . reduce 488 + + +state 782 + non_simple_argument : ARGLIST OPEN_PARENS . argument_list CLOSE_PARENS (490) + non_simple_argument : ARGLIST OPEN_PARENS . CLOSE_PARENS (491) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + CLOSE_PARENS shift 900 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 598 + named_argument goto 599 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 901 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 783 + argument_list : COMMA error . (483) + + . reduce 483 + + +state 784 + close_parens : CLOSE_PARENS . (448) + + . reduce 448 + + +state 785 + close_parens : COMPLETE_COMPLETION . (449) + + . reduce 449 + + +state 786 + invocation_expression : primary_expression open_parens_any opt_argument_list close_parens . (460) + + . reduce 460 + + +state 787 + argument_list : argument_list COMMA . argument (480) + argument_list : argument_list COMMA . named_argument (481) + argument_list : argument_list COMMA . (482) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 482 + COMMA reduce 482 + COMPLETE_COMPLETION reduce 482 + + expression goto 598 + named_argument goto 902 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument goto 903 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 788 + conditional_expression : null_coalescing_expression INTERR expression COLON . expression (614) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 904 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 789 + local_variable_initializer : STACKALLOC . simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET (169) + local_variable_initializer : STACKALLOC . simple_type (171) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 905 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 790 + local_variable_initializer : ARGLIST . (170) + + . reduce 170 + + +state 791 + local_variable_initializer : expression . (167) + + . reduce 167 + + +state 792 + local_variable_initializer : array_initializer . (168) + + . reduce 168 + + +state 793 + local_variable_declarator : IDENTIFIER ASSIGN local_variable_initializer . (164) + + . reduce 164 + + +state 794 + variable_bad_array : OPEN_BRACKET_EXPR opt_expression . CLOSE_BRACKET (172) + + CLOSE_BRACKET shift 906 + . error + + +state 795 + local_variable_declarators : local_variable_declarators COMMA local_variable_declarator . (163) + + . reduce 163 + + +state 796 + where_clause : WHERE $$92 boolean_expression . (880) + + . reduce 880 + + +state 797 + from_clause : FROM IDENTIFIER IN . $$86 expression (858) + $$86 : . (857) + + . reduce 857 + + $$86 goto 907 + + +state 798 + from_clause : FROM type IDENTIFIER . IN $$87 expression (860) + + IN shift 908 + . error + + +state 799 + join_clause : JOIN IDENTIFIER IN . $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + $$93 : . (881) + + . reduce 881 + + $$93 goto 909 + + +state 800 + join_clause : JOIN type IDENTIFIER . IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + IN shift 910 + . error + + +state 801 + let_clause : LET IDENTIFIER ASSIGN . $$91 expression (878) + $$91 : . (877) + + . reduce 877 + + $$91 goto 911 + + +state 802 + order_by : expression . (899) + order_by : expression . ASCENDING (900) + order_by : expression . DESCENDING (901) + + ASCENDING shift 912 + DESCENDING shift 913 + WHERE reduce 899 + FROM reduce 899 + JOIN reduce 899 + SELECT reduce 899 + GROUP reduce 899 + LET reduce 899 + ORDERBY reduce 899 + COMMA reduce 899 + COMPLETE_COMPLETION reduce 899 + + +state 803 + orderby_clause : ORDERBY $$99 orderings . (892) + + . reduce 892 + + +state 804 + orderings : order_by . (893) + orderings : order_by . COMMA $$100 orderings_then_by (895) + + COMMA shift 914 + WHERE reduce 893 + FROM reduce 893 + JOIN reduce 893 + SELECT reduce 893 + GROUP reduce 893 + LET reduce 893 + ORDERBY reduce 893 + COMPLETE_COMPLETION reduce 893 + + +state 805 + select_or_group_clause : SELECT $$88 . expression (864) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 915 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 806 + select_or_group_clause : GROUP $$89 . expression $$90 BY expression (867) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 916 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 807 + opt_query_continuation : INTO . IDENTIFIER $$102 query_body (907) + + IDENTIFIER shift 917 + . error + + +state 808 + query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation . (861) + + . reduce 861 + + +state 809 + namespace_body : OPEN_BRACE $$3 . namespace_body_body (36) + opt_extern_alias_directives : . (43) + + error shift 918 + EXTERN_ALIAS shift 3 + EOF reduce 43 + ABSTRACT reduce 43 + BOOL reduce 43 + BYTE reduce 43 + CHAR reduce 43 + CLASS reduce 43 + DECIMAL reduce 43 + DELEGATE reduce 43 + DOUBLE reduce 43 + ENUM reduce 43 + EXTERN reduce 43 + FIXED reduce 43 + FLOAT reduce 43 + INT reduce 43 + INTERFACE reduce 43 + INTERNAL reduce 43 + LONG reduce 43 + NAMESPACE reduce 43 + NEW reduce 43 + OBJECT reduce 43 + OVERRIDE reduce 43 + PRIVATE reduce 43 + PROTECTED reduce 43 + PUBLIC reduce 43 + READONLY reduce 43 + SBYTE reduce 43 + SEALED reduce 43 + SHORT reduce 43 + STATIC reduce 43 + STRING reduce 43 + STRUCT reduce 43 + UINT reduce 43 + ULONG reduce 43 + UNSAFE reduce 43 + USHORT reduce 43 + USING reduce 43 + VIRTUAL reduce 43 + VOID reduce 43 + VOLATILE reduce 43 + PARTIAL reduce 43 + CLOSE_BRACE reduce 43 + OPEN_BRACKET reduce 43 + IDENTIFIER reduce 43 + + extern_alias_directive goto 919 + extern_alias_directives goto 920 + namespace_body_body goto 921 + opt_extern_alias_directives goto 922 + + +state 810 + opt_semicolon : SEMICOLON . (31) + + . reduce 31 + + +state 811 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon . (26) + + . reduce 26 + + +state 812 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS . $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + $$58 : . (352) + + . reduce 352 + + $$58 goto 923 + + +state 813 + opt_type_parameter_list : OP_GENERICS_LT_DECL . type_parameters OP_GENERICS_GT (379) + opt_attributes : . (59) + + error shift 924 + OPEN_BRACKET shift 4 + IN reduce 59 + OUT reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 925 + attribute_sections goto 693 + attribute_section goto 30 + type_parameters goto 926 + type_parameter goto 927 + + +state 814 + type_declaration_name : IDENTIFIER $$61 opt_type_parameter_list . (369) + + . reduce 369 + + +state 815 + opt_enum_base : COLON error . (343) + + . reduce 343 + + +state 816 + opt_enum_base : COLON type . (342) + + . reduce 342 + + +state 817 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 . OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + + OPEN_BRACE shift 928 + . error + + +state 818 + field_declaration : opt_attributes opt_modifiers FIXED simple_type error SEMICOLON . (143) + + . reduce 143 + + +state 819 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 . fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + + OPEN_BRACKET shift 929 + . error + + fixed_field_size goto 930 + + +state 820 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS . $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + $$22 : . (180) + + . reduce 180 + + $$22 goto 931 + + +state 821 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name . $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$71 : . (649) + + . reduce 649 + + $$71 goto 932 + + +state 822 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name . $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + $$34 : . (239) + + . reduce 239 + + $$34 goto 933 + + +state 823 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name . $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + $$8 : . (106) + + . reduce 106 + + $$8 goto 934 + + +state 824 + opt_field_initializer : ASSIGN . $$16 variable_initializer (146) + $$16 : . (145) + + . reduce 145 + + $$16 goto 935 + + +state 825 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer . opt_field_declarators SEMICOLON (140) + opt_field_declarators : . (147) + + COMMA shift 936 + SEMICOLON reduce 147 + + opt_field_declarators goto 937 + field_declarators goto 938 + field_declarator goto 939 + + +state 826 + explicit_interface : IDENTIFIER opt_type_argument_list DOT . (375) + + . reduce 375 + + +state 827 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 . opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 940 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 828 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS . opt_formal_parameter_list CLOSE_PARENS (183) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 941 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 829 + explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list . DOT (376) + + DOT shift 942 + . error + + +state 830 + explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list . DOT (377) + + DOT shift 943 + . error + + +state 831 + method_declaration_name : explicit_interface IDENTIFIER opt_type_parameter_list . (372) + + . reduce 372 + + +state 832 + opt_named_modifier : OUT . (89) + + . reduce 89 + + +state 833 + opt_named_modifier : REF . (88) + + . reduce 88 + + +state 834 + named_argument : IDENTIFIER COLON opt_named_modifier . expression (86) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 944 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 835 + named_attribute_argument : IDENTIFIER ASSIGN $$6 . expression (85) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 945 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 836 + attribute_arguments : attribute_arguments COMMA positional_or_named_argument . (80) + + . reduce 80 + + +state 837 + attribute_arguments : attribute_arguments COMMA named_attribute_argument . (81) + + . reduce 81 + + +state 838 + expression_list_arguments : expression_list_arguments COMMA expression_list_argument . (499) + + . reduce 499 + + +state 839 + local_constant_declarator : IDENTIFIER ASSIGN constant_initializer_expr . (755) + + . reduce 755 + + +state 840 + constant_initializer_expr : constant_expression . (137) + + . reduce 137 + + +state 841 + constant_initializer_expr : array_initializer . (138) + + . reduce 138 + + +state 842 + local_constant_declarators : local_constant_declarators COMMA local_constant_declarator . (754) + + . reduce 754 + + +state 843 + params_modifier : PARAMS . (214) + params_modifier : PARAMS . parameter_modifier (215) + params_modifier : PARAMS . params_modifier (216) + + OUT shift 574 + PARAMS shift 843 + REF shift 575 + THIS shift 576 + BOOL reduce 214 + BYTE reduce 214 + CHAR reduce 214 + DECIMAL reduce 214 + DOUBLE reduce 214 + FLOAT reduce 214 + INT reduce 214 + LONG reduce 214 + OBJECT reduce 214 + SBYTE reduce 214 + SHORT reduce 214 + STRING reduce 214 + UINT reduce 214 + ULONG reduce 214 + USHORT reduce 214 + VOID reduce 214 + IDENTIFIER reduce 214 + + parameter_modifier goto 946 + params_modifier goto 947 + + +state 844 + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER (199) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type error (201) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER ASSIGN $$24 constant_expression (203) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + parameter_type goto 948 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 845 + opt_parameter_modifier : parameter_modifiers . (205) + parameter_modifiers : parameter_modifiers . parameter_modifier (207) + + OUT shift 574 + REF shift 575 + THIS shift 576 + BOOL reduce 205 + BYTE reduce 205 + CHAR reduce 205 + DECIMAL reduce 205 + DOUBLE reduce 205 + FLOAT reduce 205 + INT reduce 205 + LONG reduce 205 + OBJECT reduce 205 + SBYTE reduce 205 + SHORT reduce 205 + STRING reduce 205 + UINT reduce 205 + ULONG reduce 205 + USHORT reduce 205 + VOID reduce 205 + IDENTIFIER reduce 205 + + parameter_modifier goto 949 + + +state 846 + parameter_modifiers : parameter_modifier . (206) + + . reduce 206 + + +state 847 + parameter_array : opt_attributes params_modifier . type IDENTIFIER (211) + parameter_array : opt_attributes params_modifier . type IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes params_modifier . type error (213) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 950 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 848 + anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list CLOSE_PARENS . (565) + + . reduce 565 + + +state 849 + formal_parameter_list : fixed_parameters COMMA . parameter_array (189) + formal_parameter_list : fixed_parameters COMMA . arglist_modifier (190) + formal_parameter_list : fixed_parameters COMMA . parameter_array COMMA error (192) + formal_parameter_list : fixed_parameters COMMA . ARGLIST COMMA error (194) + fixed_parameters : fixed_parameters COMMA . fixed_parameter (198) + opt_attributes : . (59) + + ARGLIST shift 951 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + parameter_array goto 952 + arglist_modifier goto 953 + fixed_parameter goto 954 + + +state 850 + formal_parameter_list : parameter_array COMMA . error (191) + + error shift 955 + . error + + +state 851 + formal_parameter_list : arglist_modifier COMMA . error (193) + + error shift 956 + . error + + +state 852 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression . CLOSE_PARENS SEMICOLON (786) + + CLOSE_PARENS shift 957 + . error + + +state 853 + fixed_pointer_declarator : IDENTIFIER ASSIGN . expression (842) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 958 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 854 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS . $$83 embedded_statement (839) + $$83 : . (838) + + . reduce 838 + + $$83 goto 959 + + +state 855 + fixed_pointer_declarators : fixed_pointer_declarators COMMA . fixed_pointer_declarator (841) + + IDENTIFIER shift 702 + . error + + fixed_pointer_declarator goto 960 + + +state 856 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 . opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_condition : . (793) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 793 + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 961 + opt_for_condition goto 962 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 857 + statement_expression_list : statement_expression_list COMMA statement_expression . (799) + + . reduce 799 + + +state 858 + foreach_statement : FOREACH open_parens_any type IN expression . CLOSE_PARENS (800) + + CLOSE_PARENS shift 963 + . error + + +state 859 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN . expression CLOSE_PARENS $$80 embedded_statement (802) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 964 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +860: shift/reduce conflict (shift 965, reduce 767) on ELSE +state 860 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement . (767) + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement . ELSE embedded_statement (768) + + ELSE shift 965 + $end reduce 767 + error reduce 767 + EOF reduce 767 + BASE reduce 767 + BOOL reduce 767 + BREAK reduce 767 + BYTE reduce 767 + CASE reduce 767 + CHAR reduce 767 + CHECKED reduce 767 + CONST reduce 767 + CONTINUE reduce 767 + DECIMAL reduce 767 + DEFAULT reduce 767 + DELEGATE reduce 767 + DO reduce 767 + DOUBLE reduce 767 + FALSE reduce 767 + FIXED reduce 767 + FLOAT reduce 767 + FOR reduce 767 + FOREACH reduce 767 + GOTO reduce 767 + IF reduce 767 + INT reduce 767 + LOCK reduce 767 + LONG reduce 767 + NEW reduce 767 + NULL reduce 767 + OBJECT reduce 767 + RETURN reduce 767 + SBYTE reduce 767 + SHORT reduce 767 + SIZEOF reduce 767 + STRING reduce 767 + SWITCH reduce 767 + THIS reduce 767 + THROW reduce 767 + TRUE reduce 767 + TRY reduce 767 + TYPEOF reduce 767 + UINT reduce 767 + ULONG reduce 767 + UNCHECKED reduce 767 + UNSAFE reduce 767 + USHORT reduce 767 + USING reduce 767 + VOID reduce 767 + WHILE reduce 767 + FROM reduce 767 + FROM_FIRST reduce 767 + OPEN_BRACE reduce 767 + CLOSE_BRACE reduce 767 + OPEN_PARENS reduce 767 + SEMICOLON reduce 767 + TILDE reduce 767 + PLUS reduce 767 + MINUS reduce 767 + BANG reduce 767 + BITWISE_AND reduce 767 + STAR reduce 767 + OP_INC reduce 767 + OP_DEC reduce 767 + LITERAL reduce 767 + IDENTIFIER reduce 767 + OPEN_PARENS_LAMBDA reduce 767 + OPEN_PARENS_CAST reduce 767 + DEFAULT_COLON reduce 767 + COMPLETE_COMPLETION reduce 767 + + +state 861 + lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement . (844) + + . reduce 844 + + +state 862 + anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer . (523) + + . reduce 523 + + +state 863 + anonymous_type_parameters : anonymous_type_parameters COMMA anonymous_type_parameter . (522) + + . reduce 522 + + +state 864 + opt_comma : COMMA . (33) + variable_initializer_list : variable_initializer_list COMMA . variable_initializer (542) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 33 + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 966 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 865 + array_initializer : OPEN_BRACE variable_initializer_list opt_comma . CLOSE_BRACE (540) + + CLOSE_BRACE shift 967 + . error + + +state 866 + member_initializer : OPEN_BRACE CLOSE_BRACE . (474) + + . reduce 474 + + +state 867 + member_initializer : OPEN_BRACE expression_list . CLOSE_BRACE (473) + expression_list : expression_list . COMMA expression (496) + expression_list : expression_list . error (497) + + error shift 876 + CLOSE_BRACE shift 968 + COMMA shift 878 + . error + + +state 868 + member_initializer : IDENTIFIER ASSIGN . initializer_value (470) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 534 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 969 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + object_or_collection_initializer goto 970 + initializer_value goto 971 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 869 + close_brace_or_complete_completion : CLOSE_BRACE . (920) + + . reduce 920 + + +state 870 + close_brace_or_complete_completion : COMPLETE_COMPLETION . (921) + + . reduce 921 + + +state 871 + object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion . (463) + + . reduce 463 + + +state 872 + member_initializer_list : member_initializer_list error . (469) + + . reduce 469 + + +state 873 + object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA . CLOSE_BRACE (464) + member_initializer_list : member_initializer_list COMMA . member_initializer (468) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 723 + CLOSE_BRACE shift 972 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 724 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + GENERATE_COMPLETION shift 725 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + member_initializer goto 973 + non_assignment_expression goto 729 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 874 + member_initializer : non_assignment_expression opt_COMPLETE_COMPLETION . (472) + + . reduce 472 + + +state 875 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR . error CLOSE_BRACKET (512) + + error shift 974 + . error + + +state 876 + expression_list : expression_list error . (497) + + . reduce 497 + + +state 877 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET . opt_rank_specifier opt_array_initializer (509) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + error reduce 527 + AS reduce 527 + IS reduce 527 + WHERE reduce 527 + FROM reduce 527 + JOIN reduce 527 + ON reduce 527 + EQUALS reduce 527 + SELECT reduce 527 + GROUP reduce 527 + BY reduce 527 + LET reduce 527 + ORDERBY reduce 527 + ASCENDING reduce 527 + DESCENDING reduce 527 + INTO reduce 527 + OPEN_BRACE reduce 527 + CLOSE_BRACE reduce 527 + CLOSE_BRACKET reduce 527 + OPEN_PARENS reduce 527 + CLOSE_PARENS reduce 527 + DOT reduce 527 + COMMA reduce 527 + COLON reduce 527 + SEMICOLON reduce 527 + PLUS reduce 527 + MINUS reduce 527 + ASSIGN reduce 527 + OP_LT reduce 527 + OP_GT reduce 527 + BITWISE_AND reduce 527 + BITWISE_OR reduce 527 + STAR reduce 527 + PERCENT reduce 527 + DIV reduce 527 + CARRET reduce 527 + INTERR reduce 527 + OP_INC reduce 527 + OP_DEC reduce 527 + OP_SHIFT_LEFT reduce 527 + OP_SHIFT_RIGHT reduce 527 + OP_LE reduce 527 + OP_GE reduce 527 + OP_EQ reduce 527 + OP_NE reduce 527 + OP_AND reduce 527 + OP_OR reduce 527 + OP_MULT_ASSIGN reduce 527 + OP_DIV_ASSIGN reduce 527 + OP_MOD_ASSIGN reduce 527 + OP_ADD_ASSIGN reduce 527 + OP_SUB_ASSIGN reduce 527 + OP_SHIFT_LEFT_ASSIGN reduce 527 + OP_SHIFT_RIGHT_ASSIGN reduce 527 + OP_AND_ASSIGN reduce 527 + OP_XOR_ASSIGN reduce 527 + OP_OR_ASSIGN reduce 527 + OP_PTR reduce 527 + OP_COALESCING reduce 527 + OPEN_PARENS_CAST reduce 527 + OPEN_BRACKET_EXPR reduce 527 + COMPLETE_COMPLETION reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 975 + rank_specifier goto 336 + + +state 878 + expression_list : expression_list COMMA . expression (496) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 976 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 879 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS . opt_object_or_collection_initializer (507) + opt_object_or_collection_initializer : . (461) + + OPEN_BRACE shift 534 + error reduce 461 + AS reduce 461 + IS reduce 461 + WHERE reduce 461 + FROM reduce 461 + JOIN reduce 461 + ON reduce 461 + EQUALS reduce 461 + SELECT reduce 461 + GROUP reduce 461 + BY reduce 461 + LET reduce 461 + ORDERBY reduce 461 + ASCENDING reduce 461 + DESCENDING reduce 461 + INTO reduce 461 + INTERR_NULLABLE reduce 461 + CLOSE_BRACE reduce 461 + OPEN_BRACKET reduce 461 + CLOSE_BRACKET reduce 461 + OPEN_PARENS reduce 461 + CLOSE_PARENS reduce 461 + DOT reduce 461 + COMMA reduce 461 + COLON reduce 461 + SEMICOLON reduce 461 + PLUS reduce 461 + MINUS reduce 461 + ASSIGN reduce 461 + OP_LT reduce 461 + OP_GT reduce 461 + BITWISE_AND reduce 461 + BITWISE_OR reduce 461 + STAR reduce 461 + PERCENT reduce 461 + DIV reduce 461 + CARRET reduce 461 + INTERR reduce 461 + OP_INC reduce 461 + OP_DEC reduce 461 + OP_SHIFT_LEFT reduce 461 + OP_SHIFT_RIGHT reduce 461 + OP_LE reduce 461 + OP_GE reduce 461 + OP_EQ reduce 461 + OP_NE reduce 461 + OP_AND reduce 461 + OP_OR reduce 461 + OP_MULT_ASSIGN reduce 461 + OP_DIV_ASSIGN reduce 461 + OP_MOD_ASSIGN reduce 461 + OP_ADD_ASSIGN reduce 461 + OP_SUB_ASSIGN reduce 461 + OP_SHIFT_LEFT_ASSIGN reduce 461 + OP_SHIFT_RIGHT_ASSIGN reduce 461 + OP_AND_ASSIGN reduce 461 + OP_XOR_ASSIGN reduce 461 + OP_OR_ASSIGN reduce 461 + OP_PTR reduce 461 + OP_COALESCING reduce 461 + IDENTIFIER reduce 461 + OPEN_PARENS_CAST reduce 461 + OPEN_BRACKET_EXPR reduce 461 + COMPLETE_COMPLETION reduce 461 + + opt_object_or_collection_initializer goto 977 + object_or_collection_initializer goto 978 + + +state 880 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS . OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + OPEN_BRACE shift 979 + . error + + +state 881 + catch_args : open_parens_any CLOSE_PARENS . (833) + + . reduce 833 + + +state 882 + catch_args : open_parens_any type . opt_identifier CLOSE_PARENS (832) + opt_identifier : . (826) + + IDENTIFIER shift 980 + CLOSE_PARENS reduce 826 + + opt_identifier goto 981 + + +state 883 + catch_clause : CATCH opt_catch_args $$81 . block (829) + + OPEN_BRACE shift 143 + . error + + block goto 982 + + +state 884 + try_statement : TRY block catch_clauses FINALLY block . (822) + + . reduce 822 + + +state 885 + generic_dimension : GENERIC_DIMENSION . (554) + + . reduce 554 + + +state 886 + unbound_type_name : IDENTIFIER generic_dimension . (549) + + . reduce 549 + + +state 887 + member_name : namespace_or_type_name DOT . IDENTIFIER opt_type_argument_list (361) + unbound_type_name : namespace_or_type_name DOT . IDENTIFIER generic_dimension (553) + + IDENTIFIER shift 983 + . error + + +state 888 + namespace_or_type_name : qualified_alias_member IDENTIFIER . opt_type_argument_list (359) + unbound_type_name : qualified_alias_member IDENTIFIER . generic_dimension (550) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 273 + generic_dimension goto 984 + + +state 889 + typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression CLOSE_PARENS . (545) + + . reduce 545 + + +state 890 + unbound_type_name : unbound_type_name DOT . IDENTIFIER (551) + unbound_type_name : unbound_type_name DOT . IDENTIFIER generic_dimension (552) + + IDENTIFIER shift 985 + . error + + +state 891 + using_statement : USING open_parens_any expression CLOSE_PARENS $$85 . embedded_statement (848) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 986 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 892 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 . embedded_statement (846) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 987 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 893 + while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement . (785) + + . reduce 785 + + +state 894 + nested_from_clause : FROM type IDENTIFIER IN expression . (856) + + . reduce 856 + + +state 895 + first_from_clause : FROM_FIRST type IDENTIFIER IN expression . (854) + + . reduce 854 + + +state 896 + lambda_expression_body : $$66 expression . (634) + + . reduce 634 + + +state 897 + lambda_parameter : parameter_modifier parameter_type IDENTIFIER . (628) + + . reduce 628 + + +state 898 + lambda_parameter_list : lambda_parameter_list COMMA lambda_parameter . (627) + + . reduce 627 + + +state 899 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW . $$69 lambda_expression_body (640) + $$69 : . (639) + + . reduce 639 + + $$69 goto 988 + + +state 900 + non_simple_argument : ARGLIST OPEN_PARENS CLOSE_PARENS . (491) + + . reduce 491 + + +state 901 + argument_list : argument_list . COMMA argument (480) + argument_list : argument_list . COMMA named_argument (481) + argument_list : argument_list . COMMA (482) + non_simple_argument : ARGLIST OPEN_PARENS argument_list . CLOSE_PARENS (490) + + CLOSE_PARENS shift 989 + COMMA shift 787 + . error + + +state 902 + argument_list : argument_list COMMA named_argument . (481) + + . reduce 481 + + +state 903 + argument_list : argument_list COMMA argument . (480) + + . reduce 480 + + +state 904 + conditional_expression : null_coalescing_expression INTERR expression COLON expression . (614) + + . reduce 614 + + +state 905 + local_variable_initializer : STACKALLOC simple_type . OPEN_BRACKET_EXPR expression CLOSE_BRACKET (169) + local_variable_initializer : STACKALLOC simple_type . (171) + + OPEN_BRACKET_EXPR shift 990 + CLOSE_PARENS reduce 171 + COMMA reduce 171 + SEMICOLON reduce 171 + + +state 906 + variable_bad_array : OPEN_BRACKET_EXPR opt_expression CLOSE_BRACKET . (172) + + . reduce 172 + + +state 907 + from_clause : FROM IDENTIFIER IN $$86 . expression (858) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 991 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 908 + from_clause : FROM type IDENTIFIER IN . $$87 expression (860) + $$87 : . (859) + + . reduce 859 + + $$87 goto 992 + + +state 909 + join_clause : JOIN IDENTIFIER IN $$93 . expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 993 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 910 + join_clause : JOIN type IDENTIFIER IN . $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + $$96 : . (885) + + . reduce 885 + + $$96 goto 994 + + +state 911 + let_clause : LET IDENTIFIER ASSIGN $$91 . expression (878) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 995 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 912 + order_by : expression ASCENDING . (900) + + . reduce 900 + + +state 913 + order_by : expression DESCENDING . (901) + + . reduce 901 + + +state 914 + orderings : order_by COMMA . $$100 orderings_then_by (895) + $$100 : . (894) + + . reduce 894 + + $$100 goto 996 + + +state 915 + select_or_group_clause : SELECT $$88 expression . (864) + + . reduce 864 + + +state 916 + select_or_group_clause : GROUP $$89 expression . $$90 BY expression (867) + $$90 : . (866) + + . reduce 866 + + $$90 goto 997 + + +state 917 + opt_query_continuation : INTO IDENTIFIER . $$102 query_body (907) + $$102 : . (906) + + . reduce 906 + + $$102 goto 998 + + +state 918 + namespace_body_body : error . $$4 CLOSE_BRACE (39) + $$4 : . (38) + + . reduce 38 + + $$4 goto 999 + + +state 919 + extern_alias_directives : extern_alias_directive . (14) + + . reduce 14 + + +state 920 + extern_alias_directives : extern_alias_directives . extern_alias_directive (15) + opt_extern_alias_directives : extern_alias_directives . (44) + + EXTERN_ALIAS shift 3 + EOF reduce 44 + ABSTRACT reduce 44 + BOOL reduce 44 + BYTE reduce 44 + CHAR reduce 44 + CLASS reduce 44 + DECIMAL reduce 44 + DELEGATE reduce 44 + DOUBLE reduce 44 + ENUM reduce 44 + EXTERN reduce 44 + FIXED reduce 44 + FLOAT reduce 44 + INT reduce 44 + INTERFACE reduce 44 + INTERNAL reduce 44 + LONG reduce 44 + NAMESPACE reduce 44 + NEW reduce 44 + OBJECT reduce 44 + OVERRIDE reduce 44 + PRIVATE reduce 44 + PROTECTED reduce 44 + PUBLIC reduce 44 + READONLY reduce 44 + SBYTE reduce 44 + SEALED reduce 44 + SHORT reduce 44 + STATIC reduce 44 + STRING reduce 44 + STRUCT reduce 44 + UINT reduce 44 + ULONG reduce 44 + UNSAFE reduce 44 + USHORT reduce 44 + USING reduce 44 + VIRTUAL reduce 44 + VOID reduce 44 + VOLATILE reduce 44 + PARTIAL reduce 44 + CLOSE_BRACE reduce 44 + OPEN_BRACKET reduce 44 + IDENTIFIER reduce 44 + + extern_alias_directive goto 1000 + + +state 921 + namespace_body : OPEN_BRACE $$3 namespace_body_body . (36) + + . reduce 36 + + +state 922 + namespace_body_body : opt_extern_alias_directives . opt_using_directives opt_namespace_member_declarations CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives . opt_using_directives opt_namespace_member_declarations EOF (40) + opt_using_directives : . (41) + + USING shift 2 + EOF reduce 41 + ABSTRACT reduce 41 + BOOL reduce 41 + BYTE reduce 41 + CHAR reduce 41 + CLASS reduce 41 + DECIMAL reduce 41 + DELEGATE reduce 41 + DOUBLE reduce 41 + ENUM reduce 41 + EXTERN reduce 41 + FIXED reduce 41 + FLOAT reduce 41 + INT reduce 41 + INTERFACE reduce 41 + INTERNAL reduce 41 + LONG reduce 41 + NAMESPACE reduce 41 + NEW reduce 41 + OBJECT reduce 41 + OVERRIDE reduce 41 + PRIVATE reduce 41 + PROTECTED reduce 41 + PUBLIC reduce 41 + READONLY reduce 41 + SBYTE reduce 41 + SEALED reduce 41 + SHORT reduce 41 + STATIC reduce 41 + STRING reduce 41 + STRUCT reduce 41 + UINT reduce 41 + ULONG reduce 41 + UNSAFE reduce 41 + USHORT reduce 41 + VIRTUAL reduce 41 + VOID reduce 41 + VOLATILE reduce 41 + PARTIAL reduce 41 + CLOSE_BRACE reduce 41 + OPEN_BRACKET reduce 41 + IDENTIFIER reduce 41 + + using_directive goto 54 + using_directives goto 1001 + using_alias_directive goto 17 + using_namespace_directive goto 18 + opt_using_directives goto 1002 + + +state 923 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 . opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1003 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 924 + type_parameter : error . (383) + + . reduce 383 + + +state 925 + type_parameter : opt_attributes . opt_type_parameter_variance IDENTIFIER (382) + opt_type_parameter_variance : . (686) + + IN shift 1004 + OUT shift 1005 + IDENTIFIER reduce 686 + + opt_type_parameter_variance goto 1006 + type_parameter_variance goto 1007 + + +state 926 + opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters . OP_GENERICS_GT (379) + type_parameters : type_parameters . COMMA type_parameter (381) + + OP_GENERICS_GT shift 1008 + COMMA shift 1009 + . error + + +state 927 + type_parameters : type_parameter . (380) + + . reduce 380 + + +state 928 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE . $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + $$55 : . (338) + + . reduce 338 + + $$55 goto 1010 + + +state 929 + fixed_field_size : OPEN_BRACKET . $$18 expression CLOSE_BRACKET (160) + fixed_field_size : OPEN_BRACKET . error (161) + $$18 : . (159) + + error shift 1011 + BASE reduce 159 + BOOL reduce 159 + BYTE reduce 159 + CHAR reduce 159 + CHECKED reduce 159 + DECIMAL reduce 159 + DEFAULT reduce 159 + DELEGATE reduce 159 + DOUBLE reduce 159 + FALSE reduce 159 + FLOAT reduce 159 + INT reduce 159 + LONG reduce 159 + NEW reduce 159 + NULL reduce 159 + OBJECT reduce 159 + SBYTE reduce 159 + SHORT reduce 159 + SIZEOF reduce 159 + STRING reduce 159 + THIS reduce 159 + TRUE reduce 159 + TYPEOF reduce 159 + UINT reduce 159 + ULONG reduce 159 + UNCHECKED reduce 159 + USHORT reduce 159 + FROM reduce 159 + FROM_FIRST reduce 159 + OPEN_PARENS reduce 159 + TILDE reduce 159 + PLUS reduce 159 + MINUS reduce 159 + BANG reduce 159 + BITWISE_AND reduce 159 + STAR reduce 159 + OP_INC reduce 159 + OP_DEC reduce 159 + LITERAL reduce 159 + IDENTIFIER reduce 159 + OPEN_PARENS_LAMBDA reduce 159 + OPEN_PARENS_CAST reduce 159 + + $$18 goto 1012 + + +state 930 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size . opt_fixed_field_declarators SEMICOLON (142) + opt_fixed_field_declarators : . (154) + + COMMA shift 1013 + SEMICOLON reduce 154 + + opt_fixed_field_declarators goto 1014 + fixed_field_declarators goto 1015 + fixed_field_declarator goto 1016 + + +state 931 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 . opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1017 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 932 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 . opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1019 + + +state 933 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 . opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1020 + + +state 934 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 . opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1021 + + +state 935 + opt_field_initializer : ASSIGN $$16 . variable_initializer (146) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1022 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 936 + field_declarator : COMMA . IDENTIFIER (151) + field_declarator : COMMA . IDENTIFIER ASSIGN $$17 variable_initializer (153) + + IDENTIFIER shift 1023 + . error + + +state 937 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators . SEMICOLON (140) + + SEMICOLON shift 1024 + . error + + +state 938 + opt_field_declarators : field_declarators . (148) + field_declarators : field_declarators . field_declarator (150) + + COMMA shift 936 + SEMICOLON reduce 148 + + field_declarator goto 1025 + + +state 939 + field_declarators : field_declarator . (149) + + . reduce 149 + + +state 940 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list . CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + + CLOSE_PARENS shift 1026 + . error + + +state 941 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list . CLOSE_PARENS (183) + + CLOSE_PARENS shift 1027 + . error + + +state 942 + explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list DOT . (376) + + . reduce 376 + + +state 943 + explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list DOT . (377) + + . reduce 377 + + +state 944 + named_argument : IDENTIFIER COLON opt_named_modifier expression . (86) + + . reduce 86 + + +state 945 + named_attribute_argument : IDENTIFIER ASSIGN $$6 expression . (85) + + . reduce 85 + + +state 946 + params_modifier : PARAMS parameter_modifier . (215) + + . reduce 215 + + +state 947 + params_modifier : PARAMS params_modifier . (216) + + . reduce 216 + + +state 948 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER (199) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . error (201) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER ASSIGN $$24 constant_expression (203) + + error shift 1028 + IDENTIFIER shift 1029 + . error + + +state 949 + parameter_modifiers : parameter_modifiers parameter_modifier . (207) + + . reduce 207 + + +state 950 + parameter_array : opt_attributes params_modifier type . IDENTIFIER (211) + parameter_array : opt_attributes params_modifier type . IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes params_modifier type . error (213) + + error shift 1030 + IDENTIFIER shift 1031 + . error + + +state 951 + formal_parameter_list : fixed_parameters COMMA ARGLIST . COMMA error (194) + arglist_modifier : ARGLIST . (217) + + COMMA shift 1032 + CLOSE_BRACKET reduce 217 + CLOSE_PARENS reduce 217 + + +state 952 + formal_parameter_list : fixed_parameters COMMA parameter_array . (189) + formal_parameter_list : fixed_parameters COMMA parameter_array . COMMA error (192) + + COMMA shift 1033 + CLOSE_BRACKET reduce 189 + CLOSE_PARENS reduce 189 + + +state 953 + formal_parameter_list : fixed_parameters COMMA arglist_modifier . (190) + + . reduce 190 + + +state 954 + fixed_parameters : fixed_parameters COMMA fixed_parameter . (198) + + . reduce 198 + + +state 955 + formal_parameter_list : parameter_array COMMA error . (191) + + . reduce 191 + + +state 956 + formal_parameter_list : arglist_modifier COMMA error . (193) + + . reduce 193 + + +state 957 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS . SEMICOLON (786) + + SEMICOLON shift 1034 + . error + + +state 958 + fixed_pointer_declarator : IDENTIFIER ASSIGN expression . (842) + + . reduce 842 + + +state 959 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 . embedded_statement (839) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1035 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 960 + fixed_pointer_declarators : fixed_pointer_declarators COMMA fixed_pointer_declarator . (841) + + . reduce 841 + + +state 961 + opt_for_condition : boolean_expression . (794) + + . reduce 794 + + +state 962 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition . SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + SEMICOLON shift 1036 + . error + + +state 963 + foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS . (800) + + . reduce 800 + + +state 964 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression . CLOSE_PARENS $$80 embedded_statement (802) + + CLOSE_PARENS shift 1037 + . error + + +state 965 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE . embedded_statement (768) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1038 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 966 + variable_initializer_list : variable_initializer_list COMMA variable_initializer . (542) + + . reduce 542 + + +state 967 + array_initializer : OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE . (540) + + . reduce 540 + + +state 968 + member_initializer : OPEN_BRACE expression_list CLOSE_BRACE . (473) + + . reduce 473 + + +state 969 + initializer_value : expression . (475) + + . reduce 475 + + +state 970 + initializer_value : object_or_collection_initializer . (476) + + . reduce 476 + + +state 971 + member_initializer : IDENTIFIER ASSIGN initializer_value . (470) + + . reduce 470 + + +state 972 + object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE . (464) + + . reduce 464 + + +state 973 + member_initializer_list : member_initializer_list COMMA member_initializer . (468) + + . reduce 468 + + +state 974 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error . CLOSE_BRACKET (512) + + CLOSE_BRACKET shift 1039 + . error + + +state 975 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier . opt_array_initializer (509) + opt_array_initializer : . (537) + + OPEN_BRACE shift 531 + error reduce 537 + AS reduce 537 + IS reduce 537 + WHERE reduce 537 + FROM reduce 537 + JOIN reduce 537 + ON reduce 537 + EQUALS reduce 537 + SELECT reduce 537 + GROUP reduce 537 + BY reduce 537 + LET reduce 537 + ORDERBY reduce 537 + ASCENDING reduce 537 + DESCENDING reduce 537 + INTO reduce 537 + CLOSE_BRACE reduce 537 + CLOSE_BRACKET reduce 537 + OPEN_PARENS reduce 537 + CLOSE_PARENS reduce 537 + DOT reduce 537 + COMMA reduce 537 + COLON reduce 537 + SEMICOLON reduce 537 + PLUS reduce 537 + MINUS reduce 537 + ASSIGN reduce 537 + OP_LT reduce 537 + OP_GT reduce 537 + BITWISE_AND reduce 537 + BITWISE_OR reduce 537 + STAR reduce 537 + PERCENT reduce 537 + DIV reduce 537 + CARRET reduce 537 + INTERR reduce 537 + OP_INC reduce 537 + OP_DEC reduce 537 + OP_SHIFT_LEFT reduce 537 + OP_SHIFT_RIGHT reduce 537 + OP_LE reduce 537 + OP_GE reduce 537 + OP_EQ reduce 537 + OP_NE reduce 537 + OP_AND reduce 537 + OP_OR reduce 537 + OP_MULT_ASSIGN reduce 537 + OP_DIV_ASSIGN reduce 537 + OP_MOD_ASSIGN reduce 537 + OP_ADD_ASSIGN reduce 537 + OP_SUB_ASSIGN reduce 537 + OP_SHIFT_LEFT_ASSIGN reduce 537 + OP_SHIFT_RIGHT_ASSIGN reduce 537 + OP_AND_ASSIGN reduce 537 + OP_XOR_ASSIGN reduce 537 + OP_OR_ASSIGN reduce 537 + OP_PTR reduce 537 + OP_COALESCING reduce 537 + OPEN_PARENS_CAST reduce 537 + OPEN_BRACKET_EXPR reduce 537 + COMPLETE_COMPLETION reduce 537 + + array_initializer goto 733 + opt_array_initializer goto 1040 + + +state 976 + expression_list : expression_list COMMA expression . (496) + + . reduce 496 + + +state 977 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer . (507) + + . reduce 507 + + +state 978 + opt_object_or_collection_initializer : object_or_collection_initializer . (462) + + . reduce 462 + + +state 979 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE . opt_switch_sections CLOSE_BRACE (770) + opt_switch_sections : . (771) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + CLOSE_BRACE reduce 771 + + opt_switch_sections goto 1043 + switch_sections goto 1044 + switch_section goto 1045 + switch_labels goto 1046 + switch_label goto 1047 + + +state 980 + opt_identifier : IDENTIFIER . (827) + + . reduce 827 + + +state 981 + catch_args : open_parens_any type opt_identifier . CLOSE_PARENS (832) + + CLOSE_PARENS shift 1048 + . error + + +state 982 + catch_clause : CATCH opt_catch_args $$81 block . (829) + + . reduce 829 + + +state 983 + member_name : namespace_or_type_name DOT IDENTIFIER . opt_type_argument_list (361) + unbound_type_name : namespace_or_type_name DOT IDENTIFIER . generic_dimension (553) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 482 + generic_dimension goto 1049 + + +state 984 + unbound_type_name : qualified_alias_member IDENTIFIER generic_dimension . (550) + + . reduce 550 + + +state 985 + unbound_type_name : unbound_type_name DOT IDENTIFIER . (551) + unbound_type_name : unbound_type_name DOT IDENTIFIER . generic_dimension (552) + + GENERIC_DIMENSION shift 885 + CLOSE_PARENS reduce 551 + DOT reduce 551 + + generic_dimension goto 1050 + + +state 986 + using_statement : USING open_parens_any expression CLOSE_PARENS $$85 embedded_statement . (848) + + . reduce 848 + + +state 987 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement . (846) + + . reduce 846 + + +state 988 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 . lambda_expression_body (640) + $$66 : . (633) + + OPEN_BRACE shift 143 + BASE reduce 633 + BOOL reduce 633 + BYTE reduce 633 + CHAR reduce 633 + CHECKED reduce 633 + DECIMAL reduce 633 + DEFAULT reduce 633 + DELEGATE reduce 633 + DOUBLE reduce 633 + FALSE reduce 633 + FLOAT reduce 633 + INT reduce 633 + LONG reduce 633 + NEW reduce 633 + NULL reduce 633 + OBJECT reduce 633 + SBYTE reduce 633 + SHORT reduce 633 + SIZEOF reduce 633 + STRING reduce 633 + THIS reduce 633 + TRUE reduce 633 + TYPEOF reduce 633 + UINT reduce 633 + ULONG reduce 633 + UNCHECKED reduce 633 + USHORT reduce 633 + FROM reduce 633 + FROM_FIRST reduce 633 + OPEN_PARENS reduce 633 + TILDE reduce 633 + PLUS reduce 633 + MINUS reduce 633 + BANG reduce 633 + BITWISE_AND reduce 633 + STAR reduce 633 + OP_INC reduce 633 + OP_DEC reduce 633 + LITERAL reduce 633 + IDENTIFIER reduce 633 + OPEN_PARENS_LAMBDA reduce 633 + OPEN_PARENS_CAST reduce 633 + + block goto 765 + lambda_expression_body goto 1051 + $$66 goto 767 + + +state 989 + non_simple_argument : ARGLIST OPEN_PARENS argument_list CLOSE_PARENS . (490) + + . reduce 490 + + +state 990 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR . expression CLOSE_BRACKET (169) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1052 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 991 + from_clause : FROM IDENTIFIER IN $$86 expression . (858) + + . reduce 858 + + +state 992 + from_clause : FROM type IDENTIFIER IN $$87 . expression (860) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1053 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 993 + join_clause : JOIN IDENTIFIER IN $$93 expression . ON $$94 expression EQUALS $$95 expression opt_join_into (884) + + ON shift 1054 + . error + + +state 994 + join_clause : JOIN type IDENTIFIER IN $$96 . expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1055 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 995 + let_clause : LET IDENTIFIER ASSIGN $$91 expression . (878) + + . reduce 878 + + +state 996 + orderings : order_by COMMA $$100 . orderings_then_by (895) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1056 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + orderings_then_by goto 1057 + then_by goto 1058 + + +state 997 + select_or_group_clause : GROUP $$89 expression $$90 . BY expression (867) + + BY shift 1059 + . error + + +state 998 + opt_query_continuation : INTO IDENTIFIER $$102 . query_body (907) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + SELECT reduce 868 + GROUP reduce 868 + COMPLETE_COMPLETION reduce 868 + + query_body goto 1060 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 999 + namespace_body_body : error $$4 . CLOSE_BRACE (39) + + CLOSE_BRACE shift 1061 + . error + + +state 1000 + extern_alias_directives : extern_alias_directives extern_alias_directive . (15) + + . reduce 15 + + +state 1001 + using_directives : using_directives . using_directive (19) + opt_using_directives : using_directives . (42) + + USING shift 2 + EOF reduce 42 + ABSTRACT reduce 42 + BOOL reduce 42 + BYTE reduce 42 + CHAR reduce 42 + CLASS reduce 42 + DECIMAL reduce 42 + DELEGATE reduce 42 + DOUBLE reduce 42 + ENUM reduce 42 + EXTERN reduce 42 + FIXED reduce 42 + FLOAT reduce 42 + INT reduce 42 + INTERFACE reduce 42 + INTERNAL reduce 42 + LONG reduce 42 + NAMESPACE reduce 42 + NEW reduce 42 + OBJECT reduce 42 + OVERRIDE reduce 42 + PRIVATE reduce 42 + PROTECTED reduce 42 + PUBLIC reduce 42 + READONLY reduce 42 + SBYTE reduce 42 + SEALED reduce 42 + SHORT reduce 42 + STATIC reduce 42 + STRING reduce 42 + STRUCT reduce 42 + UINT reduce 42 + ULONG reduce 42 + UNSAFE reduce 42 + USHORT reduce 42 + VIRTUAL reduce 42 + VOID reduce 42 + VOLATILE reduce 42 + PARTIAL reduce 42 + CLOSE_BRACE reduce 42 + OPEN_BRACKET reduce 42 + IDENTIFIER reduce 42 + + using_directive goto 244 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 1002 + namespace_body_body : opt_extern_alias_directives opt_using_directives . opt_namespace_member_declarations CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives opt_using_directives . opt_namespace_member_declarations EOF (40) + opt_namespace_member_declarations : . (45) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + EOF reduce 45 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 45 + IDENTIFIER reduce 59 + + namespace_member_declaration goto 1062 + namespace_declaration goto 19 + opt_attributes goto 20 + opt_namespace_member_declarations goto 1063 + namespace_member_declarations goto 1064 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + method_header goto 31 + + +state 1003 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list . CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + CLOSE_PARENS shift 1065 + . error + + +state 1004 + type_parameter_variance : IN . (689) + + . reduce 689 + + +state 1005 + type_parameter_variance : OUT . (688) + + . reduce 688 + + +state 1006 + type_parameter : opt_attributes opt_type_parameter_variance . IDENTIFIER (382) + + IDENTIFIER shift 1066 + . error + + +state 1007 + opt_type_parameter_variance : type_parameter_variance . (687) + + . reduce 687 + + +state 1008 + opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT . (379) + + . reduce 379 + + +state 1009 + type_parameters : type_parameters COMMA . type_parameter (381) + opt_attributes : . (59) + + error shift 924 + OPEN_BRACKET shift 4 + IN reduce 59 + OUT reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 925 + attribute_sections goto 693 + attribute_section goto 30 + type_parameter goto 1067 + + +state 1010 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 . opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + opt_attributes : . (59) + opt_enum_member_declarations : . (344) + + OPEN_BRACKET shift 4 + CLOSE_BRACE reduce 344 + IDENTIFIER reduce 59 + + opt_attributes goto 1068 + attribute_sections goto 693 + attribute_section goto 30 + opt_enum_member_declarations goto 1069 + enum_member_declarations goto 1070 + enum_member_declaration goto 1071 + + +state 1011 + fixed_field_size : OPEN_BRACKET error . (161) + + . reduce 161 + + +state 1012 + fixed_field_size : OPEN_BRACKET $$18 . expression CLOSE_BRACKET (160) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1072 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1013 + fixed_field_declarator : COMMA . IDENTIFIER fixed_field_size (158) + + IDENTIFIER shift 1073 + . error + + +state 1014 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators . SEMICOLON (142) + + SEMICOLON shift 1074 + . error + + +state 1015 + opt_fixed_field_declarators : fixed_field_declarators . (155) + fixed_field_declarators : fixed_field_declarators . fixed_field_declarator (157) + + COMMA shift 1013 + SEMICOLON reduce 155 + + fixed_field_declarator goto 1075 + + +state 1016 + fixed_field_declarators : fixed_field_declarator . (156) + + . reduce 156 + + +state 1017 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list . CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + CLOSE_PARENS shift 1076 + . error + + +state 1018 + opt_class_base : COLON . type_list (674) + + error shift 1077 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1078 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + type_list goto 1079 + base_type_name goto 1080 + integral_type goto 162 + + +state 1019 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base . opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1082 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1020 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base . opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1085 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1021 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base . opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1086 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1022 + opt_field_initializer : ASSIGN $$16 variable_initializer . (146) + + . reduce 146 + + +state 1023 + field_declarator : COMMA IDENTIFIER . (151) + field_declarator : COMMA IDENTIFIER . ASSIGN $$17 variable_initializer (153) + + ASSIGN shift 1087 + COMMA reduce 151 + SEMICOLON reduce 151 + + +state 1024 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON . (140) + + . reduce 140 + + +state 1025 + field_declarators : field_declarators field_declarator . (150) + + . reduce 150 + + +state 1026 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS . $$21 opt_type_parameter_constraints_clauses (179) + $$21 : . (178) + + . reduce 178 + + $$21 goto 1088 + + +state 1027 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS . (183) + + . reduce 183 + + +state 1028 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type error . (201) + + . reduce 201 + + +state 1029 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . (199) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . ASSIGN $$24 constant_expression (203) + + OPEN_BRACKET shift 1089 + ASSIGN shift 1090 + CLOSE_BRACKET reduce 199 + CLOSE_PARENS reduce 199 + COMMA reduce 199 + + +state 1030 + parameter_array : opt_attributes params_modifier type error . (213) + + . reduce 213 + + +state 1031 + parameter_array : opt_attributes params_modifier type IDENTIFIER . (211) + parameter_array : opt_attributes params_modifier type IDENTIFIER . ASSIGN constant_expression (212) + + ASSIGN shift 1091 + CLOSE_BRACKET reduce 211 + CLOSE_PARENS reduce 211 + COMMA reduce 211 + + +state 1032 + formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA . error (194) + + error shift 1092 + . error + + +state 1033 + formal_parameter_list : fixed_parameters COMMA parameter_array COMMA . error (192) + + error shift 1093 + . error + + +state 1034 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON . (786) + + . reduce 786 + + +state 1035 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement . (839) + + . reduce 839 + + +state 1036 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON . opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_iterator : . (795) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 795 + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_expression goto 509 + opt_for_iterator goto 1094 + statement_expression_list goto 1095 + for_iterator goto 1096 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1037 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS . $$80 embedded_statement (802) + $$80 : . (801) + + . reduce 801 + + $$80 goto 1097 + + +state 1038 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement . (768) + + . reduce 768 + + +state 1039 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET . (512) + + . reduce 512 + + +state 1040 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer . (509) + + . reduce 509 + + +state 1041 + switch_label : CASE . constant_expression COLON (779) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1098 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1042 + switch_label : DEFAULT_COLON . (780) + + . reduce 780 + + +state 1043 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections . CLOSE_BRACE (770) + + CLOSE_BRACE shift 1099 + . error + + +state 1044 + opt_switch_sections : switch_sections . (772) + switch_sections : switch_sections . switch_section (774) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + CLOSE_BRACE reduce 772 + + switch_section goto 1100 + switch_labels goto 1046 + switch_label goto 1047 + + +state 1045 + switch_sections : switch_section . (773) + + . reduce 773 + + +state 1046 + switch_section : switch_labels . $$78 statement_list (776) + switch_labels : switch_labels . switch_label (778) + $$78 : . (775) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + error reduce 775 + BASE reduce 775 + BOOL reduce 775 + BREAK reduce 775 + BYTE reduce 775 + CHAR reduce 775 + CHECKED reduce 775 + CONST reduce 775 + CONTINUE reduce 775 + DECIMAL reduce 775 + DEFAULT reduce 775 + DELEGATE reduce 775 + DO reduce 775 + DOUBLE reduce 775 + FALSE reduce 775 + FIXED reduce 775 + FLOAT reduce 775 + FOR reduce 775 + FOREACH reduce 775 + GOTO reduce 775 + IF reduce 775 + INT reduce 775 + LOCK reduce 775 + LONG reduce 775 + NEW reduce 775 + NULL reduce 775 + OBJECT reduce 775 + RETURN reduce 775 + SBYTE reduce 775 + SHORT reduce 775 + SIZEOF reduce 775 + STRING reduce 775 + SWITCH reduce 775 + THIS reduce 775 + THROW reduce 775 + TRUE reduce 775 + TRY reduce 775 + TYPEOF reduce 775 + UINT reduce 775 + ULONG reduce 775 + UNCHECKED reduce 775 + UNSAFE reduce 775 + USHORT reduce 775 + USING reduce 775 + VOID reduce 775 + WHILE reduce 775 + FROM reduce 775 + FROM_FIRST reduce 775 + OPEN_BRACE reduce 775 + OPEN_PARENS reduce 775 + SEMICOLON reduce 775 + TILDE reduce 775 + PLUS reduce 775 + MINUS reduce 775 + BANG reduce 775 + BITWISE_AND reduce 775 + STAR reduce 775 + OP_INC reduce 775 + OP_DEC reduce 775 + LITERAL reduce 775 + IDENTIFIER reduce 775 + OPEN_PARENS_LAMBDA reduce 775 + OPEN_PARENS_CAST reduce 775 + + $$78 goto 1101 + switch_label goto 1102 + + +state 1047 + switch_labels : switch_label . (777) + + . reduce 777 + + +state 1048 + catch_args : open_parens_any type opt_identifier CLOSE_PARENS . (832) + + . reduce 832 + + +state 1049 + unbound_type_name : namespace_or_type_name DOT IDENTIFIER generic_dimension . (553) + + . reduce 553 + + +state 1050 + unbound_type_name : unbound_type_name DOT IDENTIFIER generic_dimension . (552) + + . reduce 552 + + +state 1051 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body . (640) + + . reduce 640 + + +state 1052 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression . CLOSE_BRACKET (169) + + CLOSE_BRACKET shift 1103 + . error + + +state 1053 + from_clause : FROM type IDENTIFIER IN $$87 expression . (860) + + . reduce 860 + + +state 1054 + join_clause : JOIN IDENTIFIER IN $$93 expression ON . $$94 expression EQUALS $$95 expression opt_join_into (884) + $$94 : . (882) + + . reduce 882 + + $$94 goto 1104 + + +state 1055 + join_clause : JOIN type IDENTIFIER IN $$96 expression . ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + ON shift 1105 + . error + + +state 1056 + then_by : expression . (902) + then_by : expression . ASCENDING (903) + then_by : expression . DESCENDING (904) + + ASCENDING shift 1106 + DESCENDING shift 1107 + WHERE reduce 902 + FROM reduce 902 + JOIN reduce 902 + SELECT reduce 902 + GROUP reduce 902 + LET reduce 902 + ORDERBY reduce 902 + COMMA reduce 902 + COMPLETE_COMPLETION reduce 902 + + +state 1057 + orderings : order_by COMMA $$100 orderings_then_by . (895) + orderings_then_by : orderings_then_by . COMMA $$101 then_by (898) + + COMMA shift 1108 + WHERE reduce 895 + FROM reduce 895 + JOIN reduce 895 + SELECT reduce 895 + GROUP reduce 895 + LET reduce 895 + ORDERBY reduce 895 + COMPLETE_COMPLETION reduce 895 + + +state 1058 + orderings_then_by : then_by . (896) + + . reduce 896 + + +state 1059 + select_or_group_clause : GROUP $$89 expression $$90 BY . expression (867) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1109 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1060 + opt_query_continuation : INTO IDENTIFIER $$102 query_body . (907) + + . reduce 907 + + +state 1061 + namespace_body_body : error $$4 CLOSE_BRACE . (39) + + . reduce 39 + + +state 1062 + namespace_member_declarations : namespace_member_declaration . (47) + + . reduce 47 + + +state 1063 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations . CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations . EOF (40) + + EOF shift 1110 + CLOSE_BRACE shift 1111 + . error + + +state 1064 + opt_namespace_member_declarations : namespace_member_declarations . (46) + namespace_member_declarations : namespace_member_declarations . namespace_member_declaration (48) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + EOF reduce 46 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 46 + IDENTIFIER reduce 59 + + namespace_member_declaration goto 1112 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + method_header goto 31 + + +state 1065 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS . $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + $$59 : . (353) + + . reduce 353 + + $$59 goto 1113 + + +state 1066 + type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER . (382) + + . reduce 382 + + +state 1067 + type_parameters : type_parameters COMMA type_parameter . (381) + + . reduce 381 + + +state 1068 + enum_member_declaration : opt_attributes . IDENTIFIER (349) + enum_member_declaration : opt_attributes . IDENTIFIER $$57 ASSIGN constant_expression (351) + + IDENTIFIER shift 1114 + . error + + +state 1069 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations . $$56 CLOSE_BRACE opt_semicolon (340) + $$56 : . (339) + + . reduce 339 + + $$56 goto 1115 + + +state 1070 + opt_enum_member_declarations : enum_member_declarations . (345) + opt_enum_member_declarations : enum_member_declarations . COMMA (346) + enum_member_declarations : enum_member_declarations . COMMA enum_member_declaration (348) + + COMMA shift 1116 + CLOSE_BRACE reduce 345 + + +state 1071 + enum_member_declarations : enum_member_declaration . (347) + + . reduce 347 + + +state 1072 + fixed_field_size : OPEN_BRACKET $$18 expression . CLOSE_BRACKET (160) + + CLOSE_BRACKET shift 1117 + . error + + +state 1073 + fixed_field_declarator : COMMA IDENTIFIER . fixed_field_size (158) + + OPEN_BRACKET shift 929 + . error + + fixed_field_size goto 1118 + + +state 1074 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON . (142) + + . reduce 142 + + +state 1075 + fixed_field_declarators : fixed_field_declarators fixed_field_declarator . (157) + + . reduce 157 + + +state 1076 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS . $$23 opt_type_parameter_constraints_clauses (182) + $$23 : . (181) + + . reduce 181 + + $$23 goto 1119 + + +state 1077 + base_type_name : error . (402) + + . reduce 402 + + +state 1078 + base_type_name : type . (401) + + . reduce 401 + + +state 1079 + type_list : type_list . COMMA base_type_name (400) + opt_class_base : COLON type_list . (674) + + COMMA shift 1120 + WHERE reduce 674 + OPEN_BRACE reduce 674 + + +state 1080 + type_list : base_type_name . (399) + + . reduce 399 + + +state 1081 + type_parameter_constraints_clause : WHERE . IDENTIFIER COLON type_parameter_constraints (679) + + IDENTIFIER shift 1121 + . error + + +state 1082 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses . $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$72 : . (650) + + . reduce 650 + + $$72 goto 1122 + + +state 1083 + opt_type_parameter_constraints_clauses : type_parameter_constraints_clauses . (676) + type_parameter_constraints_clauses : type_parameter_constraints_clauses . type_parameter_constraints_clause (678) + + WHERE shift 1081 + OPEN_BRACE reduce 676 + SEMICOLON reduce 676 + + type_parameter_constraints_clause goto 1123 + + +state 1084 + type_parameter_constraints_clauses : type_parameter_constraints_clause . (677) + + . reduce 677 + + +state 1085 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses . $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + $$35 : . (240) + + . reduce 240 + + $$35 goto 1124 + + +state 1086 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses . $$9 struct_body $$10 opt_semicolon (109) + $$9 : . (107) + + . reduce 107 + + $$9 goto 1125 + + +state 1087 + field_declarator : COMMA IDENTIFIER ASSIGN . $$17 variable_initializer (153) + $$17 : . (152) + + . reduce 152 + + $$17 goto 1126 + + +state 1088 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 . opt_type_parameter_constraints_clauses (179) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1127 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1089 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET . CLOSE_BRACKET (200) + + CLOSE_BRACKET shift 1128 + . error + + +state 1090 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN . $$24 constant_expression (203) + $$24 : . (202) + + . reduce 202 + + $$24 goto 1129 + + +state 1091 + parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN . constant_expression (212) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1130 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1092 + formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA error . (194) + + . reduce 194 + + +state 1093 + formal_parameter_list : fixed_parameters COMMA parameter_array COMMA error . (192) + + . reduce 192 + + +state 1094 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator . CLOSE_PARENS embedded_statement (788) + + CLOSE_PARENS shift 1131 + . error + + +state 1095 + for_iterator : statement_expression_list . (797) + statement_expression_list : statement_expression_list . COMMA statement_expression (799) + + COMMA shift 706 + CLOSE_PARENS reduce 797 + + +state 1096 + opt_for_iterator : for_iterator . (796) + + . reduce 796 + + +state 1097 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 . embedded_statement (802) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1132 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1098 + switch_label : CASE constant_expression . COLON (779) + + COLON shift 1133 + . error + + +state 1099 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE . (770) + + . reduce 770 + + +state 1100 + switch_sections : switch_sections switch_section . (774) + + . reduce 774 + + +state 1101 + switch_section : switch_labels $$78 . statement_list (776) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_list goto 1134 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1102 + switch_labels : switch_labels switch_label . (778) + + . reduce 778 + + +state 1103 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET . (169) + + . reduce 169 + + +state 1104 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 . expression EQUALS $$95 expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1135 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1105 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON . $$97 expression EQUALS $$98 expression opt_join_into (888) + $$97 : . (886) + + . reduce 886 + + $$97 goto 1136 + + +state 1106 + then_by : expression ASCENDING . (903) + + . reduce 903 + + +state 1107 + then_by : expression DESCENDING . (904) + + . reduce 904 + + +state 1108 + orderings_then_by : orderings_then_by COMMA . $$101 then_by (898) + $$101 : . (897) + + . reduce 897 + + $$101 goto 1137 + + +state 1109 + select_or_group_clause : GROUP $$89 expression $$90 BY expression . (867) + + . reduce 867 + + +state 1110 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations EOF . (40) + + . reduce 40 + + +state 1111 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations CLOSE_BRACE . (37) + + . reduce 37 + + +state 1112 + namespace_member_declarations : namespace_member_declarations namespace_member_declaration . (48) + + . reduce 48 + + +state 1113 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 . opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1138 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1114 + enum_member_declaration : opt_attributes IDENTIFIER . (349) + enum_member_declaration : opt_attributes IDENTIFIER . $$57 ASSIGN constant_expression (351) + $$57 : . (350) + + CLOSE_BRACE reduce 349 + COMMA reduce 349 + ASSIGN reduce 350 + + $$57 goto 1139 + + +state 1115 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 . CLOSE_BRACE opt_semicolon (340) + + CLOSE_BRACE shift 1140 + . error + + +state 1116 + opt_enum_member_declarations : enum_member_declarations COMMA . (346) + enum_member_declarations : enum_member_declarations COMMA . enum_member_declaration (348) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + CLOSE_BRACE reduce 346 + IDENTIFIER reduce 59 + + opt_attributes goto 1068 + attribute_sections goto 693 + attribute_section goto 30 + enum_member_declaration goto 1141 + + +state 1117 + fixed_field_size : OPEN_BRACKET $$18 expression CLOSE_BRACKET . (160) + + . reduce 160 + + +state 1118 + fixed_field_declarator : COMMA IDENTIFIER fixed_field_size . (158) + + . reduce 158 + + +state 1119 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 . opt_type_parameter_constraints_clauses (182) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1142 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1120 + type_list : type_list COMMA . base_type_name (400) + + error shift 1077 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1078 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + base_type_name goto 1143 + integral_type goto 162 + + +state 1121 + type_parameter_constraints_clause : WHERE IDENTIFIER . COLON type_parameter_constraints (679) + + COLON shift 1144 + . error + + +state 1122 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 . OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + OPEN_BRACE shift 1145 + . error + + +state 1123 + type_parameter_constraints_clauses : type_parameter_constraints_clauses type_parameter_constraints_clause . (678) + + . reduce 678 + + +state 1124 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 . OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + + OPEN_BRACE shift 1146 + . error + + +state 1125 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 . struct_body $$10 opt_semicolon (109) + + OPEN_BRACE shift 1147 + . error + + struct_body goto 1148 + + +state 1126 + field_declarator : COMMA IDENTIFIER ASSIGN $$17 . variable_initializer (153) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1149 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1127 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses . (179) + + . reduce 179 + + +state 1128 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET . (200) + + . reduce 200 + + +state 1129 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 . constant_expression (203) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1150 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1130 + parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression . (212) + + . reduce 212 + + +state 1131 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS . embedded_statement (788) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1151 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1132 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement . (802) + + . reduce 802 + + +state 1133 + switch_label : CASE constant_expression COLON . (779) + + . reduce 779 + + +state 1134 + statement_list : statement_list . statement (699) + switch_section : switch_labels $$78 statement_list . (776) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CASE reduce 776 + CLOSE_BRACE reduce 776 + DEFAULT_COLON reduce 776 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 762 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1135 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression . EQUALS $$95 expression opt_join_into (884) + + EQUALS shift 1152 + . error + + +state 1136 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 . expression EQUALS $$98 expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1153 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1137 + orderings_then_by : orderings_then_by COMMA $$101 . then_by (898) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1056 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + then_by goto 1154 + + +state 1138 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses . $$60 SEMICOLON (355) + $$60 : . (354) + + . reduce 354 + + $$60 goto 1155 + + +state 1139 + enum_member_declaration : opt_attributes IDENTIFIER $$57 . ASSIGN constant_expression (351) + + ASSIGN shift 1156 + . error + + +state 1140 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE . opt_semicolon (340) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1157 + + +state 1141 + enum_member_declarations : enum_member_declarations COMMA enum_member_declaration . (348) + + . reduce 348 + + +state 1142 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses . (182) + + . reduce 182 + + +state 1143 + type_list : type_list COMMA base_type_name . (400) + + . reduce 400 + + +state 1144 + type_parameter_constraints_clause : WHERE IDENTIFIER COLON . type_parameter_constraints (679) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CLASS shift 1158 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 1159 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + STRUCT shift 1160 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1161 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + type_parameter_constraints goto 1162 + type_parameter_constraint goto 1163 + + +state 1145 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE . opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_attributes : . (59) + opt_class_member_declarations : . (90) + + error shift 1164 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 90 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1166 + field_declaration goto 1167 + method_declaration goto 1168 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + opt_class_member_declarations goto 1169 + class_member_declarations goto 1170 + class_member_declaration goto 1171 + constant_declaration goto 1172 + property_declaration goto 1173 + event_declaration goto 1174 + indexer_declaration goto 1175 + operator_declaration goto 1176 + constructor_declaration goto 1177 + destructor_declaration goto 1178 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1146 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE . opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_attributes : . (59) + opt_interface_member_declarations : . (244) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 244 + IDENTIFIER reduce 59 + + opt_attributes goto 1180 + type_declaration goto 1181 + field_declaration goto 1182 + method_declaration goto 1183 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1184 + property_declaration goto 1185 + event_declaration goto 1186 + indexer_declaration goto 1187 + operator_declaration goto 1188 + constructor_declaration goto 1189 + method_header goto 31 + opt_interface_member_declarations goto 1190 + interface_member_declarations goto 1191 + interface_member_declaration goto 1192 + constructor_declarator goto 1179 + + +state 1147 + struct_body : OPEN_BRACE . $$11 opt_struct_member_declarations CLOSE_BRACE (112) + $$11 : . (111) + + . reduce 111 + + $$11 goto 1193 + + +state 1148 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body . $$10 opt_semicolon (109) + $$10 : . (108) + + . reduce 108 + + $$10 goto 1194 + + +state 1149 + field_declarator : COMMA IDENTIFIER ASSIGN $$17 variable_initializer . (153) + + . reduce 153 + + +state 1150 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression . (203) + + . reduce 203 + + +state 1151 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement . (788) + + . reduce 788 + + +state 1152 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS . $$95 expression opt_join_into (884) + $$95 : . (883) + + . reduce 883 + + $$95 goto 1195 + + +state 1153 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression . EQUALS $$98 expression opt_join_into (888) + + EQUALS shift 1196 + . error + + +state 1154 + orderings_then_by : orderings_then_by COMMA $$101 then_by . (898) + + . reduce 898 + + +state 1155 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 . SEMICOLON (355) + + SEMICOLON shift 1197 + . error + + +state 1156 + enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN . constant_expression (351) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1198 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1157 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon . (340) + + . reduce 340 + + +state 1158 + type_parameter_constraint : CLASS . (684) + + . reduce 684 + + +state 1159 + type_parameter_constraint : NEW . OPEN_PARENS CLOSE_PARENS (683) + + OPEN_PARENS shift 1199 + . error + + +state 1160 + type_parameter_constraint : STRUCT . (685) + + . reduce 685 + + +state 1161 + type_parameter_constraint : type . (682) + + . reduce 682 + + +state 1162 + type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints . (679) + type_parameter_constraints : type_parameter_constraints . COMMA type_parameter_constraint (681) + + COMMA shift 1200 + WHERE reduce 679 + OPEN_BRACE reduce 679 + SEMICOLON reduce 679 + + +state 1163 + type_parameter_constraints : type_parameter_constraint . (680) + + . reduce 680 + + +state 1164 + class_member_declaration : error . (104) + + . reduce 104 + + +state 1165 + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + constant_declaration : opt_attributes . opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes . opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes . opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + operator_declaration : opt_attributes . opt_modifiers operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes . opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + destructor_declaration : opt_attributes . opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + CONST reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + EVENT reduce 655 + EXPLICIT reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + IMPLICIT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + TILDE reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 1201 + modifiers goto 77 + modifier goto 78 + + +state 1166 + class_member_declaration : type_declaration . (103) + + . reduce 103 + + +state 1167 + class_member_declaration : field_declaration . (95) + + . reduce 95 + + +state 1168 + class_member_declaration : method_declaration . (96) + + . reduce 96 + + +state 1169 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations . CLOSE_BRACE $$73 opt_semicolon (652) + + CLOSE_BRACE shift 1202 + . error + + +state 1170 + opt_class_member_declarations : class_member_declarations . (91) + class_member_declarations : class_member_declarations . class_member_declaration (93) + opt_attributes : . (59) + + error shift 1164 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 91 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1166 + field_declaration goto 1167 + method_declaration goto 1168 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + class_member_declaration goto 1203 + constant_declaration goto 1172 + property_declaration goto 1173 + event_declaration goto 1174 + indexer_declaration goto 1175 + operator_declaration goto 1176 + constructor_declaration goto 1177 + destructor_declaration goto 1178 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1171 + class_member_declarations : class_member_declaration . (92) + + . reduce 92 + + +state 1172 + class_member_declaration : constant_declaration . (94) + + . reduce 94 + + +state 1173 + class_member_declaration : property_declaration . (97) + + . reduce 97 + + +state 1174 + class_member_declaration : event_declaration . (98) + + . reduce 98 + + +state 1175 + class_member_declaration : indexer_declaration . (99) + + . reduce 99 + + +state 1176 + class_member_declaration : operator_declaration . (100) + + . reduce 100 + + +state 1177 + class_member_declaration : constructor_declaration . (101) + + . reduce 101 + + +state 1178 + class_member_declaration : destructor_declaration . (102) + + . reduce 102 + + +state 1179 + constructor_declaration : constructor_declarator . constructor_body (294) + + OPEN_BRACE shift 1204 + SEMICOLON shift 1205 + . error + + constructor_body goto 1206 + block_prepared goto 1207 + + +state 1180 + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + constant_declaration : opt_attributes . opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes . opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes . opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + operator_declaration : opt_attributes . opt_modifiers operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes . opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + CONST reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + EVENT reduce 655 + EXPLICIT reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + IMPLICIT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 1208 + modifiers goto 77 + modifier goto 78 + + +state 1181 + interface_member_declaration : type_declaration . (256) + + . reduce 256 + + +state 1182 + interface_member_declaration : field_declaration . (249) + + . reduce 249 + + +state 1183 + interface_member_declaration : method_declaration . (250) + + . reduce 250 + + +state 1184 + interface_member_declaration : constant_declaration . (248) + + . reduce 248 + + +state 1185 + interface_member_declaration : property_declaration . (251) + + . reduce 251 + + +state 1186 + interface_member_declaration : event_declaration . (252) + + . reduce 252 + + +state 1187 + interface_member_declaration : indexer_declaration . (253) + + . reduce 253 + + +state 1188 + interface_member_declaration : operator_declaration . (254) + + . reduce 254 + + +state 1189 + interface_member_declaration : constructor_declaration . (255) + + . reduce 255 + + +state 1190 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations . CLOSE_BRACE $$36 opt_semicolon (242) + + CLOSE_BRACE shift 1209 + . error + + +state 1191 + opt_interface_member_declarations : interface_member_declarations . (245) + interface_member_declarations : interface_member_declarations . interface_member_declaration (247) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 245 + IDENTIFIER reduce 59 + + opt_attributes goto 1180 + type_declaration goto 1181 + field_declaration goto 1182 + method_declaration goto 1183 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1184 + property_declaration goto 1185 + event_declaration goto 1186 + indexer_declaration goto 1187 + operator_declaration goto 1188 + constructor_declaration goto 1189 + method_header goto 31 + interface_member_declaration goto 1210 + constructor_declarator goto 1179 + + +state 1192 + interface_member_declarations : interface_member_declaration . (246) + + . reduce 246 + + +state 1193 + struct_body : OPEN_BRACE $$11 . opt_struct_member_declarations CLOSE_BRACE (112) + opt_attributes : . (59) + opt_struct_member_declarations : . (113) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 113 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1211 + field_declaration goto 1212 + method_declaration goto 1213 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1214 + property_declaration goto 1215 + event_declaration goto 1216 + indexer_declaration goto 1217 + operator_declaration goto 1218 + constructor_declaration goto 1219 + destructor_declaration goto 1220 + opt_struct_member_declarations goto 1221 + struct_member_declarations goto 1222 + struct_member_declaration goto 1223 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1194 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 . opt_semicolon (109) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1224 + + +state 1195 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 . expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1225 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1196 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS . $$98 expression opt_join_into (888) + $$98 : . (887) + + . reduce 887 + + $$98 goto 1226 + + +state 1197 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON . (355) + + . reduce 355 + + +state 1198 + enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN constant_expression . (351) + + . reduce 351 + + +state 1199 + type_parameter_constraint : NEW OPEN_PARENS . CLOSE_PARENS (683) + + CLOSE_PARENS shift 1227 + . error + + +state 1200 + type_parameter_constraints : type_parameter_constraints COMMA . type_parameter_constraint (681) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CLASS shift 1158 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 1159 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + STRUCT shift 1160 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1161 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + type_parameter_constraint goto 1228 + + +state 1201 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + constant_declaration : opt_attributes opt_modifiers . CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers . member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers . member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + operator_declaration : opt_attributes opt_modifiers . operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes opt_modifiers . IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + destructor_declaration : opt_attributes opt_modifiers . TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CONST shift 1229 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + EVENT shift 1230 + EXPLICIT shift 1231 + FIXED shift 252 + FLOAT shift 111 + IMPLICIT shift 1232 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 1233 + PARTIAL shift 254 + TILDE shift 1234 + IDENTIFIER shift 1235 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 1236 + operator_declarator goto 1237 + operator_type goto 1238 + type_expression_or_array goto 1239 + conversion_operator_declarator goto 1240 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1202 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE . $$73 opt_semicolon (652) + $$73 : . (651) + + . reduce 651 + + $$73 goto 1241 + + +state 1203 + class_member_declarations : class_member_declarations class_member_declaration . (93) + + . reduce 93 + + +state 1204 + block_prepared : OPEN_BRACE . $$75 opt_statement_list CLOSE_BRACE (695) + $$75 : . (694) + + . reduce 694 + + $$75 goto 1242 + + +state 1205 + constructor_body : SEMICOLON . (299) + + . reduce 299 + + +state 1206 + constructor_declaration : constructor_declarator constructor_body . (294) + + . reduce 294 + + +state 1207 + constructor_body : block_prepared . (298) + + . reduce 298 + + +state 1208 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + constant_declaration : opt_attributes opt_modifiers . CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers . member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers . member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + operator_declaration : opt_attributes opt_modifiers . operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes opt_modifiers . IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CONST shift 1229 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + EVENT shift 1230 + EXPLICIT shift 1231 + FIXED shift 252 + FLOAT shift 111 + IMPLICIT shift 1232 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 1233 + PARTIAL shift 254 + IDENTIFIER shift 1235 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 1236 + operator_declarator goto 1237 + operator_type goto 1238 + type_expression_or_array goto 1239 + conversion_operator_declarator goto 1240 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1209 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE . $$36 opt_semicolon (242) + $$36 : . (241) + + . reduce 241 + + $$36 goto 1243 + + +state 1210 + interface_member_declarations : interface_member_declarations interface_member_declaration . (247) + + . reduce 247 + + +state 1211 + struct_member_declaration : type_declaration . (125) + + . reduce 125 + + +state 1212 + struct_member_declaration : field_declaration . (118) + + . reduce 118 + + +state 1213 + struct_member_declaration : method_declaration . (119) + + . reduce 119 + + +state 1214 + struct_member_declaration : constant_declaration . (117) + + . reduce 117 + + +state 1215 + struct_member_declaration : property_declaration . (120) + + . reduce 120 + + +state 1216 + struct_member_declaration : event_declaration . (121) + + . reduce 121 + + +state 1217 + struct_member_declaration : indexer_declaration . (122) + + . reduce 122 + + +state 1218 + struct_member_declaration : operator_declaration . (123) + + . reduce 123 + + +state 1219 + struct_member_declaration : constructor_declaration . (124) + + . reduce 124 + + +state 1220 + struct_member_declaration : destructor_declaration . (126) + + . reduce 126 + + +state 1221 + struct_body : OPEN_BRACE $$11 opt_struct_member_declarations . CLOSE_BRACE (112) + + CLOSE_BRACE shift 1244 + . error + + +state 1222 + opt_struct_member_declarations : struct_member_declarations . (114) + struct_member_declarations : struct_member_declarations . struct_member_declaration (116) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 114 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1211 + field_declaration goto 1212 + method_declaration goto 1213 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1214 + property_declaration goto 1215 + event_declaration goto 1216 + indexer_declaration goto 1217 + operator_declaration goto 1218 + constructor_declaration goto 1219 + destructor_declaration goto 1220 + struct_member_declaration goto 1245 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1223 + struct_member_declarations : struct_member_declaration . (115) + + . reduce 115 + + +state 1224 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon . (109) + + . reduce 109 + + +state 1225 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression . opt_join_into (884) + opt_join_into : . (889) + + INTO shift 1246 + WHERE reduce 889 + FROM reduce 889 + JOIN reduce 889 + SELECT reduce 889 + GROUP reduce 889 + LET reduce 889 + ORDERBY reduce 889 + COMPLETE_COMPLETION reduce 889 + + opt_join_into goto 1247 + + +state 1226 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 . expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1248 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1227 + type_parameter_constraint : NEW OPEN_PARENS CLOSE_PARENS . (683) + + . reduce 683 + + +state 1228 + type_parameter_constraints : type_parameter_constraints COMMA type_parameter_constraint . (681) + + . reduce 681 + + +state 1229 + constant_declaration : opt_attributes opt_modifiers CONST . type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1249 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1230 + event_declaration : opt_attributes opt_modifiers EVENT . type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT . type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1250 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1231 + conversion_operator_declarator : EXPLICIT . OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + conversion_operator_declarator : EXPLICIT . error (293) + + error shift 1251 + OPERATOR shift 1252 + . error + + +state 1232 + conversion_operator_declarator : IMPLICIT . OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + conversion_operator_declarator : IMPLICIT . error (292) + + error shift 1253 + OPERATOR shift 1254 + . error + + +state 1233 + operator_type : VOID . (262) + type_and_void : VOID . (385) + type_expression : VOID . STAR (398) + + STAR shift 464 + ABSTRACT reduce 385 + EXTERN reduce 385 + INTERNAL reduce 385 + NEW reduce 385 + OPERATOR reduce 262 + OVERRIDE reduce 385 + PRIVATE reduce 385 + PROTECTED reduce 385 + PUBLIC reduce 385 + READONLY reduce 385 + SEALED reduce 385 + STATIC reduce 385 + THIS reduce 385 + UNSAFE reduce 385 + VIRTUAL reduce 385 + VOLATILE reduce 385 + IDENTIFIER reduce 385 + + +state 1234 + destructor_declaration : opt_attributes opt_modifiers TILDE . $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + $$45 : . (307) + + . reduce 307 + + $$45 goto 1255 + + +state 1235 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER . $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + $$41 : . (295) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + ABSTRACT reduce 363 + EXTERN reduce 363 + INTERNAL reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + OPEN_PARENS reduce 295 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + $$41 goto 1256 + opt_type_argument_list goto 84 + + +state 1236 + field_declaration : opt_attributes opt_modifiers member_type . IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + method_header : opt_attributes opt_modifiers member_type . method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers member_type . modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers member_type . member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers member_type . indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + THIS shift 1257 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 470 + . error + + type_declaration_name goto 471 + method_declaration_name goto 1258 + modifiers goto 473 + member_declaration_name goto 1259 + indexer_declaration_name goto 1260 + qualified_alias_member goto 474 + explicit_interface goto 1261 + modifier goto 78 + + +state 1237 + operator_declaration : opt_attributes opt_modifiers operator_declarator . $$37 operator_body (258) + $$37 : . (257) + + . reduce 257 + + $$37 goto 1262 + + +state 1238 + operator_declarator : operator_type . OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + OPERATOR shift 1263 + . error + + +state 1239 + operator_type : type_expression_or_array . (261) + type_and_void : type_expression_or_array . (384) + + ABSTRACT reduce 384 + EXTERN reduce 384 + INTERNAL reduce 384 + NEW reduce 384 + OPERATOR reduce 261 + OVERRIDE reduce 384 + PRIVATE reduce 384 + PROTECTED reduce 384 + PUBLIC reduce 384 + READONLY reduce 384 + SEALED reduce 384 + STATIC reduce 384 + THIS reduce 384 + UNSAFE reduce 384 + VIRTUAL reduce 384 + VOLATILE reduce 384 + IDENTIFIER reduce 384 + + +state 1240 + operator_declarator : conversion_operator_declarator . (265) + + . reduce 265 + + +state 1241 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 . opt_semicolon (652) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1264 + + +state 1242 + block_prepared : OPEN_BRACE $$75 . opt_statement_list CLOSE_BRACE (695) + opt_statement_list : . (696) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 696 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + opt_statement_list goto 1265 + statement_list goto 562 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1243 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 . opt_semicolon (242) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1266 + + +state 1244 + struct_body : OPEN_BRACE $$11 opt_struct_member_declarations CLOSE_BRACE . (112) + + . reduce 112 + + +state 1245 + struct_member_declarations : struct_member_declarations struct_member_declaration . (116) + + . reduce 116 + + +state 1246 + opt_join_into : INTO . IDENTIFIER (890) + + IDENTIFIER shift 1267 + . error + + +state 1247 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into . (884) + + . reduce 884 + + +state 1248 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression . opt_join_into (888) + opt_join_into : . (889) + + INTO shift 1246 + WHERE reduce 889 + FROM reduce 889 + JOIN reduce 889 + SELECT reduce 889 + GROUP reduce 889 + LET reduce 889 + ORDERBY reduce 889 + COMPLETE_COMPLETION reduce 889 + + opt_join_into goto 1268 + + +state 1249 + constant_declaration : opt_attributes opt_modifiers CONST type . IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + + IDENTIFIER shift 1269 + . error + + +state 1250 + event_declaration : opt_attributes opt_modifiers EVENT type . member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT type . member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 1270 + member_declaration_name goto 1271 + qualified_alias_member goto 474 + explicit_interface goto 475 + + +state 1251 + conversion_operator_declarator : EXPLICIT error . (293) + + . reduce 293 + + +state 1252 + conversion_operator_declarator : EXPLICIT OPERATOR . type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1272 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1253 + conversion_operator_declarator : IMPLICIT error . (292) + + . reduce 292 + + +state 1254 + conversion_operator_declarator : IMPLICIT OPERATOR . type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1273 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1255 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 . IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + + IDENTIFIER shift 1274 + . error + + +state 1256 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 . OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + + OPEN_PARENS shift 1275 + . error + + +state 1257 + indexer_declaration_name : THIS . (373) + + . reduce 373 + + +state 1258 + method_header : opt_attributes opt_modifiers member_type method_declaration_name . OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + member_declaration_name : method_declaration_name . (370) + + OPEN_PARENS shift 674 + OPEN_BRACE reduce 370 + + +state 1259 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name . $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + $$25 : . (218) + + . reduce 218 + + $$25 goto 1276 + + +state 1260 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name . OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + OPEN_BRACKET shift 1277 + . error + + +state 1261 + method_declaration_name : explicit_interface . IDENTIFIER opt_type_parameter_list (372) + indexer_declaration_name : explicit_interface . THIS (374) + explicit_interface : explicit_interface . IDENTIFIER opt_type_argument_list DOT (377) + + THIS shift 1278 + IDENTIFIER shift 677 + . error + + +state 1262 + operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 . operator_body (258) + + OPEN_BRACE shift 143 + SEMICOLON shift 1279 + . error + + block goto 1280 + operator_body goto 1281 + + +state 1263 + operator_declarator : operator_type OPERATOR . overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + FALSE shift 1282 + TRUE shift 1283 + TILDE shift 1284 + PLUS shift 1285 + MINUS shift 1286 + BANG shift 1287 + OP_LT shift 1288 + OP_GT shift 1289 + BITWISE_AND shift 1290 + BITWISE_OR shift 1291 + STAR shift 1292 + PERCENT shift 1293 + DIV shift 1294 + CARRET shift 1295 + OP_INC shift 1296 + OP_DEC shift 1297 + OP_SHIFT_LEFT shift 1298 + OP_SHIFT_RIGHT shift 1299 + OP_LE shift 1300 + OP_GE shift 1301 + OP_EQ shift 1302 + OP_NE shift 1303 + . error + + overloadable_operator goto 1304 + + +state 1264 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon . (652) + + . reduce 652 + + +state 1265 + block_prepared : OPEN_BRACE $$75 opt_statement_list . CLOSE_BRACE (695) + + CLOSE_BRACE shift 1305 + . error + + +state 1266 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon . (242) + + . reduce 242 + + +state 1267 + opt_join_into : INTO IDENTIFIER . (890) + + . reduce 890 + + +state 1268 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into . (888) + + . reduce 888 + + +state 1269 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER . $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + $$12 : . (127) + + . reduce 127 + + $$12 goto 1306 + + +state 1270 + member_declaration_name : method_declaration_name . (370) + + . reduce 370 + + +state 1271 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name . $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name . OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + $$46 : . (309) + + OPEN_BRACE shift 1307 + COMMA reduce 309 + SEMICOLON reduce 309 + ASSIGN reduce 309 + + $$46 goto 1308 + + +state 1272 + conversion_operator_declarator : EXPLICIT OPERATOR type . OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + + OPEN_PARENS shift 1309 + . error + + +state 1273 + conversion_operator_declarator : IMPLICIT OPERATOR type . OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + + OPEN_PARENS shift 1310 + . error + + +state 1274 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER . OPEN_PARENS CLOSE_PARENS method_body (308) + + OPEN_PARENS shift 1311 + . error + + +state 1275 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS . opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1312 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1276 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 . OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + + OPEN_BRACE shift 1313 + . error + + +state 1277 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET . $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + $$28 : . (222) + + . reduce 222 + + $$28 goto 1314 + + +state 1278 + indexer_declaration_name : explicit_interface THIS . (374) + + . reduce 374 + + +state 1279 + operator_body : SEMICOLON . (260) + + . reduce 260 + + +state 1280 + operator_body : block . (259) + + . reduce 259 + + +state 1281 + operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 operator_body . (258) + + . reduce 258 + + +state 1282 + overloadable_operator : FALSE . (271) + + . reduce 271 + + +state 1283 + overloadable_operator : TRUE . (270) + + . reduce 270 + + +state 1284 + overloadable_operator : TILDE . (267) + + . reduce 267 + + +state 1285 + overloadable_operator : PLUS . (272) + + . reduce 272 + + +state 1286 + overloadable_operator : MINUS . (273) + + . reduce 273 + + +state 1287 + overloadable_operator : BANG . (266) + + . reduce 266 + + +state 1288 + overloadable_operator : OP_LT . (285) + + . reduce 285 + + +state 1289 + overloadable_operator : OP_GT . (284) + + . reduce 284 + + +state 1290 + overloadable_operator : BITWISE_AND . (277) + + . reduce 277 + + +state 1291 + overloadable_operator : BITWISE_OR . (278) + + . reduce 278 + + +state 1292 + overloadable_operator : STAR . (274) + + . reduce 274 + + +state 1293 + overloadable_operator : PERCENT . (276) + + . reduce 276 + + +state 1294 + overloadable_operator : DIV . (275) + + . reduce 275 + + +state 1295 + overloadable_operator : CARRET . (279) + + . reduce 279 + + +state 1296 + overloadable_operator : OP_INC . (268) + + . reduce 268 + + +state 1297 + overloadable_operator : OP_DEC . (269) + + . reduce 269 + + +state 1298 + overloadable_operator : OP_SHIFT_LEFT . (280) + + . reduce 280 + + +state 1299 + overloadable_operator : OP_SHIFT_RIGHT . (281) + + . reduce 281 + + +state 1300 + overloadable_operator : OP_LE . (287) + + . reduce 287 + + +state 1301 + overloadable_operator : OP_GE . (286) + + . reduce 286 + + +state 1302 + overloadable_operator : OP_EQ . (282) + + . reduce 282 + + +state 1303 + overloadable_operator : OP_NE . (283) + + . reduce 283 + + +state 1304 + operator_declarator : operator_type OPERATOR overloadable_operator . OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + OPEN_PARENS shift 1315 + . error + + +state 1305 + block_prepared : OPEN_BRACE $$75 opt_statement_list CLOSE_BRACE . (695) + + . reduce 695 + + +state 1306 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 . constant_initializer opt_constant_declarators SEMICOLON (128) + + error shift 1316 + ASSIGN shift 1317 + . error + + constant_initializer goto 1318 + + +state 1307 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE . $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + $$47 : . (311) + + . reduce 311 + + $$47 goto 1319 + + +state 1308 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 . opt_event_initializer opt_event_declarators SEMICOLON (310) + opt_event_initializer : . (314) + + ASSIGN shift 1320 + COMMA reduce 314 + SEMICOLON reduce 314 + + opt_event_initializer goto 1321 + + +state 1309 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS . $$40 opt_formal_parameter_list CLOSE_PARENS (291) + $$40 : . (290) + + . reduce 290 + + $$40 goto 1322 + + +state 1310 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS . $$39 opt_formal_parameter_list CLOSE_PARENS (289) + $$39 : . (288) + + . reduce 288 + + $$39 goto 1323 + + +state 1311 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS . CLOSE_PARENS method_body (308) + + CLOSE_PARENS shift 1324 + . error + + +state 1312 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list . CLOSE_PARENS $$42 opt_constructor_initializer (297) + + CLOSE_PARENS shift 1325 + . error + + +state 1313 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE . $$26 accessor_declarations $$27 CLOSE_BRACE (221) + $$26 : . (219) + + . reduce 219 + + $$26 goto 1326 + + +state 1314 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 . opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_BRACKET reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1327 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1315 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS . $$38 opt_formal_parameter_list CLOSE_PARENS (264) + $$38 : . (263) + + . reduce 263 + + $$38 goto 1328 + + +state 1316 + constant_initializer : error . (136) + + . reduce 136 + + +state 1317 + constant_initializer : ASSIGN . $$13 constant_initializer_expr (135) + $$13 : . (134) + + . reduce 134 + + $$13 goto 1329 + + +state 1318 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer . opt_constant_declarators SEMICOLON (128) + opt_constant_declarators : . (129) + + COMMA shift 1330 + SEMICOLON reduce 129 + + opt_constant_declarators goto 1331 + constant_declarators goto 1332 + constant_declarator goto 1333 + + +state 1319 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 . event_accessor_declarations $$48 CLOSE_BRACE (313) + opt_attributes : . (59) + + error shift 1334 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + ADD reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + REMOVE reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + + opt_attributes goto 1335 + attribute_sections goto 693 + attribute_section goto 30 + event_accessor_declarations goto 1336 + add_accessor_declaration goto 1337 + remove_accessor_declaration goto 1338 + + +state 1320 + opt_event_initializer : ASSIGN . $$49 event_variable_initializer (316) + $$49 : . (315) + + . reduce 315 + + $$49 goto 1339 + + +state 1321 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer . opt_event_declarators SEMICOLON (310) + opt_event_declarators : . (317) + + COMMA shift 1340 + SEMICOLON reduce 317 + + opt_event_declarators goto 1341 + event_declarators goto 1342 + event_declarator goto 1343 + + +state 1322 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 . opt_formal_parameter_list CLOSE_PARENS (291) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1344 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1323 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 . opt_formal_parameter_list CLOSE_PARENS (289) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1345 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1324 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS . method_body (308) + + OPEN_BRACE shift 143 + SEMICOLON shift 263 + . error + + method_body goto 1346 + block goto 265 + + +state 1325 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS . $$42 opt_constructor_initializer (297) + $$42 : . (296) + + . reduce 296 + + $$42 goto 1347 + + +state 1326 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 . accessor_declarations $$27 CLOSE_BRACE (221) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1350 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1327 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list . CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + CLOSE_BRACKET shift 1353 + . error + + +state 1328 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 . opt_formal_parameter_list CLOSE_PARENS (264) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1354 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1329 + constant_initializer : ASSIGN $$13 . constant_initializer_expr (135) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_initializer_expr goto 1355 + constant_expression goto 840 + array_initializer goto 841 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1330 + constant_declarator : COMMA . IDENTIFIER constant_initializer (133) + + IDENTIFIER shift 1356 + . error + + +state 1331 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators . SEMICOLON (128) + + SEMICOLON shift 1357 + . error + + +state 1332 + opt_constant_declarators : constant_declarators . (130) + constant_declarators : constant_declarators . constant_declarator (132) + + COMMA shift 1330 + SEMICOLON reduce 130 + + constant_declarator goto 1358 + + +state 1333 + constant_declarators : constant_declarator . (131) + + . reduce 131 + + +state 1334 + event_accessor_declarations : error . (330) + + . reduce 330 + + +state 1335 + add_accessor_declaration : opt_attributes . opt_modifiers ADD $$52 event_accessor_block (332) + remove_accessor_declaration : opt_attributes . opt_modifiers REMOVE $$53 event_accessor_block (334) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 655 + REMOVE reduce 655 + + opt_modifiers goto 1359 + modifiers goto 77 + modifier goto 78 + + +state 1336 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations . $$48 CLOSE_BRACE (313) + $$48 : . (312) + + . reduce 312 + + $$48 goto 1360 + + +state 1337 + event_accessor_declarations : add_accessor_declaration . remove_accessor_declaration (326) + event_accessor_declarations : add_accessor_declaration . (328) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + REMOVE reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + CLOSE_BRACE reduce 328 + + opt_attributes goto 1361 + attribute_sections goto 693 + attribute_section goto 30 + remove_accessor_declaration goto 1362 + + +state 1338 + event_accessor_declarations : remove_accessor_declaration . add_accessor_declaration (327) + event_accessor_declarations : remove_accessor_declaration . (329) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + ADD reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + CLOSE_BRACE reduce 329 + + opt_attributes goto 1363 + attribute_sections goto 693 + attribute_section goto 30 + add_accessor_declaration goto 1364 + + +state 1339 + opt_event_initializer : ASSIGN $$49 . event_variable_initializer (316) + $$51 : . (324) + + . reduce 324 + + event_variable_initializer goto 1365 + $$51 goto 1366 + + +state 1340 + event_declarator : COMMA . IDENTIFIER (321) + event_declarator : COMMA . IDENTIFIER ASSIGN $$50 event_variable_initializer (323) + + IDENTIFIER shift 1367 + . error + + +state 1341 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators . SEMICOLON (310) + + SEMICOLON shift 1368 + . error + + +state 1342 + opt_event_declarators : event_declarators . (318) + event_declarators : event_declarators . event_declarator (320) + + COMMA shift 1340 + SEMICOLON reduce 318 + + event_declarator goto 1369 + + +state 1343 + event_declarators : event_declarator . (319) + + . reduce 319 + + +state 1344 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list . CLOSE_PARENS (291) + + CLOSE_PARENS shift 1370 + . error + + +state 1345 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list . CLOSE_PARENS (289) + + CLOSE_PARENS shift 1371 + . error + + +state 1346 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body . (308) + + . reduce 308 + + +state 1347 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 . opt_constructor_initializer (297) + opt_constructor_initializer : . (300) + + COLON shift 1372 + OPEN_BRACE reduce 300 + SEMICOLON reduce 300 + + opt_constructor_initializer goto 1373 + constructor_initializer goto 1374 + + +state 1348 + accessor_declarations : error . (230) + + . reduce 230 + + +state 1349 + get_accessor_declaration : opt_attributes . opt_modifiers GET $$31 accessor_body (232) + set_accessor_declaration : opt_attributes . opt_modifiers SET $$32 accessor_body (234) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + GET reduce 655 + SET reduce 655 + + opt_modifiers goto 1375 + modifiers goto 77 + modifier goto 78 + + +state 1350 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations . $$27 CLOSE_BRACE (221) + $$27 : . (220) + + . reduce 220 + + $$27 goto 1376 + + +state 1351 + accessor_declarations : get_accessor_declaration . (226) + accessor_declarations : get_accessor_declaration . accessor_declarations (227) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + CLOSE_BRACE reduce 226 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1377 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1352 + accessor_declarations : set_accessor_declaration . (228) + accessor_declarations : set_accessor_declaration . accessor_declarations (229) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + CLOSE_BRACE reduce 228 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1378 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1353 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET . OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + OPEN_BRACE shift 1379 + . error + + +state 1354 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list . CLOSE_PARENS (264) + + CLOSE_PARENS shift 1380 + . error + + +state 1355 + constant_initializer : ASSIGN $$13 constant_initializer_expr . (135) + + . reduce 135 + + +state 1356 + constant_declarator : COMMA IDENTIFIER . constant_initializer (133) + + error shift 1316 + ASSIGN shift 1317 + . error + + constant_initializer goto 1381 + + +state 1357 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON . (128) + + . reduce 128 + + +state 1358 + constant_declarators : constant_declarators constant_declarator . (132) + + . reduce 132 + + +state 1359 + add_accessor_declaration : opt_attributes opt_modifiers . ADD $$52 event_accessor_block (332) + remove_accessor_declaration : opt_attributes opt_modifiers . REMOVE $$53 event_accessor_block (334) + + ADD shift 1382 + REMOVE shift 1383 + . error + + +state 1360 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 . CLOSE_BRACE (313) + + CLOSE_BRACE shift 1384 + . error + + +state 1361 + remove_accessor_declaration : opt_attributes . opt_modifiers REMOVE $$53 event_accessor_block (334) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + REMOVE reduce 655 + + opt_modifiers goto 1385 + modifiers goto 77 + modifier goto 78 + + +state 1362 + event_accessor_declarations : add_accessor_declaration remove_accessor_declaration . (326) + + . reduce 326 + + +state 1363 + add_accessor_declaration : opt_attributes . opt_modifiers ADD $$52 event_accessor_block (332) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 655 + + opt_modifiers goto 1386 + modifiers goto 77 + modifier goto 78 + + +state 1364 + event_accessor_declarations : remove_accessor_declaration add_accessor_declaration . (327) + + . reduce 327 + + +state 1365 + opt_event_initializer : ASSIGN $$49 event_variable_initializer . (316) + + . reduce 316 + + +state 1366 + event_variable_initializer : $$51 . variable_initializer (325) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1387 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1367 + event_declarator : COMMA IDENTIFIER . (321) + event_declarator : COMMA IDENTIFIER . ASSIGN $$50 event_variable_initializer (323) + + ASSIGN shift 1388 + COMMA reduce 321 + SEMICOLON reduce 321 + + +state 1368 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON . (310) + + . reduce 310 + + +state 1369 + event_declarators : event_declarators event_declarator . (320) + + . reduce 320 + + +state 1370 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS . (291) + + . reduce 291 + + +state 1371 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS . (289) + + . reduce 289 + + +state 1372 + constructor_initializer : COLON . BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS (303) + constructor_initializer : COLON . THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS (305) + constructor_initializer : COLON . error (306) + + error shift 1389 + BASE shift 1390 + THIS shift 1391 + . error + + +state 1373 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer . (297) + + . reduce 297 + + +state 1374 + opt_constructor_initializer : constructor_initializer . (301) + + . reduce 301 + + +state 1375 + get_accessor_declaration : opt_attributes opt_modifiers . GET $$31 accessor_body (232) + set_accessor_declaration : opt_attributes opt_modifiers . SET $$32 accessor_body (234) + + GET shift 1392 + SET shift 1393 + . error + + +state 1376 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 . CLOSE_BRACE (221) + + CLOSE_BRACE shift 1394 + . error + + +state 1377 + accessor_declarations : get_accessor_declaration accessor_declarations . (227) + + . reduce 227 + + +state 1378 + accessor_declarations : set_accessor_declaration accessor_declarations . (229) + + . reduce 229 + + +state 1379 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE . $$29 accessor_declarations $$30 CLOSE_BRACE (225) + $$29 : . (223) + + . reduce 223 + + $$29 goto 1395 + + +state 1380 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS . (264) + + . reduce 264 + + +state 1381 + constant_declarator : COMMA IDENTIFIER constant_initializer . (133) + + . reduce 133 + + +state 1382 + add_accessor_declaration : opt_attributes opt_modifiers ADD . $$52 event_accessor_block (332) + $$52 : . (331) + + . reduce 331 + + $$52 goto 1396 + + +state 1383 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE . $$53 event_accessor_block (334) + $$53 : . (333) + + . reduce 333 + + $$53 goto 1397 + + +state 1384 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE . (313) + + . reduce 313 + + +state 1385 + remove_accessor_declaration : opt_attributes opt_modifiers . REMOVE $$53 event_accessor_block (334) + + REMOVE shift 1383 + . error + + +state 1386 + add_accessor_declaration : opt_attributes opt_modifiers . ADD $$52 event_accessor_block (332) + + ADD shift 1382 + . error + + +state 1387 + event_variable_initializer : $$51 variable_initializer . (325) + + . reduce 325 + + +state 1388 + event_declarator : COMMA IDENTIFIER ASSIGN . $$50 event_variable_initializer (323) + $$50 : . (322) + + . reduce 322 + + $$50 goto 1398 + + +state 1389 + constructor_initializer : COLON error . (306) + + . reduce 306 + + +state 1390 + constructor_initializer : COLON BASE . OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS (303) + + OPEN_PARENS shift 1399 + . error + + +state 1391 + constructor_initializer : COLON THIS . OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS (305) + + OPEN_PARENS shift 1400 + . error + + +state 1392 + get_accessor_declaration : opt_attributes opt_modifiers GET . $$31 accessor_body (232) + $$31 : . (231) + + . reduce 231 + + $$31 goto 1401 + + +state 1393 + set_accessor_declaration : opt_attributes opt_modifiers SET . $$32 accessor_body (234) + $$32 : . (233) + + . reduce 233 + + $$32 goto 1402 + + +state 1394 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE . (221) + + . reduce 221 + + +state 1395 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 . accessor_declarations $$30 CLOSE_BRACE (225) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1403 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1396 + add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 . event_accessor_block (332) + opt_semicolon : . (30) + + OPEN_BRACE shift 143 + SEMICOLON shift 810 + ABSTRACT reduce 30 + EXTERN reduce 30 + INTERNAL reduce 30 + NEW reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + REMOVE reduce 30 + SEALED reduce 30 + STATIC reduce 30 + UNSAFE reduce 30 + VIRTUAL reduce 30 + VOLATILE reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + + opt_semicolon goto 1404 + block goto 1405 + event_accessor_block goto 1406 + + +state 1397 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 . event_accessor_block (334) + opt_semicolon : . (30) + + OPEN_BRACE shift 143 + SEMICOLON shift 810 + ABSTRACT reduce 30 + ADD reduce 30 + EXTERN reduce 30 + INTERNAL reduce 30 + NEW reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SEALED reduce 30 + STATIC reduce 30 + UNSAFE reduce 30 + VIRTUAL reduce 30 + VOLATILE reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + + opt_semicolon goto 1404 + block goto 1405 + event_accessor_block goto 1407 + + +state 1398 + event_declarator : COMMA IDENTIFIER ASSIGN $$50 . event_variable_initializer (323) + $$51 : . (324) + + . reduce 324 + + event_variable_initializer goto 1408 + $$51 goto 1366 + + +state 1399 + constructor_initializer : COLON BASE OPEN_PARENS . $$43 opt_argument_list CLOSE_PARENS (303) + $$43 : . (302) + + . reduce 302 + + $$43 goto 1409 + + +state 1400 + constructor_initializer : COLON THIS OPEN_PARENS . $$44 opt_argument_list CLOSE_PARENS (305) + $$44 : . (304) + + . reduce 304 + + $$44 goto 1410 + + +state 1401 + get_accessor_declaration : opt_attributes opt_modifiers GET $$31 . accessor_body (232) + + error shift 1411 + OPEN_BRACE shift 143 + SEMICOLON shift 1412 + . error + + block goto 1413 + accessor_body goto 1414 + + +state 1402 + set_accessor_declaration : opt_attributes opt_modifiers SET $$32 . accessor_body (234) + + error shift 1411 + OPEN_BRACE shift 143 + SEMICOLON shift 1412 + . error + + block goto 1413 + accessor_body goto 1415 + + +state 1403 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations . $$30 CLOSE_BRACE (225) + $$30 : . (224) + + . reduce 224 + + $$30 goto 1416 + + +state 1404 + event_accessor_block : opt_semicolon . (335) + + . reduce 335 + + +state 1405 + event_accessor_block : block . (336) + + . reduce 336 + + +state 1406 + add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 event_accessor_block . (332) + + . reduce 332 + + +state 1407 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 event_accessor_block . (334) + + . reduce 334 + + +state 1408 + event_declarator : COMMA IDENTIFIER ASSIGN $$50 event_variable_initializer . (323) + + . reduce 323 + + +state 1409 + constructor_initializer : COLON BASE OPEN_PARENS $$43 . opt_argument_list CLOSE_PARENS (303) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 1417 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1410 + constructor_initializer : COLON THIS OPEN_PARENS $$44 . opt_argument_list CLOSE_PARENS (305) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 1418 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1411 + accessor_body : error . (237) + + . reduce 237 + + +state 1412 + accessor_body : SEMICOLON . (236) + + . reduce 236 + + +state 1413 + accessor_body : block . (235) + + . reduce 235 + + +state 1414 + get_accessor_declaration : opt_attributes opt_modifiers GET $$31 accessor_body . (232) + + . reduce 232 + + +state 1415 + set_accessor_declaration : opt_attributes opt_modifiers SET $$32 accessor_body . (234) + + . reduce 234 + + +state 1416 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 . CLOSE_BRACE (225) + + CLOSE_BRACE shift 1419 + . error + + +state 1417 + constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list . CLOSE_PARENS (303) + + CLOSE_PARENS shift 1420 + . error + + +state 1418 + constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list . CLOSE_PARENS (305) + + CLOSE_PARENS shift 1421 + . error + + +state 1419 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE . (225) + + . reduce 225 + + +state 1420 + constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS . (303) + + . reduce 303 + + +state 1421 + constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS . (305) + + . reduce 305 + + +State 164 contains 1 shift/reduce conflict. +State 167 contains 1 shift/reduce conflict. +State 239 contains 1 shift/reduce conflict. +State 240 contains 1 shift/reduce conflict. +State 484 contains 1 shift/reduce conflict. +State 654 contains 1 shift/reduce conflict. +State 729 contains 1 shift/reduce conflict. +State 730 contains 1 shift/reduce conflict. +State 860 contains 1 shift/reduce conflict. + + +170 terminals, 432 nonterminals +922 grammar rules, 1422 states diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs new file mode 100644 index 0000000000..4a99ef1625 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs @@ -0,0 +1,55 @@ +// +// Change.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// This is the base class for all refactoring operations that are performed. + /// + public abstract class Action + { + /// + /// Gets or sets the description. + /// + /// + /// A brief description of the refactoring change. + /// + public string Description { + get; + set; + } + + /// + /// Performs the change. + /// + /// + /// The context on which the change should perform on. + /// + public abstract void Perform (Script script); + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs new file mode 100644 index 0000000000..f934917d9a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs @@ -0,0 +1,89 @@ +// +// AddAnotherAccessor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Add another accessor to a property declaration that has only one. + /// + public class AddAnotherAccessor : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pdecl = GetPropertyDeclaration (context); + if (pdecl == null) + return false; + var type = pdecl.Parent as TypeDeclaration; + if (type != null && type.ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + return false; + + return pdecl.Setter.IsNull || pdecl.Getter.IsNull; + } + + public void Run (RefactoringContext context) + { + var pdecl = GetPropertyDeclaration (context); + var accessorStatement = BuildAccessorStatement (context, pdecl); + + Accessor accessor = new Accessor () { + Body = new BlockStatement { accessorStatement } + }; + + pdecl.AddChild (accessor, pdecl.Setter.IsNull ? PropertyDeclaration.SetterRole : PropertyDeclaration.GetterRole); + + using (var script = context.StartScript ()) { + script.InsertBefore (pdecl.RBraceToken, accessor); + script.Select (accessorStatement); + script.FormatText (ctx => GetPropertyDeclaration (context)); + } + } + + static Statement BuildAccessorStatement (RefactoringContext context, PropertyDeclaration pdecl) + { + if (pdecl.Setter.IsNull && !pdecl.Getter.IsNull) { + var field = RemoveBackingStore.ScanGetter (context, pdecl); + if (field != null) + return new ExpressionStatement (new AssignmentExpression (new IdentifierExpression (field.Name), AssignmentOperatorType.Assign, new IdentifierExpression ("value"))); + } + + if (!pdecl.Setter.IsNull && pdecl.Getter.IsNull) { + var field = RemoveBackingStore.ScanSetter (context, pdecl); + if (field != null) + return new ReturnStatement (new IdentifierExpression (field.Name)); + } + + return new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "NotImplementedException"))); + } + + static PropertyDeclaration GetPropertyDeclaration (RefactoringContext context) + { + var node = context.GetNode (); + if (node == null) + return null; + return node.Parent as PropertyDeclaration; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs new file mode 100644 index 0000000000..3c52562aa6 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs @@ -0,0 +1,112 @@ +// +// CheckIfParameterIsNull.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Creates a 'if (param == null) throw new System.ArgumentNullException ();' contruct for a parameter. + /// + public class CheckIfParameterIsNull : IContextAction + { + //TODO: Create 'multiple' null checks when more than 1 parameter is selected. + public bool IsValid (RefactoringContext context) + { + var parameter = GetParameterDeclaration (context); + if (parameter == null) + return false; + + var bodyStatement = parameter.Parent.GetChildByRole (AstNode.Roles.Body); + + if (bodyStatement == null) + return false; + + if (parameter.Type is PrimitiveType) + return (((PrimitiveType)parameter.Type).Keyword == "object" || ((PrimitiveType)parameter.Type).Keyword == "string") && !HasNullCheck (parameter); + + // TODO: check for structs + return !HasNullCheck (parameter); + } + + public void Run (RefactoringContext context) + { + var parameter = GetParameterDeclaration (context); + + var bodyStatement = parameter.Parent.GetChildByRole (AstNode.Roles.Body); + + var statement = new IfElseStatement () { + Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()), + TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name))) + }; + + using (var script = context.StartScript ()) { + script.AddTo (bodyStatement, statement); + } + } + + static ParameterDeclaration GetParameterDeclaration (RefactoringContext context) + { + return context.GetNode (); + } + + static bool HasNullCheck (ParameterDeclaration parameter) + { + var visitor = new CheckNullVisitor (parameter); + parameter.Parent.AcceptVisitor (visitor, null); + return visitor.ContainsNullCheck; + } + + class CheckNullVisitor : DepthFirstAstVisitor + { + ParameterDeclaration parameter; + + public bool ContainsNullCheck { + get; + set; + } + + public CheckNullVisitor (ParameterDeclaration parameter) + { + this.parameter = parameter; + } + + public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + { + if (ifElseStatement.Condition is BinaryOperatorExpression) { + var binOp = ifElseStatement.Condition as BinaryOperatorExpression; + if ((binOp.Operator == BinaryOperatorType.Equality || binOp.Operator == BinaryOperatorType.InEquality) && + binOp.Left.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Right.IsMatch (new NullReferenceExpression ()) || + binOp.Right.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Left.IsMatch (new NullReferenceExpression ())) { + ContainsNullCheck = true; + } + } + + return base.VisitIfElseStatement (ifElseStatement, data); + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs new file mode 100644 index 0000000000..c1ec0fa06f --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs @@ -0,0 +1,52 @@ +// +// ConvertDecToHex.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Convert a dec numer to hex. For example: 16 -> 0x10 + /// + public class ConvertDecToHex : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pexpr = context.GetNode (); + if (pexpr == null || pexpr.LiteralValue.StartsWith ("0X", System.StringComparison.OrdinalIgnoreCase)) + return false; + return (pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) || + (pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte); + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + + using (var script = context.StartScript ()) { + script.Replace (pexpr, new PrimitiveExpression (pexpr.Value, string.Format ("0x{0:x}", pexpr.Value))); + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs new file mode 100644 index 0000000000..b3f38e7cbc --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs @@ -0,0 +1,95 @@ +// +// ConvertForeachToFor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Converts a foreach loop to for. + /// + public class ConvertForeachToFor : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetForeachStatement (context) != null; + } + + static string GetCountProperty (IType type) + { +// if (!type.) +// return "Length"; + return "Count"; + } + + public void Run (RefactoringContext context) + { + var foreachStatement = GetForeachStatement (context); + + var result = context.Resolve (foreachStatement.InExpression); + var countProperty = GetCountProperty (result.Type); + + var initializer = new VariableDeclarationStatement (new PrimitiveType ("int"), "i", new PrimitiveExpression (0)); + var id1 = new IdentifierExpression ("i"); + var id2 = id1.Clone (); + var id3 = id1.Clone (); + + var forStatement = new ForStatement () { + Initializers = { initializer }, + Condition = new BinaryOperatorExpression (id1, BinaryOperatorType.LessThan, new MemberReferenceExpression (foreachStatement.InExpression.Clone (), countProperty)), + Iterators = { new ExpressionStatement (new UnaryOperatorExpression (UnaryOperatorType.PostIncrement, id2)) }, + EmbeddedStatement = new BlockStatement { + new VariableDeclarationStatement (foreachStatement.VariableType.Clone (), foreachStatement.VariableName, new IndexerExpression (foreachStatement.InExpression.Clone (), id3)) + } + }; + + if (foreachStatement.EmbeddedStatement is BlockStatement) { + foreach (var child in ((BlockStatement)foreachStatement.EmbeddedStatement).Statements) { + forStatement.EmbeddedStatement.AddChild (child.Clone (), BlockStatement.StatementRole); + } + } else { + forStatement.EmbeddedStatement.AddChild (foreachStatement.EmbeddedStatement.Clone (), BlockStatement.StatementRole); + } + + using (var script = context.StartScript ()) { + script.Replace (foreachStatement, forStatement); + script.Link (initializer.Variables.First ().NameToken, id1, id2, id3); + } + } + + static ForeachStatement GetForeachStatement (RefactoringContext context) + { + var astNode = context.GetNode (); + if (astNode == null) + return null; + var result = (astNode as ForeachStatement) ?? astNode.Parent as ForeachStatement; + if (result == null || context.Resolve (result.InExpression) == null) + return null; + return result; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs new file mode 100644 index 0000000000..3c653c1c12 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs @@ -0,0 +1,52 @@ +// +// ConvertHexToDec.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Convert a hex numer to dec. For example: 0x10 -> 16 + /// + public class ConvertHexToDec: IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pexpr = context.GetNode (); + if (pexpr == null || !pexpr.LiteralValue.StartsWith ("0X", System.StringComparison.OrdinalIgnoreCase)) + return false; + return (pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) || + (pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte); + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + + using (var script = context.StartScript ()) { + script.Replace (pexpr, new PrimitiveExpression (pexpr.Value)); + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs new file mode 100644 index 0000000000..db6598a877 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs @@ -0,0 +1,73 @@ +// +// CreateBackingStore.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateBackingStore : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var propertyDeclaration = context.GetNode (); + return propertyDeclaration != null && + !propertyDeclaration.Getter.IsNull && !propertyDeclaration.Setter.IsNull && // automatic properties always need getter & setter + propertyDeclaration.Getter.Body.IsNull && + propertyDeclaration.Setter.Body.IsNull; + } + + public void Run (RefactoringContext context) + { + var property = context.GetNode (); + + string backingStoreName = context.GetNameProposal (property.Name); + + // create field + var backingStore = new FieldDeclaration (); + backingStore.ReturnType = property.ReturnType.Clone (); + + var initializer = new VariableInitializer (backingStoreName); + backingStore.Variables.Add (initializer); + + // create new property & implement the get/set bodies + var newProperty = (PropertyDeclaration)property.Clone (); + var id1 = new IdentifierExpression (backingStoreName); + var id2 = new IdentifierExpression (backingStoreName); + newProperty.Getter.Body = new BlockStatement () { + new ReturnStatement (id1) + }; + newProperty.Setter.Body = new BlockStatement () { + new ExpressionStatement (new AssignmentExpression (id2, AssignmentOperatorType.Assign, new IdentifierExpression ("value"))) + }; + + using (var script = context.StartScript ()) { + script.Replace (property, newProperty); + script.InsertBefore (property, backingStore); + script.Link (initializer, id1, id2); + } + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs new file mode 100644 index 0000000000..e8473bdd9b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs @@ -0,0 +1,109 @@ +// +// CreateEventInvocator.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateEventInvocator : IContextAction + { + public bool IsValid (RefactoringContext context) + { + VariableInitializer initializer; + var eventDeclaration = GetEventDeclaration (context, out initializer); + if (eventDeclaration == null) + return false; + var type = (TypeDeclaration)eventDeclaration.Parent; + return !type.Members.Any (m => m is MethodDeclaration && ((MethodDeclaration)m).Name == "On" + initializer.Name); + } + + public void Run (RefactoringContext context) + { + VariableInitializer initializer; + var eventDeclaration = GetEventDeclaration (context, out initializer); + var type = context.Resolve (eventDeclaration.ReturnType).Type; + if (type == null) + return; + var invokeMethod = type.GetDelegateInvokeMethod (); + if (invokeMethod == null) + return; + + bool hasSenderParam = false; + IEnumerable pars = invokeMethod.Parameters; + if (invokeMethod.Parameters.Any ()) { + var first = invokeMethod.Parameters [0]; + if (first.Name == "sender" /*&& first.Type == "System.Object"*/) { + hasSenderParam = true; + pars = invokeMethod.Parameters.Skip (1); + } + } + const string handlerName = "handler"; + + var arguments = new List (); + if (hasSenderParam) + arguments.Add (new ThisReferenceExpression ()); + foreach (var par in pars) + arguments.Add (new IdentifierExpression (par.Name)); + + var methodDeclaration = new MethodDeclaration () { + Name = "On" + initializer.Name, + ReturnType = new PrimitiveType ("void"), + Modifiers = ICSharpCode.NRefactory.CSharp.Modifiers.Protected | ICSharpCode.NRefactory.CSharp.Modifiers.Virtual, + Body = new BlockStatement () { + new VariableDeclarationStatement (context.CreateShortType (eventDeclaration.ReturnType), handlerName, new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)), + new IfElseStatement () { + Condition = new BinaryOperatorExpression (new IdentifierExpression (handlerName), BinaryOperatorType.InEquality, new PrimitiveExpression (null)), + TrueStatement = new ExpressionStatement (new InvocationExpression (new IdentifierExpression (handlerName), arguments)) + } + } + }; + + foreach (var par in pars) { + var typeName = context.CreateShortType (par.Type.Resolve (context.TypeResolveContext)); + var decl = new ParameterDeclaration (typeName, par.Name); + methodDeclaration.Parameters.Add (decl); + } + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create event invocator", methodDeclaration, Script.InsertPosition.After); + } + } + + static EventDeclaration GetEventDeclaration (RefactoringContext context, out VariableInitializer initializer) + { + var result = context.GetNode (); + if (result == null) { + initializer = null; + return null; + } + initializer = result.Variables.First (v => v.NameToken.Contains (context.Location)); + return initializer != null ? result : null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs new file mode 100644 index 0000000000..831dfe121e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs @@ -0,0 +1,77 @@ +// +// CreateField.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.PatternMatching; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateField : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var identifier = GetIdentifier (context); + if (identifier == null) + return false; + return context.Resolve (identifier) == null && GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var identifier = GetIdentifier (context); + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create field", GenerateFieldDeclaration (context, identifier), Script.InsertPosition.Before); + } + } + + static AstNode GenerateFieldDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new FieldDeclaration () { + ReturnType = GuessType (context, identifier), + Variables = { new VariableInitializer (identifier.Identifier) } + }; + } + + internal static AstType GuessType (RefactoringContext context, IdentifierExpression identifier) + { + if (identifier.Parent is AssignmentExpression) { + var assign = (AssignmentExpression)identifier.Parent; + var other = assign.Left == identifier ? assign.Right : assign.Left; + return context.Resolve (other).Type.ConvertToAstType (); + } + return null; + } + + public static IdentifierExpression GetIdentifier (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs new file mode 100644 index 0000000000..f5927a2d89 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs @@ -0,0 +1,129 @@ +// +// CreateLocalVariable.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.PatternMatching; +using System.Linq; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateLocalVariable : IContextAction + { + public List GetUnresolvedArguments (RefactoringContext context) + { + var expressions = new List (); + + var invocation = GetInvocation (context); + if (invocation != null) { + foreach (var arg in invocation.Arguments) { + IdentifierExpression identifier; + if (arg is DirectionExpression) { + identifier = ((DirectionExpression)arg).Expression as IdentifierExpression; + } else if (arg is NamedArgumentExpression) { + identifier = ((NamedArgumentExpression)arg).Expression as IdentifierExpression; + } else { + identifier = arg as IdentifierExpression; + } + if (identifier == null) + continue; + + if (context.Resolve (identifier) == null && GuessType (context, identifier) != null) + expressions.Insert (0, identifier); + } + } + return expressions; + } + + public bool IsValid (RefactoringContext context) + { + if (GetUnresolvedArguments (context).Count > 0) + return true; + var identifier = CreateField.GetIdentifier (context); + if (identifier == null) + return false; + if (context.GetNode () == null) + return false; + return context.Resolve (identifier) == null && GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var stmt = context.GetNode (); + var unresolvedArguments = GetUnresolvedArguments (context); + if (unresolvedArguments.Count > 0) { + using (var script = context.StartScript ()) { + foreach (var id in unresolvedArguments) { + script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, id)); + } + } + return; + } + + using (var script = context.StartScript ()) { + script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, CreateField.GetIdentifier (context))); + } + } + + AstNode GenerateLocalVariableDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new VariableDeclarationStatement () { + Type = GuessType (context, identifier), + Variables = { new VariableInitializer (identifier.Identifier) } + }; + } + + InvocationExpression GetInvocation (RefactoringContext context) + { + return context.GetNode (); + } + + AstType GuessType (RefactoringContext context, IdentifierExpression identifier) + { + var type = CreateField.GuessType (context, identifier); + if (type != null) + return type; + + if (identifier != null && (identifier.Parent is InvocationExpression || identifier.Parent.Parent is InvocationExpression)) { + var invocation = (identifier.Parent as InvocationExpression) ?? (identifier.Parent.Parent as InvocationExpression); + var result = context.Resolve (invocation).Type.GetDelegateInvokeMethod (); + if (result == null) + return null; + int i = 0; + foreach (var arg in invocation.Arguments) { + if (arg.Contains (identifier.StartLocation)) + break; + i++; + } + if (result.Parameters.Count < i) + return null; + return context.CreateShortType (result.Parameters[i].Type.Resolve (context.TypeResolveContext)); + } + return null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs new file mode 100644 index 0000000000..5dfd3d3599 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs @@ -0,0 +1,66 @@ +// +// CreateProperty.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.PatternMatching; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateProperty : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var identifier = CreateField.GetIdentifier (context); + if (identifier == null) + return false; + return context.Resolve (identifier) == null && CreateField.GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var identifier = GetIdentifier (context); + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create property", GeneratePropertyDeclaration (context, identifier), Script.InsertPosition.Before); + } + } + + AstNode GeneratePropertyDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new PropertyDeclaration () { + ReturnType = CreateField.GuessType (context, identifier), + Name = identifier.Identifier, + Getter = new Accessor (), + Setter = new Accessor () + }; + } + + IdentifierExpression GetIdentifier (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs new file mode 100644 index 0000000000..9a11da7b07 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs @@ -0,0 +1,59 @@ +// +// FlipOperatorArguments.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class FlipOperatorArguments : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBinaryOperatorExpression (context) != null; + } + + public void Run (RefactoringContext context) + { + var binop = GetBinaryOperatorExpression (context); + + using (var script = context.StartScript ()) { + script.Replace (binop.Left, binop.Right); + script.Replace (binop.Right, binop.Left); + } + } + + public static BinaryOperatorExpression GetBinaryOperatorExpression (RefactoringContext context) + { + var node = context.GetNode (); + + if (node == null || !node.OperatorToken.Contains (context.Location)) + return null; + var result = node as BinaryOperatorExpression; + if (result == null || (result.Operator != BinaryOperatorType.Equality && result.Operator != BinaryOperatorType.InEquality)) + return null; + return result; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs new file mode 100644 index 0000000000..5919da6564 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs @@ -0,0 +1,95 @@ +// +// GenerateGetter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.PatternMatching; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class GenerateGetter : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var initializer = GetVariableInitializer (context); + if (initializer == null || !initializer.NameToken.Contains (context.Location.Line, context.Location.Column)) + return false; + var type = initializer.Parent.Parent as TypeDeclaration; + if (type == null) + return false; + foreach (var member in type.Members) { + if (member is PropertyDeclaration && ContainsGetter ((PropertyDeclaration)member, initializer)) + return false; + } + return initializer.Parent is FieldDeclaration; + } + + public void Run (RefactoringContext context) + { + var initializer = GetVariableInitializer (context); + var field = initializer.Parent as FieldDeclaration; + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create getter", GeneratePropertyDeclaration (context, field, initializer), Script.InsertPosition.After); + } + } + + static PropertyDeclaration GeneratePropertyDeclaration (RefactoringContext context, FieldDeclaration field, VariableInitializer initializer) + { + var mod = ICSharpCode.NRefactory.CSharp.Modifiers.Public; + if (field.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Static)) + mod |= ICSharpCode.NRefactory.CSharp.Modifiers.Static; + + return new PropertyDeclaration () { + Modifiers = mod, + Name = context.GetNameProposal (initializer.Name, false), + ReturnType = field.ReturnType.Clone (), + Getter = new Accessor () { + Body = new BlockStatement () { + new ReturnStatement (new IdentifierExpression (initializer.Name)) + } + } + }; + } + + bool ContainsGetter (PropertyDeclaration property, VariableInitializer initializer) + { + if (property.Getter.IsNull || property.Getter.Body.Statements.Count () != 1) + return false; + var ret = property.Getter.Body.Statements.Single () as ReturnStatement; + if (ret == null) + return false; + return ret.Expression.IsMatch (new IdentifierExpression (initializer.Name)) || + ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)); + } + + VariableInitializer GetVariableInitializer (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs new file mode 100644 index 0000000000..28ce57cf4b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs @@ -0,0 +1,88 @@ +// +// GenerateSwitchLabels.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class GenerateSwitchLabels : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var switchStatement = GetSwitchStatement (context); + if (switchStatement == null) + return false; + var result = context.Resolve (switchStatement.Expression); + if (result == null) + return false; + return result.Type.IsEnum (); + } + + public void Run (RefactoringContext context) + { + var switchStatement = GetSwitchStatement (context); + + var result = context.Resolve (switchStatement.Expression); + var type = result.Type; + var newSwitch = (SwitchStatement)switchStatement.Clone (); + + var target = new TypeReferenceExpression (context.CreateShortType (result.Type.Resolve (context.TypeResolveContext))); + foreach (var field in type.GetFields (context.TypeResolveContext)) { + if (field.IsSynthetic || !field.IsConst) + continue; + newSwitch.SwitchSections.Add (new SwitchSection () { + CaseLabels = { + new CaseLabel (new MemberReferenceExpression (target.Clone (), field.Name)) + }, + Statements = { + new BreakStatement () + } + }); + } + + newSwitch.SwitchSections.Add (new SwitchSection () { + CaseLabels = { + new CaseLabel () + }, + Statements = { + new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "ArgumentOutOfRangeException"))) + } + }); + + using (var script = context.StartScript ()) { + script.Replace (switchStatement, newSwitch); + } + } + + static SwitchStatement GetSwitchStatement (RefactoringContext context) + { + var switchStatment = context.GetNode (); + if (switchStatment != null && switchStatment.SwitchSections.Count == 0) + return switchStatment; + return null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs new file mode 100644 index 0000000000..503899bd90 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs @@ -0,0 +1,94 @@ +// +// InsertAnonymousMethodSignature.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.TypeSystem; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class InsertAnonymousMethodSignature : IContextAction + { + public bool IsValid (RefactoringContext context) + { + IType type; + return GetAnonymousMethodExpression (context, out type) != null; + } + + public void Run (RefactoringContext context) + { + IType type; + var anonymousMethodExpression = GetAnonymousMethodExpression (context, out type); + + var delegateMethod = type.GetDelegateInvokeMethod (); + + var sb = new StringBuilder ("("); + for (int k = 0; k < delegateMethod.Parameters.Count; k++) { + if (k > 0) + sb.Append (", "); + + var paramType = delegateMethod.Parameters [k].Type; + + sb.Append (paramType.ToString ()); + sb.Append (" "); + sb.Append (delegateMethod.Parameters [k].Name); + } + sb.Append (")"); + + using (var script = context.StartScript ()) { + script.InsertText (context.GetOffset (anonymousMethodExpression.DelegateToken.EndLocation), sb.ToString ()); + } + } + + static AnonymousMethodExpression GetAnonymousMethodExpression (RefactoringContext context, out IType delegateType) + { + delegateType = null; + + var anonymousMethodExpression = context.GetNode (); + if (anonymousMethodExpression == null || !anonymousMethodExpression.DelegateToken.Contains (context.Location.Line, context.Location.Column) || anonymousMethodExpression.HasParameterList) + return null; + + IType resolvedType = null; + var parent = anonymousMethodExpression.Parent; + if (parent is AssignmentExpression) { + resolvedType = context.Resolve (((AssignmentExpression)parent).Left).Type; + } else if (parent is VariableDeclarationStatement) { + resolvedType = context.Resolve (((VariableDeclarationStatement)parent).Type).Type; + } else if (parent is InvocationExpression) { + // TODO: handle invocations + } + + if (resolvedType == null) + return null; + delegateType = resolvedType; + if (!delegateType.IsDelegate ()) + return null; + + return anonymousMethodExpression; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs new file mode 100644 index 0000000000..d1530b90de --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs @@ -0,0 +1,100 @@ +// +// IntroduceFormatItem.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.PatternMatching; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Introduce format item. Works on strings that contain selections. + /// "this is string" => string.Format ("this is {0} string", ) + /// + public class IntroduceFormatItem : IContextAction + { + readonly static MemberReferenceExpression PrototypeFormatReference = new MemberReferenceExpression (new TypeReferenceExpression (new PrimitiveType ("string")), "Format"); + + public bool IsValid (RefactoringContext context) + { + if (!context.IsSomethingSelected) + return false; + var pexpr = context.GetNode (); + if (pexpr == null || !(pexpr.Value is string)) + return false; + if (pexpr.LiteralValue.StartsWith ("@")) + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && + new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + return pexpr.StartLocation < context.Location && context.Location < pexpr.EndLocation; + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + var invocation = context.GetNode (); + if (invocation != null && invocation.Target.IsMatch (PrototypeFormatReference)) { + AddFormatCallToInvocation (context, pexpr, invocation); + return; + } + + var arg = CreateFormatArgument (context); + var newInvocation = new InvocationExpression (PrototypeFormatReference.Clone ()) { + Arguments = { CreateFormatString (context, pexpr, 0), arg } + }; + + using (var script = context.StartScript ()) { + script.Replace (pexpr, newInvocation); + script.Select (arg); + } + } + + void AddFormatCallToInvocation (RefactoringContext context, PrimitiveExpression pExpr, InvocationExpression invocation) + { + var newInvocation = (InvocationExpression)invocation.Clone (); + + newInvocation.Arguments.First ().ReplaceWith (CreateFormatString (context, pExpr, newInvocation.Arguments.Count () - 1)); + newInvocation.Arguments.Add (CreateFormatArgument (context)); + + using (var script = context.StartScript ()) { + script.Replace (invocation, newInvocation); + } + } + + static PrimitiveExpression CreateFormatArgument (RefactoringContext context) + { + return new PrimitiveExpression (context.SelectedText); + } + + static PrimitiveExpression CreateFormatString (RefactoringContext context, PrimitiveExpression pExpr, int argumentNumber) + { + var start = context.GetOffset (pExpr.StartLocation); + var end = context.GetOffset (pExpr.EndLocation); + + return new PrimitiveExpression ("", context.GetText (start, context.SelectionStart - start) + "{" + argumentNumber + "}" + context.GetText (context.SelectionEnd, end - context.SelectionEnd)); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs new file mode 100644 index 0000000000..79a59c32ae --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs @@ -0,0 +1,61 @@ +// +// InvertIf.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class InvertIf : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var ifStatement = GetIfElseStatement (context); + return ifStatement != null && !ifStatement.TrueStatement.IsNull && !ifStatement.FalseStatement.IsNull; + } + + // TODO: Invert if without else + // ex. if (cond) DoSomething () == if (!cond) return; DoSomething () + // beware of loop contexts return should be continue then. + public void Run (RefactoringContext context) + { + var ifStatement = GetIfElseStatement (context); + + using (var script = context.StartScript ()) { + script.Replace (ifStatement.Condition, CSharpUtil.InvertCondition (ifStatement.Condition)); + script.Replace (ifStatement.TrueStatement, ifStatement.FalseStatement); + script.Replace (ifStatement.FalseStatement, ifStatement.TrueStatement); + script.FormatText (ctx => GetIfElseStatement (ctx)); + } + } + + static IfElseStatement GetIfElseStatement (RefactoringContext context) + { + var result = context.GetNode (); + if (result != null && result.IfToken.Contains (context.Location)) + return result; + return null; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs new file mode 100644 index 0000000000..6655656bca --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs @@ -0,0 +1,123 @@ +// +// RemoveBackingStore.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.TypeSystem; +using System.Linq; +using ICSharpCode.NRefactory.CSharp.Resolver; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class RemoveBackingStore : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBackingField (context) != null; + } + + public void Run (RefactoringContext context) + { + var property = context.GetNode (); + var field = GetBackingField (context); + + context.ReplaceReferences (field, property); + + // create new auto property + var newProperty = (PropertyDeclaration)property.Clone (); + newProperty.Getter.Body = BlockStatement.Null; + newProperty.Setter.Body = BlockStatement.Null; + + using (var script = context.StartScript ()) { + script.Remove (context.Unit.GetNodeAt (field.Region.BeginLine, field.Region.BeginColumn)); + script.Replace (property, newProperty); + } + + } + +// void ReplaceBackingFieldReferences (MDRefactoringContext context, IField backingStore, PropertyDeclaration property) +// { +// using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { +// foreach (var memberRef in MonoDevelop.Ide.FindInFiles.ReferenceFinder.FindReferences (backingStore, monitor)) { +// if (property.Contains (memberRef.Line, memberRef.Column)) +// continue; +// if (backingStore.Location.Line == memberRef.Line && backingStore.Location.Column == memberRef.Column) +// continue; +// context.Do (new TextReplaceChange () { +// FileName = memberRef.FileName, +// Offset = memberRef.Position, +// RemovedChars = memberRef.Name.Length, +// InsertedText = property.Name +// }); +// } +// } +// } +// + static IField GetBackingField (RefactoringContext context) + { + var propertyDeclaration = context.GetNode (); + // automatic properties always need getter & setter + if (propertyDeclaration == null || propertyDeclaration.Getter.IsNull || propertyDeclaration.Setter.IsNull || propertyDeclaration.Getter.Body.IsNull || propertyDeclaration.Setter.Body.IsNull) + return null; + if (!context.HasCSharp3Support || propertyDeclaration.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Abstract) || ((TypeDeclaration)propertyDeclaration.Parent).ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + return null; + var getterField = ScanGetter (context, propertyDeclaration); + if (getterField == null) + return null; + var setterField = ScanSetter (context, propertyDeclaration); + if (setterField == null) + return null; + if (getterField.Region != setterField.Region) + return null; + return getterField; + } + + internal static IField ScanGetter (RefactoringContext context, PropertyDeclaration propertyDeclaration) + { + if (propertyDeclaration.Getter.Body.Statements.Count != 1) + return null; + var returnStatement = propertyDeclaration.Getter.Body.Statements.First () as ReturnStatement; + + var result = context.Resolve (returnStatement.Expression); + if (result == null || !(result is MemberResolveResult)) + return null; + return ((MemberResolveResult)result).Member as IField; + } + + internal static IField ScanSetter (RefactoringContext context, PropertyDeclaration propertyDeclaration) + { + if (propertyDeclaration.Setter.Body.Statements.Count != 1) + return null; + var setAssignment = propertyDeclaration.Setter.Body.Statements.First () as ExpressionStatement; + var assignment = setAssignment != null ? setAssignment.Expression as AssignmentExpression : null; + if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign) + return null; + var result = context.Resolve (assignment.Left); + if (result == null || !(result is MemberResolveResult)) + return null; + return ((MemberResolveResult)result).Member as IField; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs new file mode 100644 index 0000000000..eed2e429f0 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs @@ -0,0 +1,61 @@ +// +// RemoveBraces.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class RemoveBraces : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBlockStatement (context) != null; + } + + public void Run (RefactoringContext context) + { + var block = GetBlockStatement (context); + + using (var script = context.StartScript ()) { + script.Remove (block.LBraceToken); + script.Remove (block.RBraceToken); + script.FormatText (ctx => ctx.Unit.GetNodeAt (block.Parent.StartLocation)); + } + } + + static BlockStatement GetBlockStatement (RefactoringContext context) + { + var block = context.GetNode (); + if (block == null || block.LBraceToken.IsNull || block.RBraceToken.IsNull) + return null; + if (block.Parent.Role == TypeDeclaration.MemberRole) + return null; + if (block.Statements.Count () != 1) + return null; + return block; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs new file mode 100644 index 0000000000..4e91b866b3 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs @@ -0,0 +1,53 @@ +// +// ReplaceEmptyString.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class ReplaceEmptyString : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetEmptyString (context) != null; + } + + public void Run (RefactoringContext context) + { + var expr = GetEmptyString (context); + using (var script = context.StartScript ()) { + script.Replace (expr, new MemberReferenceExpression (new TypeReferenceExpression (new PrimitiveType ("string")), "Empty")); + } + } + + static PrimitiveExpression GetEmptyString (RefactoringContext context) + { + var node = context.GetNode (); + if (node == null || !(node.Value is string) || node.Value.ToString () != "") + return null; + return node; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs new file mode 100644 index 0000000000..4142280531 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs @@ -0,0 +1,74 @@ +// +// SplitDeclarationAndAssignment.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class SplitDeclarationAndAssignment : IContextAction + { + public bool IsValid (RefactoringContext context) + { + AstType type; + return GetVariableDeclarationStatement (context, out type) != null; + } + + public void Run (RefactoringContext context) + { + AstType type; + var varDecl = GetVariableDeclarationStatement (context, out type); + + var assign = new AssignmentExpression (new IdentifierExpression (varDecl.Variables.First ().Name), AssignmentOperatorType.Assign, varDecl.Variables.First ().Initializer.Clone ()); + + var newVarDecl = (VariableDeclarationStatement)varDecl.Clone (); + + if (newVarDecl.Type.IsMatch (new SimpleType ("var"))) + newVarDecl.Type = type; + + newVarDecl.Variables.First ().Initializer = Expression.Null; + + using (var script = context.StartScript ()) { + script.InsertBefore (varDecl, newVarDecl); + script.Replace (varDecl, varDecl.Parent is ForStatement ? (AstNode)assign : new ExpressionStatement (assign)); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context, out AstType resolvedType) + { + var result = context.GetNode (); + if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Variables.First ().NameToken.Contains (context.Location.Line, context.Location.Column)) { + resolvedType = context.Resolve (result.Variables.First ().Initializer).Type.ConvertToAstType (); + if (resolvedType == null) + return null; + return result; + } + resolvedType = null; + return null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs new file mode 100644 index 0000000000..425f54ca32 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs @@ -0,0 +1,55 @@ +// +// SplitString.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class SplitString: IContextAction + { + public bool IsValid (RefactoringContext context) + { + if (context.IsSomethingSelected) + return false; + var pexpr = context.GetNode (); + if (pexpr == null || !(pexpr.Value is string)) + return false; + if (pexpr.LiteralValue.StartsWith ("@")) + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 2) && + new AstLocation (context.Location.Line, context.Location.Column + 2) < pexpr.EndLocation; + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && + new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + int offset = context.GetOffset (context.Location); + using (var script = context.StartScript ()) { + script.InsertText (offset, pexpr.LiteralValue.StartsWith ("@") ? "\" + @\"" : "\" + \""); + } + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs new file mode 100644 index 0000000000..b31bf78cb3 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs @@ -0,0 +1,67 @@ +// +// UseExplicitType.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.TypeSystem; + + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class UseExplicitType: IContextAction + { + public bool IsValid (RefactoringContext context) + { + var varDecl = GetVariableDeclarationStatement (context); + if (varDecl == null) + return false; + var type = context.Resolve (varDecl.Variables.First ().Initializer).Type; + return !type.Equals (SharedTypes.Null) && !type.Equals (SharedTypes.UnknownType); + } + + public void Run (RefactoringContext context) + { + var varDecl = GetVariableDeclarationStatement (context); + + using (var script = context.StartScript ()) { + var type = context.Resolve (varDecl.Variables.First ().Initializer).Type; + script.Replace (varDecl.Type, context.CreateShortType (type)); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context) + { + var result = context.GetNode (); + if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location.Line, context.Location.Column) && result.Type.IsMatch (new SimpleType ("var"))) { + if (context.Resolve (result.Variables.First ().Initializer) == null) + return null; + return result; + } + return null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs new file mode 100644 index 0000000000..8aa9c8b66e --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs @@ -0,0 +1,56 @@ +// +// UseVarKeyword.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class UseVarKeyword: IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetVariableDeclarationStatement (context) != null; + } + + public void Run (RefactoringContext context) + { + var varDecl = GetVariableDeclarationStatement (context); + using (var script = context.StartScript ()) { + script.Replace (varDecl.Type, new SimpleType ("var")); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context) + { + var result = context.GetNode (); + if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location.Line, context.Location.Column) && !result.Type.IsMatch (new SimpleType ("var"))) + return result; + return null; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs new file mode 100644 index 0000000000..11212a1c9a --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs @@ -0,0 +1,44 @@ +// +// CreateLinkAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class CreateLinkAction : Action + { + public IEnumerable Linked { + get; + private set; + } + + public CreateLinkAction (IEnumerable linked) + { + this.Linked = linked; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs new file mode 100644 index 0000000000..8b7fde6615 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs @@ -0,0 +1,39 @@ +// +// FormatTextAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class FormatTextAction : Action + { + public Func Callback { get; private set; } + + public FormatTextAction (Func callback) + { + this.Callback = callback; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs new file mode 100644 index 0000000000..f801a1c9b9 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs @@ -0,0 +1,75 @@ +// +// IChangeFactory.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// A factory that creates the changes. + /// + public interface IActionFactory + { + TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText); + NodeOutputAction CreateNodeOutputAction (int offset, int removedChars, NodeOutput output); + NodeSelectionAction CreateNodeSelectionAction (AstNode node); + FormatTextAction CreateFormatTextAction (Func callback); + CreateLinkAction CreateLinkAction (IEnumerable linkedNodes); + } + + public abstract class AbstractActionFactory : IActionFactory + { + #region IActionFactory implementation + public virtual TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText) + { + throw new NotImplementedException (); + } + + public virtual NodeOutputAction CreateNodeOutputAction (int offset, int removedChars, NodeOutput output) + { + throw new NotImplementedException (); + } + + public virtual NodeSelectionAction CreateNodeSelectionAction (AstNode node) + { + throw new NotImplementedException (); + } + + public virtual FormatTextAction CreateFormatTextAction (Func callback) + { + throw new NotImplementedException (); + } + + public virtual CreateLinkAction CreateLinkAction (IEnumerable linkedNodes) + { + throw new NotImplementedException (); + } + #endregion + + } + +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs new file mode 100644 index 0000000000..8c2b64ce23 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs @@ -0,0 +1,36 @@ +// +// ContextAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public interface IContextAction + { + bool IsValid (RefactoringContext context); + void Run (RefactoringContext context); + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs new file mode 100644 index 0000000000..47d5e7ba70 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs @@ -0,0 +1,136 @@ +// +// NodeOutputChange.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// This is the node that should be outputted at a position. + /// + public class NodeOutput + { + public readonly Dictionary NodeSegments = new Dictionary (); + + public string Text { + get; + set; + } + + public void Trim () + { + for (int i = 0; i < Text.Length; i++) { + char ch = Text [i]; + if (ch != ' ' && ch != '\t') { + if (i > 0) { + Text = Text.Substring (i); + foreach (var seg in NodeSegments.Values) { + seg.Offset -= i; + } + } + break; + } + } + } + + public class Segment : ISegment + { + public int Offset { + get; + set; + } + + public int Length { + get { + return EndOffset - Offset; + } + } + + public int EndOffset { + get; + set; + } + + public Segment (int offset) + { + this.Offset = offset; + } + } + } + + + /// + /// Outputs an Ast node at a specific offset. + /// + public abstract class NodeOutputAction : TextReplaceAction + { + public NodeOutput NodeOutput { + get; + private set; + } + + public override string InsertedText { + get { + return NodeOutput.Text; + } + set { + throw new NotSupportedException ("Changing text with this propery is not supported on NodeOutputChange."); + } + } + + public NodeOutputAction (int offset, int removedChars, NodeOutput output) : base (offset, removedChars) + { + if (output == null) + throw new ArgumentNullException ("output"); + this.NodeOutput = output; + } + } + + + /// + /// An (Offset,Length)-pair. + /// + public interface ISegment + { + /// + /// Gets the start offset of the segment. + /// + int Offset { get; } + + /// + /// Gets the length of the segment. + /// + /// Must not be negative. + int Length { get; } + + /// + /// Gets the end offset of the segment. + /// + /// EndOffset = Offset + Length; + int EndOffset { get; } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs new file mode 100644 index 0000000000..b7df34b951 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs @@ -0,0 +1,40 @@ +// +// SelectionAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class NodeSelectionAction : Action + { + public AstNode AstNode { get; private set; } + + public NodeSelectionAction (AstNode astNode) + { + this.AstNode = astNode; + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs new file mode 100644 index 0000000000..a73d973733 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs @@ -0,0 +1,141 @@ +// +// RefactoringContext.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp.Resolver; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class RefactoringContext : AbstractActionFactory + { + public CompilationUnit Unit { + get; + protected set; + } + + public virtual ITypeResolveContext TypeResolveContext { + get { + return null; + } + } + + public AstLocation Location { + get; + protected set; + } + + public abstract bool HasCSharp3Support { + get; + } + + public abstract CSharpFormattingOptions FormattingOptions { + get; + } + + public abstract AstType CreateShortType (IType fullType); + + public AstType CreateShortType (string ns, string typeName) + { + return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal)); + } + + public virtual AstType CreateShortType (AstType fullType) + { + return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext)); + } + +// public abstract IType GetDefinition (AstType resolvedType); + + public abstract void ReplaceReferences (IMember member, MemberDeclaration replaceWidth); + + public AstNode GetNode () + { + return Unit.GetNodeAt (Location); + } + + public T GetNode () where T : AstNode + { + return Unit.GetNodeAt (Location); + } + + public abstract Script StartScript (); + + #region Text stuff + public abstract string EolMarker { get; } + public abstract bool IsSomethingSelected { get; } + public abstract string SelectedText { get; } + public abstract int SelectionStart { get; } + public abstract int SelectionEnd { get; } + public abstract int SelectionLength { get; } + public abstract int GetOffset (AstLocation location); + public int GetOffset (int line, int col) + { + return GetOffset (new AstLocation (line, col)); + } + public abstract AstLocation GetLocation (int offset); + public abstract string GetText (int offset, int length); + #endregion + + #region Resolving + public abstract ResolveResult Resolve (AstNode expression); + #endregion + + public string GetNameProposal (string name, bool camelCase = true) + { + string baseName = (camelCase ? char.ToLower (name [0]) : char.ToUpper (name [0])) + name.Substring (1); + + var type = GetNode (); + if (type == null) + return baseName; + + int number = -1; + string proposedName; + do { + proposedName = AppendNumberToName (baseName, number++); + } while (type.Members.Select (m => m.GetChildByRole (AstNode.Roles.Identifier)).Any (n => n.Name == proposedName)); + return proposedName; + } + + static string AppendNumberToName (string baseName, int number) + { + return baseName + (number > 0 ? (number + 1).ToString () : ""); + } + } + + public static class ExtensionMethods + { + #region ConvertTypes + public static ICSharpCode.NRefactory.CSharp.AstType ConvertToAstType (this IType type) + { + var builder = new TypeSystemAstBuilder (); + return builder.ConvertType (type); + } + #endregion + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs new file mode 100644 index 0000000000..db6be31899 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs @@ -0,0 +1,180 @@ +// +// Script.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class Script : IDisposable + { + public RefactoringContext Context { + get; + private set; + } + + protected readonly List changes = new List (); + + public IEnumerable Actions { + get { + return changes; + } + } + + public Script (RefactoringContext context) + { + if (context == null) + throw new ArgumentNullException ("context"); + this.Context = context; + } + + public void Queue (Action change) + { + changes.Add (change); + } + + public void InsertText (int offset, string text) + { + Queue (Context.CreateTextReplaceAction (offset, 0, text)); + } + + public void InsertBefore (AstNode node, AstNode insertNode) + { + var startOffset = Context.GetOffset (node.StartLocation.Line, 1); + var output = OutputNode (GetIndentLevelAt (startOffset), insertNode); + + if (!(insertNode is Expression || insertNode is AstType)) + output.Text += Context.EolMarker; + + Queue (Context.CreateNodeOutputAction (startOffset, 0, output)); + } + + public void AddTo (BlockStatement bodyStatement, AstNode insertNode) + { + var startOffset = Context.GetOffset (bodyStatement.LBraceToken.StartLocation) + 1; + var output = OutputNode (GetIndentLevelAt (startOffset), insertNode, true); + Queue (Context.CreateNodeOutputAction (startOffset, 0, output)); + } + + public void Link (params AstNode[] nodes) + { + Queue (Context.CreateLinkAction (nodes)); + } + + public void Link (IEnumerable nodes) + { + Queue (Context.CreateLinkAction (nodes)); + } + + public void Remove (AstNode node) + { + var startOffset = Context.GetOffset (node.StartLocation); + var endOffset = Context.GetOffset (node.EndLocation); + Remove (startOffset, endOffset - startOffset); + } + + void Remove (int offset, int length) + { + Queue (Context.CreateTextReplaceAction (offset, length, null)); + } + + void Replace (int offset, int length, string text) + { + Queue (Context.CreateTextReplaceAction (offset, length, text)); + } + + public void Replace (AstNode node, AstNode replaceWith) + { + var startOffset = Context.GetOffset (node.StartLocation); + var endOffset = Context.GetOffset (node.EndLocation); + int level = 0; + if (!(replaceWith is Expression) && !(replaceWith is AstType)) + level = GetIndentLevelAt (startOffset); + NodeOutput output = OutputNode (level, replaceWith); + output.Trim (); + Queue (Context.CreateNodeOutputAction (startOffset, endOffset - startOffset, output)); + } + + public void FormatText (Func callback) + { + Queue (Context.CreateFormatTextAction (callback)); + } + + public void Select (AstNode node) + { + Queue (Context.CreateNodeSelectionAction (node)); + } + + public enum InsertPosition { + Start, + Before, + After, + End + } + + public abstract void InsertWithCursor (string operation, AstNode node, InsertPosition defaultPosition); + + protected int GetIndentLevelAt (int offset) + { + var node = Context.Unit.GetNodeAt (Context.GetLocation (offset)); + int level = 0; + while (node != null) { + if (node is BlockStatement || node is TypeDeclaration || node is NamespaceDeclaration) + level++; + node = node.Parent; + } + return level; + } + + protected NodeOutput OutputNode (int indentLevel, AstNode node, bool startWithNewLine = false) + { + var result = new NodeOutput (); + var stringWriter = new System.IO.StringWriter (); + var formatter = new TextWriterOutputFormatter (stringWriter); + formatter.Indentation = indentLevel; + stringWriter.NewLine = Context.EolMarker; + if (startWithNewLine) + formatter.NewLine (); + var visitor = new OutputVisitor (formatter, Context.FormattingOptions); + visitor.OutputStarted += (sender, e) => { + result.NodeSegments [e.AstNode] = new NodeOutput.Segment (stringWriter.GetStringBuilder ().Length); + }; + visitor.OutputFinished += (sender, e) => { + result.NodeSegments [e.AstNode].EndOffset = stringWriter.GetStringBuilder ().Length; + }; + node.AcceptVisitor (visitor, null); + result.Text = stringWriter.ToString ().TrimEnd (); + if (node is FieldDeclaration) + result.Text += Context.EolMarker; + + return result; + } + + #region IDisposable implementation + public abstract void Dispose (); + #endregion + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs new file mode 100644 index 0000000000..63830b47a0 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs @@ -0,0 +1,158 @@ +// +// StringBuilderOutputFormatter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Text; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class StringBuilderOutputFormatter : IOutputFormatter + { + readonly StringBuilder sb = new StringBuilder (); + int indentation; + bool needsIndent = true; + + public int Length { + get { + WriteIndentation (); + return sb.Length; + } + } + + public int Indentation { + get { + return this.indentation; + } + set { + indentation = value; + } + } + + public string EolMarker { + get; + set; + } + + public override string ToString () + { + return sb.ToString (); + } + + public void WriteIdentifier (string ident) + { + WriteIndentation (); + sb.Append (ident); + } + + public void WriteKeyword (string keyword) + { + WriteIndentation (); + sb.Append (keyword); + } + + public void WriteToken (string token) + { + WriteIndentation (); + sb.Append (token); + } + + public void Space () + { + WriteIndentation (); + sb.Append (' '); + } + + public void OpenBrace (BraceStyle style) + { + WriteIndentation (); + sb.Append (' '); + sb.Append ('{'); + Indent (); + NewLine (); + } + + public void CloseBrace (BraceStyle style) + { + Unindent (); + WriteIndentation (); + sb.Append ('}'); + } + + void WriteIndentation () + { + if (needsIndent) { + needsIndent = false; + for (int i = 0; i < indentation; i++) { + sb.Append ('\t'); + } + } + } + + public void NewLine () + { + sb.Append (EolMarker); + needsIndent = true; + } + + public void Indent () + { + indentation++; + } + + public void Unindent () + { + indentation--; + } + + public void WriteComment (CommentType commentType, string content) + { + WriteIndentation (); + switch (commentType) { + case CommentType.SingleLine: + sb.Append ("//"); + sb.AppendLine (content); + break; + case CommentType.MultiLine: + sb.Append ("/*"); + sb.Append (content); + sb.Append ("*/"); + break; + case CommentType.Documentation: + sb.Append ("///"); + sb.AppendLine (content); + break; + } + } + + public virtual void StartNode (AstNode node) + { + } + + public virtual void EndNode (AstNode node) + { + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs new file mode 100644 index 0000000000..d2bc29f585 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs @@ -0,0 +1,134 @@ +// +// TextReplaceChange.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// This is the base action for changes in a text document. + /// + public abstract class TextReplaceAction : Action + { + /// + /// Gets or sets the offset. + /// + /// + /// The offset of the replace. + /// + public int Offset { + get; + set; + } + + int removedChars; + /// + /// Gets or sets the numer of chars to removed. + /// + /// + /// The numer of chars to remove. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + /// + public int RemovedChars { + get { + return removedChars; + } + set { + if (value < 0) + throw new ArgumentOutOfRangeException ("RemovedChars", "needs to be >= 0"); + removedChars = value; + } + } + + /// + /// Gets or sets the inserted text. + /// + /// + /// The text to insert. + /// + public virtual string InsertedText { + get; + set; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The offset of the replace. + /// + /// + /// The numer of chars to remove. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + /// + protected TextReplaceAction (int offset, int removedChars) + { + if (removedChars < 0) + throw new ArgumentOutOfRangeException ("removedChars", "removedChars needs to be >= 0"); + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "offset needs to be >= 0"); + this.removedChars = removedChars; + this.Offset = offset; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The offset of the replace. + /// + /// + /// The numer of chars to remove. + /// + /// + /// The text to insert. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + public TextReplaceAction (int offset, int removedChars, string insertedText) : this (offset, removedChars) + { + this.InsertedText = insertedText; + } + + /// + /// Returns a that represents the current . + /// + /// + /// A that represents the current . + /// + public override string ToString () + { + return string.Format ("[TextReplaceAction: Offset={0}, RemovedChars={1}, InsertedText={2}]", Offset, RemovedChars, InsertedText == null ? "" : InsertedText.Replace ("\t", "\\t").Replace ("\n", "\\n")); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs new file mode 100644 index 0000000000..6bd0c98309 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -0,0 +1,218 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Converts from type system to the C# AST. + /// + public class TypeSystemAstBuilder + { + readonly CSharpResolver resolver; + + /// + /// Creates a new TypeSystemAstBuilder. + /// + /// + /// A resolver initialized for the position where the type will be inserted. + /// + public TypeSystemAstBuilder(CSharpResolver resolver = null) + { + this.resolver = resolver; + } + + public AstType ConvertType(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + TypeWithElementType typeWithElementType = type as TypeWithElementType; + if (typeWithElementType != null) { + if (typeWithElementType is PointerType) { + return ConvertType(typeWithElementType.ElementType).MakePointerType(); + } else if (typeWithElementType is ArrayType) { + return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); + } else { + // e.g. ByReferenceType; not supported as type in C# + return ConvertType(typeWithElementType.ElementType); + } + } + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { + return ConvertType(pt.TypeArguments[0]).MakeNullableType(); + } + return ConvertTypeDefinition(pt.GetDefinition(), pt.TypeArguments); + } + ITypeDefinition typeDef = type as ITypeDefinition; + if (typeDef != null) { + if (typeDef.TypeParameterCount > 0) { + // Create an unbound type + IType[] typeArguments = new IType[typeDef.TypeParameterCount]; + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = SharedTypes.UnknownType; + } + return ConvertTypeDefinition(typeDef, typeArguments); + } else { + return ConvertTypeDefinition(typeDef, EmptyList.Instance); + } + } + return new SimpleType(type.Name); + } + + AstType ConvertTypeDefinition(ITypeDefinition typeDef, IList typeArguments) + { + Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); + switch (ReflectionHelper.GetTypeCode(typeDef)) { + case TypeCode.Object: + return new PrimitiveType("object"); + case TypeCode.Boolean: + return new PrimitiveType("bool"); + case TypeCode.Char: + return new PrimitiveType("char"); + case TypeCode.SByte: + return new PrimitiveType("sbyte"); + case TypeCode.Byte: + return new PrimitiveType("byte"); + case TypeCode.Int16: + return new PrimitiveType("short"); + case TypeCode.UInt16: + return new PrimitiveType("ushort"); + case TypeCode.Int32: + return new PrimitiveType("int"); + case TypeCode.UInt32: + return new PrimitiveType("uint"); + case TypeCode.Int64: + return new PrimitiveType("long"); + case TypeCode.UInt64: + return new PrimitiveType("ulong"); + case TypeCode.Single: + return new PrimitiveType("float"); + case TypeCode.Double: + return new PrimitiveType("double"); + case TypeCode.Decimal: + return new PrimitiveType("decimal"); + case TypeCode.String: + return new PrimitiveType("string"); + } + // There is no type code for System.Void + if (typeDef != null && typeDef.Namespace == "System" && typeDef.Name == "Void" && typeDef.TypeParameterCount == 0) + return new PrimitiveType("void"); + if (resolver != null && TypeArgumentsTrivial(typeArguments, OuterTypeParameterCount(typeDef))) { + TypeResolveResult trr = resolver.ResolveSimpleName(typeDef.Name, typeArguments) as TypeResolveResult; + if (trr != null && !trr.IsError && trr.Type.GetDefinition() == typeDef) { + // We can use the short type name + SimpleType shortResult = new SimpleType(typeDef.Name); + AddTypeArguments(shortResult, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); + return shortResult; + } + } + + MemberType result = new MemberType(); + if (typeDef.DeclaringTypeDefinition != null) { + // Handle nested types + result.Target = ConvertTypeDefinition(typeDef.DeclaringTypeDefinition, typeArguments); + } else { + // Handle top-level types + if (string.IsNullOrEmpty(typeDef.Namespace)) { + result.Target = new SimpleType("global"); + result.IsDoubleColon = true; + } else { + result.Target = ConvertNamespace(typeDef.Namespace); + } + } + result.MemberName = typeDef.Name; + AddTypeArguments(result, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); + return result; + } + + /// + /// Gets the number of type parameters belonging to outer classes. + /// + int OuterTypeParameterCount(ITypeDefinition typeDef) + { + if (typeDef.DeclaringType != null) + return typeDef.DeclaringType.TypeParameterCount; + else + return 0; + } + + /// + /// Gets whether the first type arguments are trivial, + /// that is, they point to a type parameter with the same index. + /// + bool TypeArgumentsTrivial(IList typeArguments, int num) + { + for (int i = 0; i < num; i++) { + ITypeParameter tp = typeArguments[i] as ITypeParameter; + if (!(tp != null && tp.OwnerType == EntityType.TypeDefinition && tp.Index == i)) + return false; + } + return true; + } + + /// + /// Adds type arguments to the result type. + /// + /// The result AST node (a SimpleType or MemberType) + /// The list of type arguments + /// Index of first type argument to add + /// Index after last type argument to add + void AddTypeArguments(AstType result, IList typeArguments, int startIndex, int endIndex) + { + for (int i = startIndex; i < endIndex; i++) { + result.AddChild(ConvertType(typeArguments[i]), AstType.Roles.TypeArgument); + } + } + + AstType ConvertNamespace(string ns) + { + if (resolver != null) { + // Look if there's an alias to the target namespace + for (UsingScope usingScope = resolver.UsingScope; usingScope != null; usingScope = usingScope.Parent) { + foreach (var pair in usingScope.UsingAliases) { + // maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts + NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context); + if (nrr != null && nrr.NamespaceName == ns) + return new SimpleType(pair.Key); + } + } + } + + int pos = ns.LastIndexOf('.'); + if (pos < 0) { + if (IsValidNamespace(ns)) { + return new SimpleType(ns); + } else { + return new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = ns + }; + } + } else { + string parentNamespace = ns.Substring(0, pos); + string localNamespace = ns.Substring(pos + 1); + return new MemberType { + Target = ConvertNamespace(parentNamespace), + MemberName = localNamespace + }; + } + } + + bool IsValidNamespace(string firstNamespacePart) + { + if (resolver == null) + return true; // just assume namespaces are valid if we don't have a resolver + NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList.Instance) as NamespaceResolveResult; + return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs new file mode 100644 index 0000000000..f2f5dba1f7 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs @@ -0,0 +1,144 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public sealed class CSharpAttribute : Immutable, IAttribute + { + ITypeReference attributeType; + DomRegion region; + IList positionalArguments; + IList> namedCtorArguments; + IList> namedArguments; + + public CSharpAttribute(ITypeReference attributeType, DomRegion region, + IList positionalArguments, + IList> namedCtorArguments, + IList> namedArguments) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + this.attributeType = attributeType; + this.region = region; + this.positionalArguments = positionalArguments; + this.namedCtorArguments = namedCtorArguments; + this.namedArguments = namedArguments; + } + + public DomRegion Region { + get { return region; } + } + + public ITypeReference AttributeType { + get { return attributeType; } + } + + public IMethod ResolveConstructor(ITypeResolveContext context) + { + IType type = attributeType.Resolve(context); + throw new NotImplementedException(); + } + + public IList GetPositionalArguments(ITypeResolveContext context) + { + if (namedCtorArguments == null || namedCtorArguments.Count == 0) { + // no namedCtorArguments: just return the positionalArguments + if (positionalArguments != null) + return new ReadOnlyCollection(positionalArguments); + else + return EmptyList.Instance; + } + // we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments + List result = new List(this.positionalArguments); + IMethod method = ResolveConstructor(context); + if (method != null) { + for (int i = result.Count; i < method.Parameters.Count; i++) { + IParameter p = method.Parameters[i]; + bool found = false; + foreach (var pair in namedCtorArguments) { + if (pair.Key == p.Name) { + result.Add(pair.Value); + found = true; + } + } + if (!found) { + // add the parameter's default value: + result.Add(p.DefaultValue ?? new SimpleConstantValue(p.Type, CSharpResolver.GetDefaultValue(p.Type.Resolve(context)))); + } + } + } + return result.AsReadOnly(); + } + + public IList> GetNamedArguments(ITypeResolveContext context) + { + if (namedArguments != null) + return new ReadOnlyCollection>(namedArguments); + else + return EmptyList>.Instance; + } + } + + /// + /// Type reference used within an attribute. + /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. + /// + public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning + { + ITypeReference withoutSuffix, withSuffix; + + public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix) + { + if (withoutSuffix == null) + throw new ArgumentNullException("withoutSuffix"); + if (withSuffix == null) + throw new ArgumentNullException("withSuffix"); + this.withoutSuffix = withoutSuffix; + this.withSuffix = withSuffix; + } + + public IType Resolve(ITypeResolveContext context) + { + // If both types exist, C# considers that to be an ambiguity, but we are less strict. + IType type = withoutSuffix.Resolve(context); + var attrType = context.GetTypeDefinition (typeof(System.Attribute)); + if (attrType == null) + return SharedTypes.UnknownType; + + if (type == SharedTypes.UnknownType || !(type.GetDefinition () != null && type.GetDefinition ().IsDerivedFrom (attrType, context))) + type = withSuffix.Resolve(context); + + return type; + } + + public override string ToString() + { + return withoutSuffix.ToString() + "[Attribute]"; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + withoutSuffix = provider.Intern(withoutSuffix); + withSuffix = provider.Intern(withSuffix); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return withoutSuffix.GetHashCode() + 715613 * withSuffix.GetHashCode(); + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + AttributeTypeReference atr = other as AttributeTypeReference; + return atr != null && this.withoutSuffix == atr.withoutSuffix && this.withSuffix == atr.withSuffix; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 2a32d791aa..31dbf0f869 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -26,11 +26,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal readonly CancellationToken cancellationToken; #region Constructor - public CSharpResolver(ITypeResolveContext context) + public CSharpResolver(ITypeResolveContext context) : this (context, CancellationToken.None) { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; } public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken) @@ -86,12 +83,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal readonly LocalVariable prev; internal readonly ITypeReference type; + internal readonly DomRegion region; internal readonly string name; internal readonly IConstantValue constantValue; - public LocalVariable(LocalVariable prev, ITypeReference type, string name, IConstantValue constantValue) + public LocalVariable(LocalVariable prev, ITypeReference type, DomRegion region, string name, IConstantValue constantValue) { this.prev = prev; + this.region = region; this.type = type; this.name = name; this.constantValue = constantValue; @@ -100,6 +99,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public string Name { get { return name; } } + + public DomRegion DeclarationRegion { + get { return region; } + } + public ITypeReference Type { get { return type; } } @@ -126,7 +130,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public void PushBlock() { - localVariableStack = new LocalVariable(localVariableStack, null, null, null); + localVariableStack = new LocalVariable(localVariableStack, null, DomRegion.Empty, null, null); } /// @@ -146,13 +150,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Adds a new variable to the current block. /// - public IVariable AddVariable(ITypeReference type, string name, IConstantValue constantValue = null) + public IVariable AddVariable(ITypeReference type, DomRegion declarationRegion, string name, IConstantValue constantValue = null) { if (type == null) throw new ArgumentNullException("type"); if (name == null) throw new ArgumentNullException("name"); - return localVariableStack = new LocalVariable(localVariableStack, type, name, constantValue); + return localVariableStack = new LocalVariable(localVariableStack, type, declarationRegion, name, constantValue); } /// @@ -306,6 +310,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return true; } } + bool IEntity.IsPrivate { + get { return false; } + } + + bool IEntity.IsPublic { + get { return true; } + } + + bool IEntity.IsProtected { + get { return false; } + } + + bool IEntity.IsInternal { + get { return false; } + } + + bool IEntity.IsProtectedOrInternal { + get { return false; } + } + + bool IEntity.IsProtectedAndInternal { + get { return false; } + } + IProjectContent IEntity.ProjectContent { get { throw new NotSupportedException(); } } @@ -628,8 +656,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // TODO: find user-defined operators - if (lhsType == SharedTypes.Null && rhsType.IsReferenceType == false - || lhsType.IsReferenceType == false && rhsType == SharedTypes.Null) + if (lhsType == SharedTypes.Null && rhsType.IsReferenceType(context) == false + || lhsType.IsReferenceType(context) == false && rhsType == SharedTypes.Null) { isNullable = true; } @@ -1559,9 +1587,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { if (k == 0) { // look for type parameter with that name - foreach (ITypeParameter tp in t.TypeParameters) { - if (tp.Name == identifier) - return new TypeResolveResult(tp); + var typeParameters = t.TypeParameters; + // only look at type parameters defined directly on this type, not at those copied from outer classes + for (int i = (t.DeclaringTypeDefinition != null ? t.DeclaringTypeDefinition.TypeParameterCount : 0); i < typeParameters.Count; i++) { + if (typeParameters[i].Name == identifier) + return new TypeResolveResult(typeParameters[i]); } } @@ -1587,7 +1617,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } // then look for a type - ITypeDefinition def = context.GetClass(n.NamespaceName, identifier, k, StringComparer.Ordinal); + ITypeDefinition def = context.GetTypeDefinition(n.NamespaceName, identifier, k, StringComparer.Ordinal); if (def != null) { IType result = def; if (k != 0) { @@ -1621,14 +1651,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver foreach (var u in n.Usings) { NamespaceResolveResult ns = u.ResolveNamespace(context); if (ns != null) { - def = context.GetClass(ns.NamespaceName, identifier, k, StringComparer.Ordinal); - if (firstResult == null) { - if (k == 0) - firstResult = def; - else - firstResult = new ParameterizedType(def, typeArguments); - } else { - return new AmbiguousTypeResolveResult(firstResult); + def = context.GetTypeDefinition(ns.NamespaceName, identifier, k, StringComparer.Ordinal); + if (def != null) { + if (firstResult == null) { + if (k == 0) + firstResult = def; + else + firstResult = new ParameterizedType(def, typeArguments); + } else { + return new AmbiguousTypeResolveResult(firstResult); + } } } } @@ -1637,10 +1669,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // if we didn't find anything: repeat lookup with parent namespace } - if (typeArguments.Count == 0) - return new UnknownIdentifierResolveResult(identifier); - else + if (typeArguments.Count == 0) { + if (identifier == "dynamic") + return new TypeResolveResult(SharedTypes.Dynamic); + else + return new UnknownIdentifierResolveResult(identifier); + } else { return ErrorResult; + } } /// @@ -1685,7 +1721,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) return new NamespaceResolveResult(fullName); } - ITypeDefinition def = context.GetClass(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); + ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); if (def != null) return new TypeResolveResult(def); return ErrorResult; @@ -1760,7 +1796,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IEnumerable GetExtensionMethods(string namespaceName) { return - from c in context.GetClasses(namespaceName, StringComparer.Ordinal) + from c in context.GetTypes(namespaceName, StringComparer.Ordinal) where c.IsStatic && c.HasExtensionMethods from m in c.Methods where m.IsExtensionMethod @@ -1869,7 +1905,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver do { newName = newArgumentName + num.ToString(); num++; - } while(argumentNames.Contains(newArgumentName)); + } while(argumentNames.Contains(newName)); newArgumentName = newName; } argumentNames[i] = newArgumentName; @@ -2043,7 +2079,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region ResolveConditional - public ResolveResult ResolveConditional(ResolveResult trueExpression, ResolveResult falseExpression) + public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression) { // C# 4.0 spec §7.14: Conditional operator @@ -2052,11 +2088,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Conversions c = new Conversions(context); bool isValid; IType resultType; - if (HasType(trueExpression) && HasType(falseExpression)) { + if (trueExpression.Type == SharedTypes.Dynamic || falseExpression.Type == SharedTypes.Dynamic) { + resultType = SharedTypes.Dynamic; + isValid = true; + } else if (HasType(trueExpression) && HasType(falseExpression)) { bool t2f = c.ImplicitConversion(trueExpression.Type, falseExpression.Type); bool f2t = c.ImplicitConversion(falseExpression.Type, trueExpression.Type); - resultType = (f2t && !t2f) ? falseExpression.Type : trueExpression.Type; - isValid = (t2f != f2t) || (t2f && f2t && c.IdentityConversion(trueExpression.Type, falseExpression.Type)); + resultType = (f2t && !t2f) ? trueExpression.Type : falseExpression.Type; + // The operator is valid: + // a) if there's a conversion in one direction but not the other + // b) if there are conversions in both directions, and the types are equivalent + isValid = (t2f != f2t) || (t2f && f2t && trueExpression.Type.Equals(falseExpression.Type)); } else if (HasType(trueExpression)) { resultType = trueExpression.Type; isValid = c.ImplicitConversion(falseExpression, resultType); @@ -2066,7 +2108,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { return ErrorResult; } - return isValid ? new ResolveResult(resultType) : new ErrorResolveResult(resultType); + if (isValid) { + if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) { + bool? val = condition.ConstantValue as bool?; + if (val == true) + return ResolveCast(resultType, trueExpression); + else if (val == false) + return ResolveCast(resultType, falseExpression); + } + return new ResolveResult(resultType); + } else { + return new ErrorResolveResult(resultType); + } } bool HasType(ResolveResult r) @@ -2087,5 +2140,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } #endregion + + #region ResolveDefaultValue + public ResolveResult ResolveDefaultValue(IType type) + { + return new ConstantResolveResult(type, GetDefaultValue(type)); + } + + public static object GetDefaultValue(IType type) + { + switch (ReflectionHelper.GetTypeCode(type)) { + case TypeCode.Boolean: + return false; + case TypeCode.Char: + return '\0'; + case TypeCode.SByte: + return (sbyte)0; + case TypeCode.Byte: + return (byte)0; + case TypeCode.Int16: + return (short)0; + case TypeCode.UInt16: + return (ushort)0; + case TypeCode.Int32: + return 0; + case TypeCode.UInt32: + return 0U; + case TypeCode.Int64: + return 0L; + case TypeCode.UInt64: + return 0UL; + case TypeCode.Single: + return 0f; + case TypeCode.Double: + return 0.0; + case TypeCode.Decimal: + return 0m; + default: + return null; + } + } + #endregion } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs new file mode 100644 index 0000000000..5c59905173 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs @@ -0,0 +1,638 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.CSharp.Analysis; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues +{ + // Contains representations for constant C# expressions. + // We use these instead of storing the full AST to reduce the memory usage. + + public sealed class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning + { + ConstantExpression expression; + UsingScope parentUsingScope; + ITypeDefinition parentTypeDefinition; + + public CSharpConstantValue(ConstantExpression expression, UsingScope parentUsingScope, ITypeDefinition parentTypeDefinition) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.expression = expression; + this.parentUsingScope = parentUsingScope; + this.parentTypeDefinition = parentTypeDefinition; + } + + CSharpResolver CreateResolver(ITypeResolveContext context) + { + // Because constants are evaluated by the compiler, we need to evaluate them in the resolve context + // of the project where they are defined, not in that where the constant value is used. + // TODO: how do we get the correct resolve context? + return new CSharpResolver(context) { + CheckForOverflow = false, // TODO: get project-wide overflow setting + CurrentTypeDefinition = parentTypeDefinition, + UsingScope = parentUsingScope + }; + } + + public IType GetValueType(ITypeResolveContext context) + { + CSharpResolver resolver = CreateResolver(context); + IType type = expression.Resolve(resolver).Type; + if (resolver.Context != context) { + // Retrieve the equivalent type in the new resolve context. + // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0. + // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0. + return type.AcceptVisitor(new MapTypeIntoNewContext(context)); + } + return type; + } + + public object GetValue(ITypeResolveContext context) + { + CSharpResolver resolver = CreateResolver(context); + object val = expression.Resolve(resolver).ConstantValue; + if (resolver.Context != context) { + // If 'val' is a type or an array containing types, we need to map it to the new context. + val = MapToNewContext(val, context); + } + return val; + } + + static object MapToNewContext(object val, ITypeResolveContext context) + { + IType type = val as IType; + if (type != null) { + return type.AcceptVisitor(new MapTypeIntoNewContext(context)); + } + object[] arr = val as object[]; + if (arr != null) { + object[] newArr = new object[arr.Length]; + bool modified = false; + for (int i = 0; i < arr.Length; i++) { + newArr[i] = MapToNewContext(arr[i], context); + modified |= arr[i] != newArr[i]; + } + if (modified) + return newArr; + } + return val; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return expression.GetHashCode() + ^ (parentUsingScope != null ? parentUsingScope.GetHashCode() : 0) + ^ (parentTypeDefinition != null ? parentTypeDefinition.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + CSharpConstantValue cv = other as CSharpConstantValue; + return cv != null + && expression == cv.expression + && parentUsingScope == cv.parentUsingScope + && parentTypeDefinition == cv.parentTypeDefinition; + } + } + + /// + /// Increments an integer by a fixed amount without changing the type. + /// + public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning + { + IConstantValue baseValue; + int incrementAmount; + + public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1) + { + if (baseValue == null) + throw new ArgumentNullException("baseValue"); + IncrementConstantValue icv = baseValue as IncrementConstantValue; + if (icv != null) { + this.baseValue = icv.baseValue; + this.incrementAmount = icv.incrementAmount + incrementAmount; + } else { + this.baseValue = baseValue; + this.incrementAmount = incrementAmount; + } + } + + public IType GetValueType(ITypeResolveContext context) + { + return baseValue.GetValueType(context); + } + + public object GetValue(ITypeResolveContext context) + { + object val = baseValue.GetValue(context); + if (val == null) + return null; + TypeCode typeCode = Type.GetTypeCode(val.GetType()); + if (!(typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64)) + return null; + long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false); + return CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + baseValue = provider.Intern(baseValue); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return baseValue.GetHashCode() ^ incrementAmount; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + IncrementConstantValue o = other as IncrementConstantValue; + return o != null && baseValue == o.baseValue && incrementAmount == o.incrementAmount; + } + } + + public abstract class ConstantExpression + { + public abstract ResolveResult Resolve(CSharpResolver resolver); + } + + /// + /// C#'s equivalent to the SimpleConstantValue. + /// + public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning + { + ITypeReference type; + object value; + + public ITypeReference Type { + get { return type; } + } + + public object Value { + get { return value; } + } + + public PrimitiveConstantExpression(ITypeReference type, object value) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + this.value = value; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + object val = value; + if (val is ITypeReference) + val = ((ITypeReference)val).Resolve(resolver.Context); + return new ConstantResolveResult(type.Resolve(resolver.Context), val); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + value = provider.Intern(value); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + PrimitiveConstantExpression scv = other as PrimitiveConstantExpression; + return scv != null && type == scv.type && value == scv.value; + } + } + + public sealed class ConstantCast : ConstantExpression, ISupportsInterning + { + ITypeReference targetType; + ConstantExpression expression; + + public ConstantCast(ITypeReference targetType, ConstantExpression expression) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (expression == null) + throw new ArgumentNullException("expression"); + this.targetType = targetType; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveCast(targetType.Resolve(resolver.Context), expression.Resolve(resolver)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + targetType = provider.Intern(targetType); + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return targetType.GetHashCode() + expression.GetHashCode() * 1018829; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantCast cast = other as ConstantCast; + return cast != null + && this.targetType == cast.targetType && this.expression == cast.expression; + } + } + + public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning + { + string identifier; + IList typeArguments; + + public ConstantIdentifierReference(string identifier, IList typeArguments = null) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.typeArguments = typeArguments; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveSimpleName(identifier, ResolveTypes(resolver, typeArguments)); + } + + internal static IList ResolveTypes(CSharpResolver resolver, IList typeArguments) + { + if (typeArguments == null) + return EmptyList.Instance; + IType[] types = new IType[typeArguments.Count]; + for (int i = 0; i < types.Length; i++) { + types[i] = typeArguments[i].Resolve(resolver.Context); + } + return types; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + identifier = provider.Intern(identifier); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hashCode = identifier.GetHashCode(); + if (typeArguments != null) + hashCode ^= typeArguments.GetHashCode(); + return hashCode; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantIdentifierReference cir = other as ConstantIdentifierReference; + return cir != null && + this.identifier == cir.identifier && this.typeArguments == cir.typeArguments; + } + } + + public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning + { + ITypeReference targetType; + ConstantExpression targetExpression; + string memberName; + IList typeArguments; + + public ConstantMemberReference(ITypeReference targetType, string memberName, IList typeArguments = null) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (memberName == null) + throw new ArgumentNullException("memberName"); + this.targetType = targetType; + this.memberName = memberName; + this.typeArguments = typeArguments; + } + + public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList typeArguments = null) + { + if (targetExpression == null) + throw new ArgumentNullException("targetExpression"); + if (memberName == null) + throw new ArgumentNullException("memberName"); + this.targetExpression = targetExpression; + this.memberName = memberName; + this.typeArguments = typeArguments; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + ResolveResult rr; + if (targetType != null) + rr = new TypeResolveResult(targetType.Resolve(resolver.Context)); + else + rr = targetExpression.Resolve(resolver); + return resolver.ResolveMemberAccess(rr, memberName, ConstantIdentifierReference.ResolveTypes(resolver, typeArguments)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + targetType = provider.Intern(targetType); + targetExpression = provider.Intern(targetExpression); + memberName = provider.Intern(memberName); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hashCode; + if (targetType != null) + hashCode = targetType.GetHashCode(); + else + hashCode = targetExpression.GetHashCode(); + hashCode ^= memberName.GetHashCode(); + if (typeArguments != null) + hashCode ^= typeArguments.GetHashCode(); + return hashCode; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantMemberReference cmr = other as ConstantMemberReference; + return cmr != null + && this.targetType == cmr.targetType && this.targetExpression == cmr.targetExpression + && this.memberName == cmr.memberName && this.typeArguments == cmr.typeArguments; + } + } + + public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning + { + bool checkForOverflow; + ConstantExpression expression; + + public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.checkForOverflow = checkForOverflow; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = this.checkForOverflow; + return expression.Resolve(resolver); + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return expression.GetHashCode() ^ (checkForOverflow ? 161851612 : 75163517); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantCheckedExpression cce = other as ConstantCheckedExpression; + return cce != null + && this.expression == cce.expression + && this.checkForOverflow == cce.checkForOverflow; + } + } + + public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning + { + ITypeReference type; + + public ConstantDefaultValue(ITypeReference type) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveDefaultValue(type.Resolve(resolver.Context)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantDefaultValue o = other as ConstantDefaultValue; + return o != null && this.type == o.type; + } + } + + public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning + { + UnaryOperatorType operatorType; + ConstantExpression expression; + + public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.operatorType = operatorType; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return expression.GetHashCode() * 811 + operatorType.GetHashCode(); + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantUnaryOperator uop = other as ConstantUnaryOperator; + return uop != null + && this.operatorType == uop.operatorType + && this.expression == uop.expression; + } + } + + public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning + { + ConstantExpression left; + BinaryOperatorType operatorType; + ConstantExpression right; + + public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right) + { + if (left == null) + throw new ArgumentNullException("left"); + if (right == null) + throw new ArgumentNullException("right"); + this.left = left; + this.operatorType = operatorType; + this.right = right; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + ResolveResult lhs = left.Resolve(resolver); + ResolveResult rhs = right.Resolve(resolver); + return resolver.ResolveBinaryOperator(operatorType, lhs, rhs); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + left = provider.Intern(left); + right = provider.Intern(right); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return left.GetHashCode() * 811 + operatorType.GetHashCode() + right.GetHashCode() * 91781; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantBinaryOperator bop = other as ConstantBinaryOperator; + return bop != null + && this.operatorType == bop.operatorType + && this.left == bop.left && this.right == bop.right; + } + } + + public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning + { + ConstantExpression condition, trueExpr, falseExpr; + + public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr) + { + if (condition == null) + throw new ArgumentNullException("condition"); + if (trueExpr == null) + throw new ArgumentNullException("trueExpr"); + if (falseExpr == null) + throw new ArgumentNullException("falseExpr"); + this.condition = condition; + this.trueExpr = trueExpr; + this.falseExpr = falseExpr; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveConditional( + condition.Resolve(resolver), + trueExpr.Resolve(resolver), + falseExpr.Resolve(resolver) + ); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + condition = provider.Intern(condition); + trueExpr = provider.Intern(trueExpr); + falseExpr = provider.Intern(falseExpr); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return condition.GetHashCode() * 182981713 + + trueExpr.GetHashCode() * 917517169 + + falseExpr.GetHashCode() * 611651; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantConditionalOperator coo = other as ConstantConditionalOperator; + return coo != null + && this.condition == coo.condition + && this.trueExpr == coo.trueExpr + && this.falseExpr == coo.falseExpr; + } + } + + /// + /// Represents an array creation (as used within an attribute argument) + /// + public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning + { + // type may be null when the element is being inferred + ITypeReference type; + IList arrayElements; + + public ConstantArrayCreation(ITypeReference type, IList arrayElements) + { + if (arrayElements == null) + throw new ArgumentNullException("arrayElements"); + this.type = type; + this.arrayElements = arrayElements; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + throw new NotImplementedException(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + arrayElements = provider.InternList(arrayElements); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return (type != null ? type.GetHashCode() : 0) ^ arrayElements.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantArrayCreation cac = other as ConstantArrayCreation; + return cac != null && this.type == cac.type && this.arrayElements == cac.arrayElements; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs index e0be4512aa..3109fb8f8e 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs @@ -3,8 +3,9 @@ using System; using System.Collections.Generic; -using System.Diagnostics; +using System.Linq; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.CSharp.Resolver { @@ -30,9 +31,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { if (resolveResult == null) throw new ArgumentNullException("resolveResult"); - if (resolveResult.IsCompileTimeConstant && (ImplicitEnumerationConversion(resolveResult, toType) || ImplicitConstantExpressionConversion(resolveResult, toType))) + if (resolveResult.IsCompileTimeConstant) { + if (ImplicitEnumerationConversion(resolveResult, toType)) + return true; + if (ImplicitConstantExpressionConversion(resolveResult, toType)) + return true; + } + if (ImplicitConversion(resolveResult.Type, toType)) return true; - return ImplicitConversion(resolveResult.Type, toType); + // TODO: Anonymous function conversions + // TODO: Method group conversions + return false; } public bool ImplicitConversion(IType fromType, IType toType) @@ -46,18 +55,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return true; if (ImplicitNumericConversion(fromType, toType)) return true; - if (ImplicitReferenceConversion(fromType, toType)) - return true; if (ImplicitNullableConversion(fromType, toType)) return true; if (NullLiteralConversion(fromType, toType)) return true; + if (ImplicitReferenceConversion(fromType, toType)) + return true; if (BoxingConversion(fromType, toType)) return true; if (ImplicitDynamicConversion(fromType, toType)) return true; + if (ImplicitTypeParameterConversion(fromType, toType)) + return true; if (ImplicitPointerConversion(fromType, toType)) return true; + if (ImplicitUserDefinedConversion(fromType, toType)) + return true; + return false; + } + + public bool StandardImplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + // C# 4.0 spec: §6.3.1 + if (IdentityConversion(fromType, toType)) + return true; + if (ImplicitNumericConversion(fromType, toType)) + return true; + if (ImplicitNullableConversion(fromType, toType)) + return true; + if (ImplicitReferenceConversion(fromType, toType)) + return true; + if (ImplicitTypeParameterConversion(fromType, toType)) + return true; + if (BoxingConversion(fromType, toType)) + return true; return false; } #endregion @@ -168,7 +203,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §6.1.6 // reference conversions are possible only if both types are known to be reference types - if (fromType.IsReferenceType != true || toType.IsReferenceType != true) + if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) return false; // conversion from null literal is always possible @@ -194,7 +229,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver || ImplicitReferenceConversion(fromArray.ElementType, toPT.TypeArguments[0]); } // conversion from any array to System.Array and the interfaces it implements: - ITypeDefinition systemArray = context.GetClass("System", "Array", 0, StringComparer.Ordinal); + ITypeDefinition systemArray = context.GetTypeDefinition("System", "Array", 0, StringComparer.Ordinal); return systemArray != null && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType)); } @@ -203,7 +238,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // Determines whether s is a subtype of t. - // Helper method used for ImplicitReferenceConversion and BoxingConversion + // Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion bool IsSubtypeOf(IType s, IType t) { // conversion to dynamic + object are always possible @@ -262,7 +297,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §6.1.7 fromType = NullableType.GetUnderlyingType(fromType); - return fromType.IsReferenceType == false && toType.IsReferenceType == true && IsSubtypeOf(fromType, toType); + return fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true && IsSubtypeOf(fromType, toType); } #endregion @@ -304,6 +339,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region ImplicitTypeParameterConversion + /// + /// Implicit conversions involving type parameters. + /// + bool ImplicitTypeParameterConversion(IType fromType, IType toType) + { + ITypeParameter t = fromType as ITypeParameter; + if (t == null) + return false; // not a type parameter + if (t.IsReferenceType(context) == true) + return false; // already handled by ImplicitReferenceConversion + return IsSubtypeOf(t, toType); + } + #endregion + #region ImplicitPointerConversion bool ImplicitPointerConversion(IType fromType, IType toType) { @@ -316,7 +366,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion - // TODO: add support for user-defined conversions + #region ImplicitUserDefinedConversion + bool ImplicitUserDefinedConversion(IType fromType, IType toType) + { + // C# 4.0 spec §6.4.4 User-defined implicit conversions + // Currently we only test whether an applicable implicit conversion exists, + // we do not resolve which conversion is the most specific and gets used. + + // Find the candidate operators: + Predicate opImplicitFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; + var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opImplicitFilter) + .Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opImplicitFilter)); + // Determine whether one of them is applicable: + foreach (IMethod op in operators) { + IType sourceType = op.Parameters[0].Type.Resolve(context); + IType targetType = op.ReturnType.Resolve(context); + // Try if the operator is applicable: + if (StandardImplicitConversion(fromType, sourceType) && StandardImplicitConversion(targetType, toType)) { + return true; + } + // Try if the operator is applicable in lifted form: + if (sourceType.IsReferenceType(context) == false && targetType.IsReferenceType(context) == false) { + IType liftedSourceType = NullableType.Create(sourceType, context); + IType liftedTargetType = NullableType.Create(targetType, context); + if (StandardImplicitConversion(fromType, liftedSourceType) && StandardImplicitConversion(liftedTargetType, toType)) { + return true; + } + } + } + return false; + } + #endregion #region BetterConversion /// diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs new file mode 100644 index 0000000000..14cc7ccb1b --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs @@ -0,0 +1,49 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Converts a type by replacing all type definitions with the equivalent definitions in the new context. + /// + sealed class MapTypeIntoNewContext : TypeVisitor + { + readonly ITypeResolveContext context; + + public MapTypeIntoNewContext(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + } + + public override IType VisitTypeDefinition(ITypeDefinition type) + { + if (type.DeclaringTypeDefinition != null) { + ITypeDefinition decl = type.DeclaringTypeDefinition.AcceptVisitor(this) as ITypeDefinition; + if (decl != null) { + foreach (ITypeDefinition c in decl.NestedTypes) { + if (c.Name == type.Name && c.TypeParameterCount == type.TypeParameterCount) + return c; + } + } + return type; + } else { + return context.GetTypeDefinition(type.Namespace, type.Name, type.TypeParameterCount, StringComparer.Ordinal) ?? type; + } + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + // TODO: how to map type parameters? + // It might have constraints, and those constraints might be mutually recursive. + // Maybe reintroduce ITypeParameter.Owner? + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs index f124141faf..06c1e67bcb 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs @@ -25,9 +25,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec, §7.4 member lookup if (member is IEvent || member is IMethod) return true; - if (member.ReturnType == SharedTypes.Dynamic) + IType returnType = member.ReturnType.Resolve(context); + if (returnType == SharedTypes.Dynamic) return true; - return member.ReturnType.Resolve(context).IsDelegate(); + return returnType.IsDelegate(); } #endregion @@ -66,7 +67,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case Accessibility.None: return false; case Accessibility.Private: - return entity.DeclaringTypeDefinition == currentTypeDefinition; + // check for members of outer classes (private members of outer classes can be accessed) + var lookupTypeDefinition = currentTypeDefinition; + while (lookupTypeDefinition != null) { + if (entity.DeclaringTypeDefinition.Equals (lookupTypeDefinition)) + return true; + lookupTypeDefinition = lookupTypeDefinition.DeclaringTypeDefinition; + } + return false; case Accessibility.Public: return true; case Accessibility.Protected: @@ -91,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool IsProtectedAccessible(ITypeDefinition declaringType) { - if (declaringType == currentTypeDefinition) + if (declaringType.Equals (currentTypeDefinition)) return true; // PERF: this might hurt performance as this method is called several times (once for each member) // make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance @@ -159,7 +167,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (!isInvocation) { // Consider nested types only if it's not an invocation. The type parameter count must match in this case. Predicate typeFilter = delegate (ITypeDefinition d) { - return d.TypeParameterCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); + // inner types contain the type parameters of outer types. therefore this count has to been adjusted. + int correctedCount = d.TypeParameterCount - (d.DeclaringType != null ? d.DeclaringType.TypeParameterCount : 0); + return correctedCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); }; types.AddRange(type.GetNestedTypes(context, typeFilter)); } @@ -170,10 +180,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Predicate memberFilter = delegate(IMember member) { return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess); }; - members.AddRange(type.GetMethods(context, memberFilter.SafeCast()).SafeCast()); - members.AddRange(type.GetProperties(context, memberFilter.SafeCast()).SafeCast()); - members.AddRange(type.GetFields(context, memberFilter.SafeCast()).SafeCast()); - members.AddRange(type.GetEvents(context, memberFilter.SafeCast()).SafeCast()); + members.AddRange(type.GetMembers(context, memberFilter)); if (isInvocation) members.RemoveAll(m => !IsInvocable(m, context)); } else { diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs index 350701a0e0..c6c9e00a43 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -31,6 +31,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.parentUsingScope = parentUsingScope; } + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public MemberTypeOrNamespaceReference AddSuffix(string suffix) + { + return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope); + } + public ResolveResult DoResolve(ITypeResolveContext context) { ResolveResult targetRR = target.DoResolve(context); @@ -48,11 +57,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) { + // TODO: use resolve context for original project, if possible return DoResolve(context) as NamespaceResolveResult; } public IType Resolve(ITypeResolveContext context) { + // TODO: use resolve context for original project, if possible; then map the result type into the new context TypeResolveResult rr = DoResolve(context) as TypeResolveResult; return rr != null ? rr.Type : SharedTypes.UnknownType; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs index d4d1fca43c..e3942491af 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs @@ -259,11 +259,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.TypeArguments[i]; if (tp.HasReferenceTypeConstraint) { - if (typeArg.IsReferenceType != true) + if (typeArg.IsReferenceType(overloadResolution.context) != true) ConstraintsValid = false; } if (tp.HasValueTypeConstraint) { - if (typeArg.IsReferenceType != false) + if (typeArg.IsReferenceType(overloadResolution.context) != false) ConstraintsValid = false; if (NullableType.IsNullable(typeArg)) ConstraintsValid = false; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 1403107ad0..3e10c6016b 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -1,4 +1,4 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -39,7 +39,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType); CSharpResolver resolver; readonly ParsedFile parsedFile; - readonly Dictionary cache = new Dictionary(); + readonly Dictionary resolveResultCache = new Dictionary(); + readonly Dictionary resolverBeforeDict = new Dictionary(); readonly IResolveVisitorNavigator navigator; ResolveVisitorNavigationMode mode = ResolveVisitorNavigationMode.Scan; @@ -95,7 +96,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void Scan(AstNode node) { - if (node == null) + if (node == null || node.IsNull) return; if (mode == ResolveVisitorNavigationMode.ResolveAll) { Resolve(node); @@ -110,6 +111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } break; case ResolveVisitorNavigationMode.Scan: + resolverBeforeDict[node] = resolver.Clone(); node.AcceptVisitor(this, null); break; case ResolveVisitorNavigationMode.Resolve: @@ -117,7 +119,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Resolve(node); break; default: - throw new Exception("Invalid value for ResolveVisitorNavigationMode"); + throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode"); } mode = oldMode; } @@ -125,21 +127,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public ResolveResult Resolve(AstNode node) { - if (node == null) + if (node == null || node.IsNull) return errorResult; bool wasScan = mode == ResolveVisitorNavigationMode.Scan; if (wasScan) mode = ResolveVisitorNavigationMode.Resolve; ResolveResult result; - if (!cache.TryGetValue(node, out result)) { + if (!resolveResultCache.TryGetValue(node, out result)) { resolver.cancellationToken.ThrowIfCancellationRequested(); - result = cache[node] = node.AcceptVisitor(this, null) ?? errorResult; + resolverBeforeDict[node] = resolver.Clone(); + result = resolveResultCache[node] = node.AcceptVisitor(this, null) ?? errorResult; } if (wasScan) mode = ResolveVisitorNavigationMode.Scan; return result; } + protected override ResolveResult VisitChildren(AstNode node, object data) + { + ScanChildren(node); + return null; + } + void ScanChildren(AstNode node) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { @@ -156,11 +165,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public ResolveResult GetResolveResult(AstNode node) { ResolveResult result; - if (cache.TryGetValue(node, out result)) + if (resolveResultCache.TryGetValue(node, out result)) return result; else return null; } + + /// + /// Gets the resolver state in front of the specified node. + /// Returns null if no cached resolver was found (e.g. if the node was skipped by the navigator) + /// + public CSharpResolver GetResolverStateBefore(AstNode node) + { + CSharpResolver r; + if (resolverBeforeDict.TryGetValue(node, out r)) + return r; + else + return null; + } #endregion #region Track UsingScope @@ -199,9 +221,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver try { ITypeDefinition newTypeDefinition = null; if (resolver.CurrentTypeDefinition != null) { - foreach (ITypeDefinition innerClass in resolver.CurrentTypeDefinition.InnerClasses) { - if (innerClass.Region.IsInside(typeDeclaration.StartLocation)) { - newTypeDefinition = innerClass; + foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) { + if (nestedType.Region.IsInside(typeDeclaration.StartLocation)) { + newTypeDefinition = nestedType; break; } } @@ -241,7 +263,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) { - int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count(); + int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; ResolveResult result = null; for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FieldDeclaration.Roles.Variable) { @@ -334,7 +356,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, "value"); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); Scan(node); resolver.PopBlock(); } else { @@ -369,7 +391,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (resolver.CurrentMember != null) { resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, "value"); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); ScanChildren(eventDeclaration); resolver.PopBlock(); } else { @@ -403,6 +425,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + public override ResolveResult VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + { + ScanChildren(typeParameterDeclaration); + if (resolverEnabled) { + string name = typeParameterDeclaration.Name; + IMethod m = resolver.CurrentMember as IMethod; + if (m != null) { + foreach (var tp in m.TypeParameters) { + if (tp.Name == name) + return new TypeResolveResult(tp); + } + } + if (resolver.CurrentTypeDefinition != null) { + var typeParameters = resolver.CurrentTypeDefinition.TypeParameters; + // look backwards so that TPs in the current type take precedence over those copied from outer types + for (int i = typeParameters.Count - 1; i >= 0; i--) { + if (typeParameters[i].Name == name) + return new TypeResolveResult(typeParameters[i]); + } + } + return errorResult; + } else { + return null; + } + } + public override ResolveResult VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) { try { @@ -420,6 +468,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver resolver.CurrentMember = null; } } + + public override ResolveResult VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + { + throw new NotImplementedException(); + } #endregion #region Track CheckForOverflow @@ -497,11 +550,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver throw new NotImplementedException(); } - public override ResolveResult VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr) { - // TODO: ? - ScanChildren(undocumentedExpression); - return new ResolveResult(resolver.Context.GetClass(typeof(RuntimeArgumentHandle)) ?? SharedTypes.UnknownType); + if (expr is NamedArgumentExpression) { + var namedArgExpr = (NamedArgumentExpression)expr; + resolveExpr = namedArgExpr.Expression; + return namedArgExpr.Identifier; + } + // no name given, so it's a projection initializer + if (expr is MemberReferenceExpression) { + resolveExpr = expr; + return ((MemberReferenceExpression)expr).MemberName; + } + if (expr is IdentifierExpression) { + resolveExpr = expr; + return ((IdentifierExpression)expr).Identifier; + } + resolveExpr = null; + return null; + } + + public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + // 7.6.10.6 Anonymous object creation expressions + var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$"); + anonymousType.IsSynthetic = true; + foreach (var expr in anonymousTypeCreateExpression.Initializer) { + Expression resolveExpr; + var name = GetAnonymousTypePropertyName(expr, out resolveExpr); + if (string.IsNullOrEmpty(name)) + continue; + + var property = new DefaultProperty(anonymousType, name) { + Accessibility = Accessibility.Public, + ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false) + }; + anonymousType.Properties.Add(property); + } + return new TypeResolveResult(anonymousType); } public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) @@ -567,9 +653,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { if (resolverEnabled) { - Scan(conditionalExpression.Condition); - return resolver.ResolveConditional(Resolve(conditionalExpression.TrueExpression), - Resolve(conditionalExpression.FalseExpression)); + return resolver.ResolveConditional( + Resolve(conditionalExpression.Condition), + Resolve(conditionalExpression.TrueExpression), + Resolve(conditionalExpression.FalseExpression)); } else { ScanChildren(conditionalExpression); return null; @@ -579,7 +666,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { if (resolverEnabled) { - return new ConstantResolveResult(ResolveType(defaultValueExpression.Type), null); + return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type)); } else { ScanChildren(defaultValueExpression); return null; @@ -597,11 +684,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + public override ResolveResult VisitEmptyExpression(EmptyExpression emptyExpression, object data) + { + return errorResult; + } + public override ResolveResult VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) { if (resolverEnabled) { - // TODO: type arguments? - return resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList.Instance, + List typeArguments = new List(); + foreach (AstType typeArgument in identifierExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments, IsTargetOfInvocation(identifierExpression)); } else { ScanChildren(identifierExpression); @@ -649,7 +744,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitIsExpression(IsExpression isExpression, object data) { ScanChildren(isExpression); - return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); + if (resolverEnabled) + return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); + else + return null; } public override ResolveResult VisitLambdaExpression(LambdaExpression lambdaExpression, object data) @@ -661,10 +759,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { if (resolverEnabled) { ResolveResult target = Resolve(memberReferenceExpression.Target); - List typeArgumentNodes = memberReferenceExpression.TypeArguments.ToList(); - // TODO: type arguments? + List typeArguments = new List(); + foreach (AstType typeArgument in memberReferenceExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } return resolver.ResolveMemberAccess(target, memberReferenceExpression.MemberName, - EmptyList.Instance, + typeArguments, IsTargetOfInvocation(memberReferenceExpression)); } else { ScanChildren(memberReferenceExpression); @@ -706,7 +806,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) { - throw new NotImplementedException(); + if (resolverEnabled) { + ResolveResult target = Resolve(pointerReferenceExpression.Target); + ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target); + List typeArguments = new List(); + foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName, + typeArguments, + IsTargetOfInvocation(pointerReferenceExpression)); + } else { + ScanChildren(pointerReferenceExpression); + return null; + } } public override ResolveResult VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) @@ -755,6 +868,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return null; } + public override ResolveResult VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + if (resolverEnabled) { + return Resolve(typeReferenceExpression.Type); + } else { + Scan(typeReferenceExpression.Type); + return null; + } + } + public override ResolveResult VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { if (resolverEnabled) { @@ -765,6 +888,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return null; } } + + public override ResolveResult VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + { + ScanChildren(undocumentedExpression); + if (resolverEnabled) { + ITypeReference resultType; + switch (undocumentedExpression.UndocumentedExpressionType) { + case UndocumentedExpressionType.ArgListAccess: + case UndocumentedExpressionType.ArgList: + resultType = typeof(RuntimeArgumentHandle).ToTypeReference(); + break; + case UndocumentedExpressionType.RefValue: + var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression; + if (tre != null) + resultType = ResolveType(tre.Type); + else + resultType = SharedTypes.UnknownType; + break; + case UndocumentedExpressionType.RefType: + resultType = systemType; + break; + case UndocumentedExpressionType.MakeRef: + resultType = typeof(TypedReference).ToTypeReference(); + break; + default: + throw new InvalidOperationException("Invalid value for UndocumentedExpressionType"); + } + return new ResolveResult(resultType.Resolve(resolver.Context)); + } else { + return null; + } + } #endregion #region Local Variable Scopes (Block Statements) @@ -787,7 +942,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitFixedStatement(FixedStatement fixedStatement, object data) { resolver.PushBlock(); - ScanChildren(fixedStatement); + + VariableInitializer firstInitializer = fixedStatement.Variables.FirstOrDefault(); + ITypeReference type = MakeTypeReference(fixedStatement.Type, + firstInitializer != null ? firstInitializer.Initializer : null, + false); + + for (AstNode node = fixedStatement.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == FixedStatement.Roles.Variable) { + VariableInitializer vi = (VariableInitializer)node; + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation) , vi.Name); + } + Scan(node); + } resolver.PopBlock(); return null; } @@ -805,123 +972,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { resolver.PushBlock(); ITypeReference type = MakeTypeReference(foreachStatement.VariableType, foreachStatement.InExpression, true); - resolver.AddVariable(type, foreachStatement.VariableName); + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, foreachStatement.VariableNameToken.StartLocation, foreachStatement.VariableNameToken.EndLocation), foreachStatement.VariableName); ScanChildren(foreachStatement); resolver.PopBlock(); return null; } - #endregion - - #region Simple Statements (only ScanChildren) - public override ResolveResult VisitExpressionStatement(ExpressionStatement expressionStatement, object data) - { - ScanChildren(expressionStatement); - return null; - } - - public override ResolveResult VisitBreakStatement(BreakStatement breakStatement, object data) - { - ScanChildren(breakStatement); - return null; - } - - public override ResolveResult VisitContinueStatement(ContinueStatement continueStatement, object data) - { - ScanChildren(continueStatement); - return null; - } - - public override ResolveResult VisitEmptyStatement(EmptyStatement emptyStatement, object data) - { - ScanChildren(emptyStatement); - return null; - } - - public override ResolveResult VisitGotoStatement(GotoStatement gotoStatement, object data) - { - ScanChildren(gotoStatement); - return null; - } - - public override ResolveResult VisitIfElseStatement(IfElseStatement ifElseStatement, object data) - { - ScanChildren(ifElseStatement); - return null; - } - - public override ResolveResult VisitLabelStatement(LabelStatement labelStatement, object data) - { - ScanChildren(labelStatement); - return null; - } - - public override ResolveResult VisitLockStatement(LockStatement lockStatement, object data) - { - ScanChildren(lockStatement); - return null; - } - - public override ResolveResult VisitReturnStatement(ReturnStatement returnStatement, object data) - { - ScanChildren(returnStatement); - return null; - } - - public override ResolveResult VisitSwitchStatement(SwitchStatement switchStatement, object data) - { - ScanChildren(switchStatement); - return null; - } - - public override ResolveResult VisitSwitchSection(SwitchSection switchSection, object data) - { - ScanChildren(switchSection); - return null; - } - - public override ResolveResult VisitCaseLabel(CaseLabel caseLabel, object data) - { - ScanChildren(caseLabel); - return null; - } - - public override ResolveResult VisitThrowStatement(ThrowStatement throwStatement, object data) - { - ScanChildren(throwStatement); - return null; - } - - public override ResolveResult VisitUnsafeStatement(UnsafeStatement unsafeStatement, object data) - { - ScanChildren(unsafeStatement); - return null; - } - - public override ResolveResult VisitWhileStatement(WhileStatement whileStatement, object data) - { - ScanChildren(whileStatement); - return null; - } - - public override ResolveResult VisitYieldStatement(YieldStatement yieldStatement, object data) - { - ScanChildren(yieldStatement); - return null; - } - #endregion - - #region Try / Catch - public override ResolveResult VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) - { - ScanChildren(tryCatchStatement); - return null; - } public override ResolveResult VisitCatchClause(CatchClause catchClause, object data) { resolver.PushBlock(); if (catchClause.VariableName != null) { - resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), catchClause.VariableName); + resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), new DomRegion (parsedFile.FileName, catchClause.VariableNameToken.StartLocation, catchClause.VariableNameToken.EndLocation), catchClause.VariableName); } ScanChildren(catchClause); resolver.PopBlock(); @@ -937,17 +998,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ITypeReference type = MakeTypeReference(variableDeclarationStatement.Type, firstInitializer != null ? firstInitializer.Initializer : null, false); - - int initializerCount = variableDeclarationStatement.Variables.Count(); + + int initializerCount = variableDeclarationStatement.Variables.Count; ResolveResult result = null; for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == FieldDeclaration.Roles.Variable) { + if (node.Role == VariableDeclarationStatement.Roles.Variable) { VariableInitializer vi = (VariableInitializer)node; IConstantValue cv = null; if (isConst) throw new NotImplementedException(); - resolver.AddVariable(type, vi.Name, cv); + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation), vi.Name, cv); if (resolverEnabled && initializerCount == 1) { result = Resolve(node); @@ -1062,14 +1123,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Attributes - public override ResolveResult VisitAttribute(Attribute attribute, object data) - { - throw new NotImplementedException(); + ITypeReference GetAttributeType (Attribute attribute) + { + var withoutSuffix = MakeTypeReference(attribute.Type); + ITypeReference withSuffix; + if (attribute.Type is SimpleType) { + var st = (SimpleType)attribute.Type; + withSuffix = MakeTypeReference(new SimpleType (st.Identifier + "Attribute")); + } else if (attribute.Type is MemberType) { + var mt = (MemberType)attribute.Type; + withSuffix = MakeTypeReference(new MemberType (mt.Target.Clone (), mt.MemberName + "Attribute")); + } else { + // unsupported type. + return SharedTypes.UnknownType; + } + return new AttributeTypeReference(withoutSuffix, withSuffix); } - public override ResolveResult VisitAttributeSection(AttributeSection attributeSection, object data) + public override ResolveResult VisitAttribute(Attribute attribute, object data) { - ScanChildren(attributeSection); + ScanChildren(attribute); + if (resolverEnabled) { + var type = GetAttributeType (attribute).Resolve (resolver.Context); + if (!attribute.HasArgumentList) + return new TypeResolveResult (type); + // try if the attribute usage references a constructuor + string[] argumentNames; + ResolveResult[] arguments = GetArguments(attribute.Arguments, out argumentNames); + var result = resolver.ResolveObjectCreation(type, arguments, argumentNames); + Console.WriteLine (result); + // if this is an error give back type resolve result, an attribute arg list isn't a constructor reference + // in all cases. - is it better to always give back the type resolve result ? + if (result.IsError) + return new TypeResolveResult (type); + return result; + } return null; } #endregion @@ -1077,11 +1165,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #region Using Declaration public override ResolveResult VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) { + // TODO: set isInUsingDeclaration + ScanChildren(usingDeclaration); return null; } public override ResolveResult VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) { + // TODO: set isInUsingDeclaration + ScanChildren(usingDeclaration); return null; } #endregion @@ -1124,70 +1216,50 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Query Expressions - /* - public override ResolveResult VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitQueryExpressionWhereClause(QueryExpressionWhereClause queryExpressionWhereClause, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) + public override ResolveResult VisitQueryExpression(QueryExpression queryExpression, object data) { throw new NotImplementedException(); } + #endregion - public override ResolveResult VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) + public override ResolveResult VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { - throw new NotImplementedException(); + ScanChildren(constructorInitializer); + return null; } - public override ResolveResult VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) + public override ResolveResult VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) { - throw new NotImplementedException(); + // TODO: array initializers are valid expressions if the parent node is a variable/field declaration + // that explicitly defines an array type + return errorResult; } - public override ResolveResult VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) + public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { throw new NotImplementedException(); } - public override ResolveResult VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data) + public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data) { throw new NotImplementedException(); } - */ - #endregion + #region Token Nodes public override ResolveResult VisitIdentifier(Identifier identifier, object data) { return null; } - public override ResolveResult VisitConstraint(Constraint constraint, object data) - { - ScanChildren(constraint); - return null; - } - - public override ResolveResult VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) + public override ResolveResult VisitComment(Comment comment, object data) { - ScanChildren(constructorInitializer); return null; } - public override ResolveResult VisitAccessor(Accessor accessor, object data) + public override ResolveResult VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) { - ScanChildren(accessor); return null; } + #endregion } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs index a500e85e00..12699dd1c0 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -29,6 +29,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.isInUsingDeclaration = isInUsingDeclaration; } + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public SimpleTypeOrNamespaceReference AddSuffix(string suffix) + { + return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); + } + public ResolveResult DoResolve(ITypeResolveContext context) { CSharpResolver r = new CSharpResolver(context); @@ -43,11 +52,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) { + // TODO: use resolve context for original project, if possible return DoResolve(context) as NamespaceResolveResult; } public IType Resolve(ITypeResolveContext context) { + // TODO: use resolve context for original project, if possible; then map the result type into the new context TypeResolveResult rr = DoResolve(context) as TypeResolveResult; return rr != null ? rr.Type : SharedTypes.UnknownType; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs index ced1e1f024..e3c75632e9 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs @@ -511,11 +511,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; ParameterizedType pV = V as ParameterizedType; - if (arrU != null && (arrV != null && arrU.Dimensions == arrV.Dimensions - || IsIEnumerableCollectionOrList(pV) && arrU.Dimensions == 1)) - { + if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { MakeLowerBoundInference(arrU.ElementType, arrV.ElementType); return; + } else if (arrU != null && IsIEnumerableCollectionOrList(pV) && arrU.Dimensions == 1) { + MakeLowerBoundInference(arrU.ElementType, pV.TypeArguments[0]); + return; } // Handle parameterized types: if (pV != null) { @@ -534,7 +535,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { IType Ui = uniqueBaseType.TypeArguments[i]; IType Vi = pV.TypeArguments[i]; - if (Ui.IsReferenceType == true) { + if (Ui.IsReferenceType(context) == true) { // look for variance ITypeParameter Xi = pV.GetDefinition().TypeParameters[i]; switch (Xi.Variance) { @@ -594,11 +595,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; ParameterizedType pU = U as ParameterizedType; - if (arrV != null && (arrU != null && arrU.Dimensions == arrV.Dimensions - || IsIEnumerableCollectionOrList(pU) && arrV.Dimensions == 1)) - { + if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) { MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); return; + } else if (arrV != null && IsIEnumerableCollectionOrList(pU) && arrV.Dimensions == 1) { + MakeUpperBoundInference(pU.TypeArguments[0], arrV.ElementType); + return; } // Handle parameterized types: if (pU != null) { @@ -617,7 +619,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { IType Ui = pU.TypeArguments[i]; IType Vi = uniqueBaseType.TypeArguments[i]; - if (Ui.IsReferenceType == true) { + if (Ui.IsReferenceType(context) == true) { // look for variance ITypeParameter Xi = pU.GetDefinition().TypeParameters[i]; switch (Xi.Variance) { @@ -690,8 +692,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return "X"; } } - public override bool? IsReferenceType { - get { return null; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; } public override int GetHashCode() @@ -831,7 +834,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver candidateTypeDefinitions = hashSet.ToList(); } else { // Find candidates by looking at all classes in the project: - candidateTypeDefinitions = context.GetAllClasses().ToList(); + candidateTypeDefinitions = context.GetAllTypes().ToList(); } // Now filter out candidates that violate the upper bounds: diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs index 315f212ebd..70d88aa164 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.Documentation static string GetRedirectionTarget(string target) { - string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); programFilesDir = AppendDirectorySeparator(programFilesDir); string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 2dd5e0d789..269af85462 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -6,7 +6,7 @@ AnyCPU Library ICSharpCode.NRefactory - newNRefactory + ICSharpCode.NewNRefactory v4.0 Properties 10.0.0 @@ -31,6 +31,7 @@ False DEBUG;TRACE;FULL_AST False + true bin\Release\ @@ -41,7 +42,6 @@ 4 - true 4 @@ -55,9 +55,6 @@ - - Properties\GlobalAssemblyInfo.cs - @@ -100,10 +97,10 @@ - - - - + + + + @@ -115,6 +112,7 @@ + @@ -164,10 +162,20 @@ + + + + + + + + + + @@ -195,6 +203,7 @@ + @@ -241,6 +250,7 @@ + @@ -248,6 +258,7 @@ + @@ -267,6 +278,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -275,6 +334,7 @@ + @@ -284,28 +344,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil - False diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs index ccd8db4993..4e54cff3e2 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs @@ -10,13 +10,13 @@ namespace ICSharpCode.NRefactory.PatternMatching /// public interface INode { - CSharp.Role Role { get; } + Role Role { get; } INode FirstChild { get; } INode NextSibling { get; } bool IsNull { get; } bool DoMatch(INode other, Match match); - bool DoMatchCollection(CSharp.Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo); + bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo); } public static class PatternExtensions diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs index a135a6a58c..b42db0209b 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.PatternMatching { } - public override bool DoMatchCollection(CSharp.Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { backtrackingInfo.backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); return childNode.DoMatch(pos, match); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs index c1fbc7f66c..5553840afb 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.PatternMatching get { return false; } } - CSharp.Role INode.Role { + Role INode.Role { get { return null; } } @@ -43,7 +43,7 @@ namespace ICSharpCode.NRefactory.PatternMatching public abstract bool DoMatch(INode other, Match match); - public virtual bool DoMatchCollection(CSharp.Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + public virtual bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { return DoMatch (pos, match); } @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.PatternMatching return w.ToString(); } - public static bool DoMatchCollection(CSharp.Role role, INode firstPatternChild, INode firstOtherChild, Match match) + public static bool DoMatchCollection(Role role, INode firstPatternChild, INode firstOtherChild, Match match) { BacktrackingInfo backtrackingInfo = new BacktrackingInfo(); Stack patternStack = new Stack(); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs index b6694c814e..249075fe36 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.PatternMatching this.MaxCount = int.MaxValue; } - public override bool DoMatchCollection(CSharp.Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { var backtrackingStack = backtrackingInfo.backtrackingStack; Debug.Assert(pos == null || pos.Role == role); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs index a20a111b02..28987ead7d 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs @@ -10,4 +10,22 @@ using System.Runtime.InteropServices; // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("ICSharpCode.NRefactory")] -[assembly: AssemblyDescription("New NRefactory (NR5); special version for use in SharpDevelop 4.x")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ICSharpCode")] +[assembly: AssemblyProduct("SharpDevelop/MonoDevelop")] +[assembly: AssemblyCopyright("Copyright 2010 AlphaSierraPapa")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/SupportedLanguage.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/SupportedLanguage.cs new file mode 100644 index 0000000000..cc120febd8 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/SupportedLanguage.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory +{ + public enum SupportedLanguage { + CSharp, + //VBNet + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 6e7d27f409..9f42a2ec85 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -31,8 +31,9 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override Nullable IsReferenceType { - get { return true; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; } public override int GetHashCode() @@ -113,7 +114,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public class ArrayTypeReference : ITypeReference, ISupportsInterning + public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning { ITypeReference elementType; int dimensions; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs index 6d457dc2f7..39288f25fd 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -16,8 +16,9 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override Nullable IsReferenceType { - get { return null; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; } public override int GetHashCode() diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 80a5227069..d7765d938d 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -43,8 +43,28 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets/Sets the interning provider. /// public IInterningProvider InterningProvider { get; set; } + + /// + /// Gets a value indicating whether this instance stores references to the cecil objects. + /// + /// + /// true if this instance has references to the cecil objects; otherwise, false. + /// + public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } } #endregion + /// + /// Initializes a new instance of the class. + /// + /// + /// If true references to the cecil objects are hold. In this case the cecil loader can do a type system -> cecil mapping. + /// + public CecilLoader (bool createCecilReferences = false) + { + if (createCecilReferences) + typeSystemTranslationTable = new Dictionary (); + } + #region Load From AssemblyDefinition /// /// Loads the assembly definition into a project content. @@ -90,6 +110,8 @@ namespace ICSharpCode.NRefactory.TypeSystem foreach (CecilTypeDefinition c in types) { c.Init(this); } + if (HasCecilReferences) + typeSystemTranslationTable[pc] = assemblyDefinition; return pc; } finally { this.EarlyBindContext = oldEarlyBindContext; @@ -151,6 +173,17 @@ namespace ICSharpCode.NRefactory.TypeSystem // Disposing the synchronization context has no effect } + public IParsedFile GetFile(string fileName) + { + return null; + } + + public IEnumerable Files { + get { + return EmptyList.Instance; + } + } + string IDocumentationProvider.GetDocumentation(IEntity entity) { if (documentationProvider != null) @@ -168,7 +201,10 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("fileName"); var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() }; AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param); - return LoadAssembly(asm); + var result = LoadAssembly(asm); + if (HasCecilReferences) + typeSystemTranslationTable[result] = asm; + return result; } // used to prevent Cecil from loading referenced assemblies @@ -292,7 +328,7 @@ namespace ICSharpCode.NRefactory.TypeSystem name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); var earlyBindContext = this.EarlyBindContext; if (earlyBindContext != null) { - IType c = earlyBindContext.GetClass(ns, name, typeParameterCount, StringComparer.Ordinal); + IType c = earlyBindContext.GetTypeDefinition(ns, name, typeParameterCount, StringComparer.Ordinal); if (c != null) return c; } @@ -653,7 +689,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #region Read Type Definition sealed class CecilTypeDefinition : DefaultTypeDefinition { - TypeDefinition typeDefinition; + internal TypeDefinition typeDefinition; public CecilTypeDefinition(IProjectContent pc, TypeDefinition typeDefinition) : base(pc, typeDefinition.Namespace, ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name)) @@ -717,8 +753,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } InitMembers(loader); - - this.typeDefinition = null; + if (!loader.HasCecilReferences) + this.typeDefinition = null; Freeze(); // freeze after initialization ApplyInterningProvider(loader.InterningProvider); } @@ -741,11 +777,11 @@ namespace ICSharpCode.NRefactory.TypeSystem if (name.Length == 0 || name[0] == '<') continue; name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); - InnerClasses.Add(new CecilTypeDefinition(this, name, nestedType)); + NestedTypes.Add(new CecilTypeDefinition(this, name, nestedType)); } } - foreach (CecilTypeDefinition innerClass in this.InnerClasses) { - innerClass.Init(loader); + foreach (CecilTypeDefinition nestedType in this.NestedTypes) { + nestedType.Init(loader); } } @@ -908,7 +944,7 @@ namespace ICSharpCode.NRefactory.TypeSystem m.IsExtensionMethod = true; } - FinishReadMember(m); + FinishReadMember(m, method); return m; } @@ -1042,7 +1078,7 @@ namespace ICSharpCode.NRefactory.TypeSystem f.IsVolatile = true; } - FinishReadMember(f); + FinishReadMember(f, field); return f; } @@ -1077,7 +1113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem break; } - tp.HasDefaultConstructorConstraint = g.HasReferenceTypeConstraint; + tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint; tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint; tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint; @@ -1111,7 +1147,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } AddAttributes(property, p); - FinishReadMember(p); + FinishReadMember(p, property); return p; } @@ -1151,15 +1187,69 @@ namespace ICSharpCode.NRefactory.TypeSystem AddAttributes(ev, e); - FinishReadMember(e); + FinishReadMember(e, ev); + return e; } #endregion - void FinishReadMember(AbstractMember member) + void FinishReadMember(AbstractMember member, object cecilDefinition) { member.Freeze(); member.ApplyInterningProvider(this.InterningProvider); + if (HasCecilReferences) + typeSystemTranslationTable[member] = cecilDefinition; + } + + #region Type system translation table + Dictionary typeSystemTranslationTable; + + T InternalGetCecilObject (object typeSystemObject) where T : class + { + if (typeSystemObject == null) + throw new ArgumentNullException ("typeSystemObject"); + if (!HasCecilReferences) + throw new NotSupportedException ("This instance contains no cecil references."); + object result; + if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result)) + throw new InvalidOperationException ("No cecil reference stored for " + typeSystemObject); + return result as T; + } + + public AssemblyDefinition GetCecilObject (IProjectContent content) + { + return InternalGetCecilObject (content); + } + + public TypeDefinition GetCecilObject (ITypeDefinition type) + { + if (type == null) + throw new ArgumentNullException ("type"); + var cecilType = type as CecilTypeDefinition; + if (cecilType == null) + throw new ArgumentException ("type is no cecil type definition."); + return cecilType.typeDefinition; + } + + public MethodDefinition GetCecilObject (IMethod method) + { + return InternalGetCecilObject (method); } + + public FieldDefinition GetCecilObject (IField field) + { + return InternalGetCecilObject (field); + } + + public EventDefinition GetCecilObject (IEvent evt) + { + return InternalGetCecilObject (evt); + } + + public PropertyDefinition GetCecilObject (IProperty property) + { + return InternalGetCecilObject (property); + } + #endregion } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs index b9d31cae61..851b97e90a 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs @@ -60,6 +60,22 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + public AstLocation Begin { + get { + return new AstLocation (beginLine, beginColumn); + } + } + + public AstLocation End { + get { + return new AstLocation (endLine, endColumn); + } + } + + public DomRegion (int beginLine, int beginColumn, int endLine, int endColumn) : this (null, beginLine, beginColumn, endLine, endColumn) + { + } + public DomRegion(string fileName, int beginLine, int beginColumn, int endLine, int endColumn) { this.fileName = fileName; @@ -69,15 +85,45 @@ namespace ICSharpCode.NRefactory.TypeSystem this.endColumn = endColumn; } - public DomRegion(string fileName, int beginLine, int beginColumn) + public DomRegion (int beginLine, int beginColumn) : this (null, beginLine, beginColumn) + { + } + + public DomRegion (string fileName, int beginLine, int beginColumn) { this.fileName = fileName; - this.beginLine = beginLine; + this.beginLine = beginLine; this.beginColumn = beginColumn; this.endLine = -1; this.endColumn = -1; } + public DomRegion (AstLocation begin, AstLocation end) : this (null, begin, end) + { + } + + public DomRegion (string fileName, AstLocation begin, AstLocation end) + { + this.fileName = fileName; + this.beginLine = begin.Line; + this.beginColumn = begin.Column; + this.endLine = end.Line; + this.endColumn = end.Column; + } + + public DomRegion (AstLocation begin) : this (null, begin) + { + } + + public DomRegion (string fileName, AstLocation begin) + { + this.fileName = fileName; + this.beginLine = begin.Line; + this.beginColumn = begin.Column; + this.endLine = -1; + this.endColumn = -1; + } + /// /// Returns true, if the given coordinates (line, column) are in the region. /// This method assumes that for an unknown end the end line is == -1 diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs new file mode 100644 index 0000000000..1684e8d81c --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs @@ -0,0 +1,135 @@ +// +// Error.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Enum that describes the type of an error. + /// + public enum ErrorType + { + Unknown, + Error, + Warning + } + + /// + /// Descibes an error during parsing. + /// + public class Error + { + /// + /// The type of the error. + /// + public ErrorType ErrorType { get; private set; } + + /// + /// The error description. + /// + public string Message { get; private set; } + + /// + /// The region of the error. + /// + public DomRegion Region { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The region of the error. + /// + public Error (ErrorType errorType, string message, DomRegion region) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = region; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The location of the error. + /// + public Error (ErrorType errorType, string message, AstLocation location) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = new DomRegion (location, location); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The line of the error. + /// + /// + /// The column of the error. + /// + public Error (ErrorType errorType, string message, int line, int col) : this (errorType, message, new AstLocation (line, col)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + public Error (ErrorType errorType, string message) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = DomRegion.Empty; + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index da2a6c06af..e2608b812f 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -1,10 +1,13 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; +using ICSharpCode.NRefactory.CSharp.Refactoring; +using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.TypeSystem { @@ -73,7 +76,7 @@ namespace ICSharpCode.NRefactory.TypeSystem Func> recursion = t => t.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)); - ITypeDefinition typeDef = type as ITypeDefinition; + ITypeDefinition typeDef = type.GetDefinition(); if (typeDef != null) { typeDefinitions.Add(typeDef); return TreeTraversal.PreOrder(typeDef, recursion); @@ -185,8 +188,17 @@ namespace ICSharpCode.NRefactory.TypeSystem ITypeDefinition def = type.GetDefinition(); if (def != null && def.ClassType == ClassType.Delegate) { foreach (IMethod method in def.Methods) { - if (method.Name == "Invoke") + if (method.Name == "Invoke") { + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + SpecializedMethod m = new SpecializedMethod(method); + m.SetDeclaringType(pt); + var substitution = pt.GetSubstitution(); + m.SubstituteTypes(t => new SubstitutionTypeReference(t, substitution)); + return m; + } return method; + } } } return null; @@ -208,13 +220,46 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion - #region GetAllClasses + #region GetAllTypes /// - /// Gets all classes, including nested classes. + /// Gets all type definitions, including nested types. /// - public static IEnumerable GetAllClasses(this ITypeResolveContext context) + public static IEnumerable GetAllTypes(this ITypeResolveContext context) { - return TreeTraversal.PreOrder(context.GetClasses(), t => t.InnerClasses); + return TreeTraversal.PreOrder(context.GetTypes(), t => t.NestedTypes); + } + #endregion + + #region GetType/Member + /// + /// Gets the type (potentially a nested type) defined at the specified location. + /// Returns null if no type is defined at that location. + /// + public static ITypeDefinition GetTypeDefinition (this IParsedFile file, int line, int column) + { + return file.GetTypeDefinition (new AstLocation (line, column)); + } + + /// + /// Gets the member defined at the specified location. + /// Returns null if no member is defined at that location. + /// + public static IMember GetMember (this IParsedFile file, int line, int column) + { + return file.GetMember (new AstLocation (line, column)); + } + #endregion + + #region GetSubTypeDefinitions + /// + /// Gets all sub type definitions defined in a context. + /// + public static IEnumerable GetSubTypeDefinitions (this ITypeDefinition baseType, ITypeResolveContext context) + { + foreach (var contextType in context.GetAllTypes ()) { + if (contextType.IsDerivedFrom (baseType, context)) + yield return contextType; + } } #endregion } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs new file mode 100644 index 0000000000..c7f8e7c238 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -0,0 +1,216 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace ICSharpCode.NRefactory +{ + /// + /// Provides an interface to handle annotations in an object. + /// + public interface IAnnotatable + { + /// + /// Gets all annotations stored on this IAnnotatable. + /// + IEnumerable Annotations { + get; + } + + /// + /// Gets the first annotation of the specified type. + /// Returns null if no matching annotation exists. + /// + /// + /// The type of the annotation. + /// + T Annotation () where T: class; + + /// + /// Gets the first annotation of the specified type. + /// Returns null if no matching annotation exists. + /// + /// + /// The type of the annotation. + /// + object Annotation (Type type); + + /// + /// Adds an annotation to this instance. + /// + /// + /// The annotation to add. + /// + void AddAnnotation (object annotation); + + /// + /// Removes all annotations of the specified type. + /// + /// + /// The type of the annotations to remove. + /// + void RemoveAnnotations () where T : class; + + /// + /// Removes all annotations of the specified type. + /// + /// + /// The type of the annotations to remove. + /// + void RemoveAnnotations(Type type); + } + + public abstract class AbstractAnnotatable : IAnnotatable + { + // Annotations: points either null (no annotations), to the single annotation, + // or to an AnnotationList. + // Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list) + protected object annotations; + + sealed class AnnotationList : List, ICloneable + { + // There are two uses for this custom list type: + // 1) it's private, and thus (unlike List) cannot be confused with real annotations + // 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation. + public AnnotationList (int initialCapacity) : base(initialCapacity) + { + } + + public object Clone () + { + lock (this) { + AnnotationList copy = new AnnotationList (this.Count); + for (int i = 0; i < this.Count; i++) { + object obj = this [i]; + ICloneable c = obj as ICloneable; + copy.Add (c != null ? c.Clone () : obj); + } + return copy; + } + } + } + + public virtual void AddAnnotation (object annotation) + { + if (annotation == null) + throw new ArgumentNullException ("annotation"); + retry: // Retry until successful + object oldAnnotation = Interlocked.CompareExchange (ref this.annotations, annotation, null); + if (oldAnnotation == null) { + return; // we successfully added a single annotation + } + AnnotationList list = oldAnnotation as AnnotationList; + if (list == null) { + // we need to transform the old annotation into a list + list = new AnnotationList (4); + list.Add (oldAnnotation); + list.Add (annotation); + if (Interlocked.CompareExchange (ref this.annotations, list, oldAnnotation) != oldAnnotation) { + // the transformation failed (some other thread wrote to this.annotations first) + goto retry; + } + } else { + // once there's a list, use simple locking + lock (list) { + list.Add (annotation); + } + } + } + + public virtual void RemoveAnnotations () where T : class + { + retry: // Retry until successful + object oldAnnotations = this.annotations; + AnnotationList list = oldAnnotations as AnnotationList; + if (list != null) { + lock (list) + list.RemoveAll (obj => obj is T); + } else if (oldAnnotations is T) { + if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) { + // Operation failed (some other thread wrote to this.annotations first) + goto retry; + } + } + } + + public virtual void RemoveAnnotations (Type type) + { + if (type == null) + throw new ArgumentNullException ("type"); + retry: // Retry until successful + object oldAnnotations = this.annotations; + AnnotationList list = oldAnnotations as AnnotationList; + if (list != null) { + lock (list) + list.RemoveAll (obj => type.IsInstanceOfType (obj)); + } else if (type.IsInstanceOfType (oldAnnotations)) { + if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) { + // Operation failed (some other thread wrote to this.annotations first) + goto retry; + } + } + } + + public T Annotation () where T: class + { + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + foreach (object obj in list) { + T t = obj as T; + if (t != null) + return t; + } + return null; + } + } else { + return annotations as T; + } + } + + public object Annotation (Type type) + { + if (type == null) + throw new ArgumentNullException ("type"); + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + foreach (object obj in list) { + if (type.IsInstanceOfType (obj)) + return obj; + } + } + } else { + if (type.IsInstanceOfType (annotations)) + return annotations; + } + return null; + } + + /// + /// Gets all annotations stored on this AstNode. + /// + public IEnumerable Annotations { + get { + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + return list.ToArray (); + } + } else { + if (annotations != null) + return new object[] { annotations }; + else + return Enumerable.Empty (); + } + } + } + } +} + diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs index 42f913f45c..ff6abe9eb6 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs @@ -29,12 +29,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the positional arguments passed to the attribute. /// - IList PositionalArguments { get; } + IList GetPositionalArguments(ITypeResolveContext context); /// /// Gets the named arguments passed to the attribute. /// - IList> NamedArguments { get; } + IList> GetNamedArguments(ITypeResolveContext context); /// /// Resolves the constructor method used for this attribute invocation. @@ -58,18 +58,24 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - IList IAttribute.PositionalArguments { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } + IList IAttribute.GetPositionalArguments(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; } - IList> IAttribute.NamedArguments { - get { - Contract.Ensures(Contract.Result>>() != null); - return null; - } + IList> IAttribute.GetNamedArguments(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>>() != null); + return null; + } + + IMethod IAttribute.ResolveConstructor(ITypeResolveContext context) + { + Contract.Requires(context != null); + return null; } } #endif diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs index d9f92d1cea..74bdec3802 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -68,6 +68,54 @@ namespace ICSharpCode.NRefactory.TypeSystem /// bool IsSynthetic { get; } + /// + /// Gets a value indicating whether this instance is private. + /// + /// + /// true if this instance is private; otherwise, false. + /// + bool IsPrivate { get; } + + /// + /// Gets a value indicating whether this instance is public. + /// + /// + /// true if this instance is public; otherwise, false. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether this instance is protected. + /// + /// + /// true if this instance is protected; otherwise, false. + /// + bool IsProtected { get; } + + /// + /// Gets a value indicating whether this instance is internal. + /// + /// + /// true if this instance is internal; otherwise, false. + /// + bool IsInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected or internal. + /// + /// + /// true if this instance is protected or internal; otherwise, false. + /// + bool IsProtectedOrInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected and internal. + /// + /// + /// true if this instance is protected and internal; otherwise, false. + /// + bool IsProtectedAndInternal { get; } + /// /// The assembly in which this entity is defined. /// This property never returns null. diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs new file mode 100644 index 0000000000..0852028f20 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a single file that was parsed. + /// + public interface IParsedFile : IFreezable + { + /// + /// Gets the parent project content. + /// + IProjectContent ProjectContent { get; } + + /// + /// Returns the full path of the file. + /// + string FileName { get; } + + /// + /// Gets the time of object creation. + /// + DateTime ParseTime { get; } + + /// + /// Gets all top-level type definitions. + /// + IList TopLevelTypeDefinitions { get; } + + /// + /// Gets all assembly attributes that are defined in this file. + /// + IList AssemblyAttributes { get; } + + /// + /// Gets the top-level type defined at the specified location. + /// Returns null if no type is defined at that location. + /// + ITypeDefinition GetTopLevelTypeDefinition(AstLocation location); + + /// + /// Gets the type (potentially a nested type) defined at the specified location. + /// Returns null if no type is defined at that location. + /// + ITypeDefinition GetTypeDefinition(AstLocation location); + + /// + /// Gets the member defined at the specified location. + /// Returns null if no member is defined at that location. + /// + IMember GetMember(AstLocation location); + + /// + /// Gets the parser errors. + /// + IList Errors { get; } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs index be4d9651d7..8485531140 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -13,9 +13,22 @@ namespace ICSharpCode.NRefactory.TypeSystem #if WITH_CONTRACTS [ContractClass(typeof(IProjectContentContract))] #endif - public interface IProjectContent : ITypeResolveContext + public interface IProjectContent : ITypeResolveContext, IAnnotatable { + /// + /// Gets the list of all assembly attributes in the project. + /// IList AssemblyAttributes { get; } + + /// + /// Gets a parsed file by its file name. + /// + IParsedFile GetFile(string fileName); + + /// + /// Gets the list of all parsed files in the project content. + /// + IEnumerable Files { get; } } #if WITH_CONTRACTS @@ -28,6 +41,12 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } } + + IParsedFile IProjectContent.GetFile(string fileName) + { + Contract.Requires(fileName != null); + return; + } } #endif } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs index f6d3b3a32d..6e64bf1204 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -20,7 +20,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// false, if the type is a value type. /// null, if the type is not known (e.g. unconstrained generic type parameter or type not found) /// - bool? IsReferenceType { get; } + /// + /// The resolve context is required for type parameters with a constraint "T : SomeType": + /// the type parameter is a reference type iff SomeType is a class type. + /// + bool? IsReferenceType(ITypeResolveContext context); /// /// Gets the underlying type definition. @@ -90,14 +94,22 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets all events that can be called on this return type. /// IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all members that can be called on this return type. + /// This is the union of GetFields(),GetProperties(),GetMethods() and GetEvents(). This does not include constructors. + /// + IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null); } #if WITH_CONTRACTS [ContractClassFor(typeof(IType))] abstract class ITypeContract : ITypeReferenceContract, IType { - Nullable IType.IsReferenceType { - get { return null; } + bool? IType.IsReferenceType(ITypeResolveContext context) + { + Contract.Requires(context != null); + return null; } int IType.TypeParameterCount { @@ -121,42 +133,49 @@ namespace ICSharpCode.NRefactory.TypeSystem IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); return null; } IEnumerable IType.GetMethods(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); return null; } IEnumerable IType.GetConstructors(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); return null; } IEnumerable IType.GetProperties(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); return null; } IEnumerable IType.GetFields(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); return null; } IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) { Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); return null; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs index ef6568eda1..507d5420d3 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IList GetParts(); - IList InnerClasses { get; } + IList NestedTypes { get; } IList Fields { get; } IList Properties { get; } IList Methods { get; } @@ -128,6 +128,10 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } + bool ITypeDefinition.HasExtensionMethods { + get { return default(bool); } + } + #region IEntity EntityType IEntity.EntityType { get { return EntityType.None; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index 222c06ff10..f9a0cc3cd5 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IList Attributes { get; } /// - /// Gets the contraints of this type parameter. + /// Gets the constraints of this type parameter. /// IList Constraints { get; } @@ -154,6 +154,14 @@ namespace ICSharpCode.NRefactory.TypeSystem void IFreezable.Freeze() { } + + EntityType ITypeParameter.OwnerType { + get { return EntityType.None; } + } + + DomRegion ITypeParameter.Region { + get { return DomRegion.Empty; } + } } #endif } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs index 9cdfb4133d..b1490a653b 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs @@ -18,36 +18,36 @@ namespace ICSharpCode.NRefactory.TypeSystem public interface ITypeResolveContext { /// - /// Retrieves a class. + /// Retrieves a type. /// - /// Namespace that contains the class - /// Name of the class + /// Namespace that contains the type + /// Name of the type /// Number of type parameters /// Language-specific rules for how class names are compared - /// The type definition for the class; or null if no such class exists. - /// This method never returns inner classes; it can be used only with top-level classes. - ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer); + /// The type definition for the class; or null if no such type exists. + /// This method never returns inner types; it can be used only with top-level types. + ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer); /// - /// Retrieves all top-level classes. + /// Retrieves all top-level types. /// /// /// If this method is called within using (pc.Synchronize()), then the returned enumerable is valid /// only until the end of the synchronize block. /// - IEnumerable GetClasses(); + IEnumerable GetTypes(); /// - /// Retrieves all classes in the specified namespace. + /// Retrieves all types in the specified namespace. /// - /// Namespace in which classes are being retrieved. Use string.Empty for the root namespace. + /// Namespace in which types are being retrieved. Use string.Empty for the root namespace. /// Language-specific rules for how namespace names are compared - /// List of classes within that namespace. + /// List of types within that namespace. /// /// If this method is called within using (var spc = pc.Synchronize()), then the returned enumerable is valid /// only until the end of the synchronize block. /// - IEnumerable GetClasses(string nameSpace, StringComparer nameComparer); + IEnumerable GetTypes(string nameSpace, StringComparer nameComparer); /// /// Retrieves all namespaces. @@ -112,13 +112,13 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } - IEnumerable ITypeResolveContext.GetClasses() + IEnumerable ITypeResolveContext.GetTypes() { Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable ITypeResolveContext.GetClasses(string nameSpace, StringComparer nameComparer) + IEnumerable ITypeResolveContext.GetTypes(string nameSpace, StringComparer nameComparer) { Contract.Requires(nameSpace != null); Contract.Requires(nameComparer != null); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs index 5c8f1d9031..b5a0bad882 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs @@ -19,6 +19,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// string Name { get; } + /// + /// Gets the declaration region of the variable. + /// + DomRegion DeclarationRegion { get; } + /// /// Gets the type of the variable. /// diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs index 3f0e0d0837..10ca6ee6e3 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs @@ -63,18 +63,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return new List(inputList); } - protected static IList FreezeList(IList list) where T : IFreezable + protected static ReadOnlyCollection FreezeList(IList list) where T : IFreezable { if (list == null || list.Count == 0) return EmptyList.Instance; - list = new ReadOnlyCollection(list.ToArray()); - foreach (T item in list) { + var result = new ReadOnlyCollection(list.ToArray()); + foreach (T item in result) { item.Freeze(); } - return list; + return result; } - protected static IList FreezeList(IList list) + protected static ReadOnlyCollection FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; @@ -82,7 +82,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return new ReadOnlyCollection(list.ToArray()); } - protected static IList FreezeList(IList list) + protected static ReadOnlyCollection FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs index a514e20a8c..7d5961b9c7 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs @@ -227,6 +227,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + public bool IsPrivate { + get { return Accessibility == Accessibility.Private; } + } + + public bool IsPublic { + get { return Accessibility == Accessibility.Public; } + } + + public bool IsProtected { + get { return Accessibility == Accessibility.Protected; } + } + + public bool IsInternal { + get { return Accessibility == Accessibility.Internal; } + } + + public bool IsProtectedOrInternal { + get { return Accessibility == Accessibility.ProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return Accessibility == Accessibility.ProtectedAndInternal; } + } + public IProjectContent ProjectContent { get { return declaringTypeDefinition.ProjectContent; } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index 9fd926da90..76cc4db1da 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using System.Linq; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { @@ -34,7 +35,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return this.FullName; } } - public abstract bool? IsReferenceType { get; } + public abstract bool? IsReferenceType(ITypeResolveContext context); public virtual int TypeParameterCount { get { return 0; } @@ -89,6 +90,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return EmptyList.Instance; } + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + return GetMethods(context, filter).SafeCast() + .Concat(GetProperties(context, filter).SafeCast()) + .Concat(GetFields(context, filter).SafeCast()) + .Concat(GetEvents(context, filter).SafeCast()); + } + public override bool Equals(object obj) { return Equals(obj as IType); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs index 3d0ca71a1f..d8d9d2319d 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -52,10 +52,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } /// - public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { foreach (ITypeResolveContext context in children) { - ITypeDefinition d = context.GetClass(nameSpace, name, typeParameterCount, nameComparer); + ITypeDefinition d = context.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); if (d != null) return d; } @@ -63,15 +63,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } /// - public IEnumerable GetClasses() + public IEnumerable GetTypes() { - return children.SelectMany(c => c.GetClasses()); + return children.SelectMany(c => c.GetTypes()); } /// - public IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { - return children.SelectMany(c => c.GetClasses(nameSpace, nameComparer)); + return children.SelectMany(c => c.GetTypes(nameSpace, nameComparer)); } /// @@ -93,11 +93,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// public virtual ISynchronizedTypeResolveContext Synchronize() - { - return Synchronize(new CacheManager(), true); - } - - ISynchronizedTypeResolveContext Synchronize(CacheManager cacheManager, bool isTopLevel) { ISynchronizedTypeResolveContext[] sync = new ISynchronizedTypeResolveContext[children.Length]; bool success = false; @@ -107,7 +102,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (sync[i] == null) throw new InvalidOperationException(children[i] + ".ToString() returned null"); } - ISynchronizedTypeResolveContext r = new CompositeSynchronizedTypeResolveContext(sync, cacheManager, isTopLevel); + ISynchronizedTypeResolveContext r = new CompositeSynchronizedTypeResolveContext(sync, new CacheManager(), true); success = true; return r; } finally { @@ -132,7 +127,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation readonly CacheManager cacheManager; readonly bool isTopLevel; - public CompositeSynchronizedTypeResolveContext(ISynchronizedTypeResolveContext[] children, CacheManager cacheManager, bool isTopLevel) + public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, CacheManager cacheManager, bool isTopLevel) : base(children) { Debug.Assert(cacheManager != null); @@ -142,10 +137,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public void Dispose() { - foreach (ISynchronizedTypeResolveContext element in children) { - element.Dispose(); - } if (isTopLevel) { + foreach (ISynchronizedTypeResolveContext element in children) { + element.Dispose(); + } // When the top-level synchronized block is closed, clear any cached data cacheManager.Dispose(); } @@ -160,7 +155,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public override ISynchronizedTypeResolveContext Synchronize() { // re-use the same cache manager for nested synchronized contexts - return base.Synchronize(cacheManager, false); + if (isTopLevel) + return new CompositeSynchronizedTypeResolveContext(children, cacheManager, false); + else + return this; } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs index 8607ffca81..15f8a18158 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs @@ -68,6 +68,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + IList IAttribute.GetPositionalArguments(ITypeResolveContext context) + { + return this.PositionalArguments; + } + public IList> NamedArguments { get { if (namedArguments == null) @@ -76,6 +81,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + IList> IAttribute.GetNamedArguments(ITypeResolveContext context) + { + return this.NamedArguments; + } + public IMethod ResolveConstructor(ITypeResolveContext context) { IType[] parameterTypes = null; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs index 690dba3e59..c4fd96b3e4 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs @@ -41,6 +41,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation constantValue = provider.Intern(constantValue); } + DomRegion IVariable.DeclarationRegion { + get { + return Region; + } + } + public bool IsConst { get { return constantValue != null; } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs index 7ed3cab395..a0c57feda8 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs @@ -36,9 +36,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// protected DefaultMethod(IMethod method) : base(method) { - returnTypeAttributes = CopyList(returnTypeAttributes); - typeParameters = CopyList(typeParameters); - parameters = CopyList(parameters); + returnTypeAttributes = CopyList(method.ReturnTypeAttributes); + typeParameters = CopyList(method.TypeParameters); + parameters = CopyList(method.Parameters); this.IsExtensionMethod = method.IsExtensionMethod; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs index 0f412842d5..08455723e3 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -105,6 +105,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + DomRegion IVariable.DeclarationRegion { + get { + return Region; + } + } + bool HasFlag(byte flag) { return (this.flags & flag) != 0; diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index c707780c42..f9ee9a45ea 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation IList baseTypes; IList typeParameters; - IList innerClasses; + IList nestedTypes; IList fields; IList methods; IList properties; @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { baseTypes = FreezeList(baseTypes); typeParameters = FreezeList(typeParameters); - innerClasses = FreezeList(innerClasses); + nestedTypes = FreezeList(nestedTypes); fields = FreezeList(fields); methods = FreezeList(methods); properties = FreezeList(properties); @@ -113,11 +113,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public IList InnerClasses { + public IList NestedTypes { get { - if (innerClasses == null) - innerClasses = new List(); - return innerClasses; + if (nestedTypes == null) + nestedTypes = new List(); + return nestedTypes; } } @@ -162,19 +162,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public bool? IsReferenceType { - get { - switch (this.ClassType) { - case ClassType.Class: - case ClassType.Interface: - case ClassType.Delegate: - return true; - case ClassType.Enum: - case ClassType.Struct: - return false; - default: - return null; - } + public bool? IsReferenceType(ITypeResolveContext context) + { + switch (this.ClassType) { + case ClassType.Class: + case ClassType.Interface: + case ClassType.Delegate: + return true; + case ClassType.Enum: + case ClassType.Struct: + return false; + default: + return null; } } @@ -313,6 +312,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + public bool IsPrivate { + get { return Accessibility == Accessibility.Private; } + } + + public bool IsPublic { + get { return Accessibility == Accessibility.Public; } + } + + public bool IsProtected { + get { return Accessibility == Accessibility.Protected; } + } + + public bool IsInternal { + get { return Accessibility == Accessibility.Internal; } + } + + public bool IsProtectedOrInternal { + get { return Accessibility == Accessibility.ProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return Accessibility == Accessibility.ProtectedAndInternal; } + } + public bool HasExtensionMethods { get { return flags[FlagHasExtensionMethods]; } set { @@ -353,7 +376,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation primitiveBaseType = typeof(object); break; } - IType t = context.GetClass(primitiveBaseType); + IType t = context.GetTypeDefinition(primitiveBaseType); if (t != null) yield return t; } @@ -369,11 +392,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return new ITypeDefinition[] { this }; } - public IType GetElementType() - { - throw new InvalidOperationException(); - } - public ITypeDefinition GetDefinition() { return this; @@ -404,9 +422,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation break; // there is at most 1 non-interface base } } - foreach (ITypeDefinition innerClass in this.InnerClasses) { - if (filter == null || filter(innerClass)) { - nestedTypes.Add(innerClass); + foreach (ITypeDefinition nestedType in this.NestedTypes) { + if (filter == null || filter(nestedType)) { + nestedTypes.Add(nestedType); } } } @@ -535,6 +553,34 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return events; } + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetMembers(context, filter); + + List members = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + members.AddRange(baseType.GetMembers(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(members); + AddFilteredRange(members, this.Methods.Where(m => !m.IsConstructor), filter); + AddFilteredRange(members, this.Properties, filter); + AddFilteredRange(members, this.Fields, filter); + AddFilteredRange(members, this.Events, filter); + } + } + return members; + } + static void AddFilteredRange(List targetList, IEnumerable sourceList, Predicate filter) where T : class { if (filter == null) { diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs index f1ddcc5c07..ec8ce70079 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -12,7 +12,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// - public class DefaultTypeParameter : AbstractFreezable, ITypeParameter, ISupportsInterning + public sealed class DefaultTypeParameter : AbstractFreezable, ITypeParameter, ISupportsInterning { string name; int index; @@ -71,17 +71,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public bool? IsReferenceType { - get { - switch (flags.Data & (FlagReferenceTypeConstraint | FlagValueTypeConstraint)) { - case FlagReferenceTypeConstraint: - return true; - case FlagValueTypeConstraint: - return false; - default: - return null; + public bool? IsReferenceType(ITypeResolveContext context) + { + switch (flags.Data & (FlagReferenceTypeConstraint | FlagValueTypeConstraint)) { + case FlagReferenceTypeConstraint: + return true; + case FlagValueTypeConstraint: + return false; + } + // protect against cyclic dependencies between type parameters + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + foreach (ITypeReference constraintRef in this.Constraints) { + IType constraint = constraintRef.Resolve(context); + ITypeDefinition constraintDef = constraint.GetDefinition(); + // While interfaces are reference types, an interface constraint does not + // force the type parameter to be a reference type; so we need to explicitly look for classes here. + if (constraintDef != null && constraintDef.ClassType == ClassType.Class) + return true; + if (constraint is ITypeParameter) { + bool? isReferenceType = constraint.IsReferenceType(context); + if (isReferenceType.HasValue) + return isReferenceType.Value; + } + } } } + return null; } int IType.TypeParameterCount { @@ -188,11 +204,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public virtual IType BoundTo { + IType ITypeParameter.BoundTo { get { return null; } } - public virtual ITypeParameter UnboundTypeParameter { + ITypeParameter ITypeParameter.UnboundTypeParameter { get { return null; } } @@ -234,31 +250,86 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) { - // TODO: get methods from constraints - IType objectType = context.GetClass("System", "Object", 0, StringComparer.Ordinal); - IEnumerable objectMethods; - if (objectType != null) - objectMethods = objectType.GetMethods(context, filter); - else - objectMethods = EmptyList.Instance; - - // don't return static methods (those cannot be called from type parameter) - return objectMethods.Where(m => !m.IsStatic); + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetMethods(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } } public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) { - return EmptyList.Instance; + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetProperties(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } } public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) { - return EmptyList.Instance; + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetFields(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } } public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) { - return EmptyList.Instance; + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetEvents(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetMembers(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + // Problem with type parameter resolving - circular declarations + // void Example (S s, T t) where S : T where T : S + IEnumerable GetNonCircularBaseTypes(ITypeResolveContext context) + { + var result = this.GetBaseTypes(context).Where(bt => !IsCircular (context, bt)); + if (result.Any ()) + return result; + + // result may be empty, GetBaseTypes doesn't return object/struct when there are only constraints (even circular) as base types are available, + // but even when there are only circular references the default base type should be included. + IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); + if (defaultBaseType != null) + return new [] { defaultBaseType }; + return Enumerable.Empty (); + } + + bool IsCircular(ITypeResolveContext context, IType baseType) + { + var parameter = baseType as DefaultTypeParameter; + if (parameter == null) + return false; + var stack = new Stack(); + while (true) { + if (parameter == this) + return true; + foreach (DefaultTypeParameter parameterBaseType in parameter.GetNonCircularBaseTypes(context).Where(t => t is DefaultTypeParameter)) { + stack.Push(parameterBaseType); + } + if (stack.Count == 0) + return false; + parameter = stack.Pop(); + } } IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) @@ -268,12 +339,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable GetBaseTypes(ITypeResolveContext context) { - IType defaultBaseType = context.GetClass("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); - if (defaultBaseType != null) - yield return defaultBaseType; - + bool hasNonInterfaceConstraint = false; foreach (ITypeReference constraint in this.Constraints) { - yield return constraint.Resolve(context); + IType c = constraint.Resolve(context); + yield return c; + ITypeDefinition cdef = c.GetDefinition(); + if (!(cdef != null && cdef.ClassType == ClassType.Interface)) + hasNonInterfaceConstraint = true; + } + // Do not add the 'System.Object' constraint if there is another constraint with a base class. + if (HasValueTypeConstraint || !hasNonInterfaceConstraint) { + IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); + if (defaultBaseType != null) + yield return defaultBaseType; } } @@ -301,7 +379,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { DefaultTypeParameter o = other as DefaultTypeParameter; - return o != null + return o != null && this.attributes == o.attributes && this.constraints == o.constraints && this.flags == o.flags diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs index 8f2b704418..976b90ca5c 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation IType DoResolve(ITypeResolveContext context) { */ - return context.GetClass(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + return context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; } public override string ToString() diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs index 5146309b12..856b7aa63a 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ITypeDefinition declaringType = declaringTypeRef.Resolve(context) as ITypeDefinition; if (declaringType != null) { int tpc = declaringType.TypeParameterCount; - foreach (IType type in declaringType.InnerClasses) { + foreach (IType type in declaringType.NestedTypes) { if (type.Name == name && type.TypeParameterCount == tpc + additionalTypeParameterCount) return type; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs index f8677c2969..4876c1e5cd 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -10,7 +10,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Proxy that forwards calls to another TypeResolveContext. /// Useful as base class for decorators. /// - public class ProxyTypeResolveContext : ITypeResolveContext + public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext { protected readonly ITypeResolveContext target; @@ -25,21 +25,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } /// - public virtual ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public virtual ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { - return target.GetClass(nameSpace, name, typeParameterCount, nameComparer); + return target.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); } /// - public virtual IEnumerable GetClasses() + public virtual IEnumerable GetTypes() { - return target.GetClasses(); + return target.GetTypes(); } /// - public virtual IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public virtual IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { - return target.GetClasses(nameSpace, nameComparer); + return target.GetTypes(nameSpace, nameComparer); } /// diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs index 3a7f5caa90..6cb78cbfaa 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -19,7 +19,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Compared with , this class adds support for the IProjectContent interface, /// for partial classes, and for multi-threading. /// - public sealed class SimpleProjectContent : IProjectContent + public sealed class SimpleProjectContent : AbstractAnnotatable, IProjectContent { // This class is sealed by design: // the synchronization story doesn't mix well with someone trying to extend this class. @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation readonly TypeStorage types = new TypeStorage(); readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); + readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer); #region AssemblyAttributes readonly List assemblyAttributes = new List(); // mutable assembly attribute storage @@ -35,13 +36,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// public IList AssemblyAttributes { - get { return readOnlyAssemblyAttributes; } + get { return readOnlyAssemblyAttributes; } } - void AddRemoveAssemblyAttributes(ICollection addedAttributes, ICollection removedAttributes) + void AddRemoveAssemblyAttributes(ICollection removedAttributes, ICollection addedAttributes) { // API uses ICollection instead of IEnumerable to discourage users from evaluating // the list inside the lock (this method is called inside the write lock) + // [[not an issue anymore; the user now passes IParsedFile]] bool hasChanges = false; if (removedAttributes != null && removedAttributes.Count > 0) { if (assemblyAttributes.RemoveAll(removedAttributes.Contains) > 0) @@ -74,37 +76,41 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #region RemoveType void RemoveType(ITypeDefinition typeDefinition) { - throw new NotImplementedException(); + types.RemoveType (typeDefinition); // <- Daniel: Correct ? } #endregion #region UpdateProjectContent /// - /// Removes oldTypes from the project, adds newTypes. - /// Removes oldAssemblyAttributes, adds newAssemblyAttributes. + /// Removes types and attributes from oldFile from the project, and adds those from newFile. /// /// /// The update is done inside a write lock; when other threads access this project content /// from within a using (Synchronize()) block, they will not see intermediate (inconsistent) state. /// - public void UpdateProjectContent(ICollection oldTypes = null, - ICollection newTypes = null, - ICollection oldAssemblyAttributes = null, - ICollection newAssemblyAttributes = null) + public void UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) { + if (oldFile != null && newFile != null) { + if (!Platform.FileNameComparer.Equals(oldFile.FileName, newFile.FileName)) + throw new ArgumentException("When both oldFile and newFile are specified, they must use the same file name."); + } readerWriterLock.EnterWriteLock(); try { - if (oldTypes != null) { - foreach (var element in oldTypes) { + if (oldFile != null) { + foreach (var element in oldFile.TopLevelTypeDefinitions) { RemoveType(element); } + if (newFile == null) { + fileDict.Remove(oldFile.FileName); + } } - if (newTypes != null) { - foreach (var element in newTypes) { + if (newFile != null) { + foreach (var element in newFile.TopLevelTypeDefinitions) { AddType(element); } + fileDict[newFile.FileName] = newFile; } - AddRemoveAssemblyAttributes(oldAssemblyAttributes, newAssemblyAttributes); + AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, newFile != null ? newFile.AssemblyAttributes : null); } finally { readerWriterLock.ExitWriteLock(); } @@ -112,33 +118,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region IProjectContent implementation - public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { readerWriterLock.EnterReadLock(); try { - return types.GetClass(nameSpace, name, typeParameterCount, nameComparer); + return types.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); } finally { readerWriterLock.ExitReadLock(); } } - public IEnumerable GetClasses() + public IEnumerable GetTypes() { readerWriterLock.EnterReadLock(); try { // make a copy with ToArray() for thread-safe access - return types.GetClasses().ToArray(); + return types.GetTypes().ToArray(); } finally { readerWriterLock.ExitReadLock(); } } - public IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { readerWriterLock.EnterReadLock(); try { // make a copy with ToArray() for thread-safe access - return types.GetClasses(nameSpace, nameComparer).ToArray(); + return types.GetTypes(nameSpace, nameComparer).ToArray(); } finally { readerWriterLock.ExitReadLock(); } @@ -164,6 +170,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation readerWriterLock.ExitReadLock(); } } + + public IParsedFile GetFile(string fileName) + { + readerWriterLock.EnterReadLock(); + try { + IParsedFile file; + if (fileDict.TryGetValue(fileName, out file)) + return file; + else + return null; + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IEnumerable Files { + get { + readerWriterLock.EnterReadLock(); + try { + return fileDict.Values.ToArray(); + } finally { + readerWriterLock.ExitReadLock(); + } + } + } #endregion #region Synchronization diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs index d55da252b2..9d76f93e26 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs @@ -52,20 +52,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return false; return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); } - + /// /// Performs type substitution in parameter types and in the return type. /// - public void SubstituteTypes(ITypeResolveContext context, TypeVisitor substitution) + public void SubstituteTypes(Func substitution) { - this.ReturnType = this.ReturnType.Resolve(context).AcceptVisitor(substitution); + this.ReturnType = substitution(this.ReturnType); var p = this.Parameters; for (int i = 0; i < p.Count; i++) { - IType newType = p[i].Type.Resolve(context).AcceptVisitor(substitution); + ITypeReference newType = substitution(p[i].Type); if (newType != p[i].Type) { p[i] = new DefaultParameter(p[i]) { Type = newType }; } } + // TODO: we might also have to perform substitution within the method's constraints } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs index deb9b0c588..921ffc0299 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs @@ -56,12 +56,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Performs type substitution in parameter types and in the return type. /// - public void SubstituteTypes(ITypeResolveContext context, TypeVisitor substitution) + public void SubstituteTypes(Func substitution) { - this.ReturnType = this.ReturnType.Resolve(context).AcceptVisitor(substitution); + this.ReturnType = substitution(this.ReturnType); var p = this.Parameters; for (int i = 0; i < p.Count; i++) { - IType newType = p[i].Type.Resolve(context).AcceptVisitor(substitution); + ITypeReference newType = substitution(p[i].Type); if (newType != p[i].Type) { p[i] = new DefaultParameter(p[i]) { Type = newType }; } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs new file mode 100644 index 0000000000..aaf38718c9 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// A type reference that wraps another type reference; but performs a substitution in the resolved type. + /// + public class SubstitutionTypeReference : ITypeReference + { + readonly ITypeReference baseTypeReference; + readonly TypeVisitor substitution; + + public SubstitutionTypeReference(ITypeReference baseTypeReference, TypeVisitor substitution) + { + if (baseTypeReference == null) + throw new ArgumentNullException("baseTypeReference"); + if (substitution == null) + throw new ArgumentNullException("substitution"); + this.baseTypeReference = baseTypeReference; + this.substitution = substitution; + } + + public IType Resolve(ITypeResolveContext context) + { + return baseTypeReference.Resolve(context).AcceptVisitor(substitution); + } + } +} diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs index aa05ee8d75..d5f2842952 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public bool Equals(FullNameAndTypeParameterCount x, FullNameAndTypeParameterCount y) { - return x.TypeParameterCount == y.TypeParameterCount + return x.TypeParameterCount == y.TypeParameterCount && NameComparer.Equals(x.Name, y.Name) && NameComparer.Equals(x.Namespace, y.Namespace); } @@ -110,11 +110,32 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #region Namespace Storage class NamespaceEntry { + /// + /// Full namespace name + /// public readonly string Name; + + /// + /// Parent namespace + /// + public readonly NamespaceEntry Parent; + + /// + /// Number of classes in this namespace (not in sub-namespaces). + /// Note: this always refers to the number of classes from the ordinal typeDict that map + /// to this namespace when compared with the appropriate StringComparer. + /// The actual number of classes in the typeDict matching this StringComparer might be lower. + /// public int ClassCount; - public NamespaceEntry(string name) + /// + /// Number of sub-namespaces. + /// + public int SubNamespaceCount; + + public NamespaceEntry(NamespaceEntry parent, string name) { + this.Parent = parent; this.Name = name; } } @@ -145,9 +166,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } // now create new dict - var newDict = _typeDicts[0].Values.GroupBy(c => c.Namespace, nameComparer) - .Select(g => new NamespaceEntry(g.Key) { ClassCount = g.Count() }) - .ToDictionary(d => d.Name); + var newDict = new Dictionary(nameComparer); + foreach (ITypeDefinition type in _typeDicts[0].Values) { + NamespaceEntry ne = GetOrCreateNamespaceEntry(newDict, type.Namespace); + ne.ClassCount++; + } // add the new dict to the array of dicts var newNamespaceDicts = new Dictionary[namespaceDicts.Length + 1]; @@ -157,11 +180,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return newDict; } } + + NamespaceEntry GetOrCreateNamespaceEntry(Dictionary dict, string ns) + { + NamespaceEntry ne; + if (!dict.TryGetValue(ns, out ne)) { + NamespaceEntry parentEntry; + if (string.IsNullOrEmpty(ns)) { + parentEntry = null; + } else { + int pos = ns.LastIndexOf('.'); + string parentNS = pos < 0 ? string.Empty : ns.Substring(0, pos); + parentEntry = GetOrCreateNamespaceEntry(dict, parentNS); + parentEntry.SubNamespaceCount++; + } + ne = new NamespaceEntry(parentEntry, ns); + dict.Add(ns, ne); + } + return ne; + } #endregion #region ITypeResolveContext implementation /// - public ITypeDefinition GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { if (nameSpace == null) throw new ArgumentNullException("nameSpace"); @@ -179,19 +221,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } /// - public IEnumerable GetClasses() + public IEnumerable GetTypes() { return _typeDicts[0].Values; } /// - public IEnumerable GetClasses(string nameSpace, StringComparer nameComparer) + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) { if (nameSpace == null) throw new ArgumentNullException("nameSpace"); if (nameComparer == null) throw new ArgumentNullException("nameComparer"); - return GetClasses().Where(c => nameComparer.Equals(nameSpace, c.Namespace)); + return GetTypes().Where(c => nameComparer.Equals(nameSpace, c.Namespace)); } /// @@ -248,7 +290,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ITypeDefinition defInDict; if (dict.TryGetValue(key, out defInDict)) { if (defInDict == typeDefinition) { - wasRemoved = true; + if (dict.Comparer == FullNameAndTypeParameterCountComparer.Ordinal) { + // Set wasRemoved flag only on removal in the ordinal comparison. + // This keeps the ClassCount consistent when there are name clashes. + wasRemoved = true; + } dict.Remove(key); } } @@ -257,12 +303,23 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation foreach (var dict in _namespaceDicts) { NamespaceEntry ns; if (dict.TryGetValue(typeDefinition.Namespace, out ns)) { - if (--ns.ClassCount == 0) - dict.Remove(typeDefinition.Namespace); + ns.ClassCount--; + RemoveNamespaceIfPossible(dict, ns); } } } } + + void RemoveNamespaceIfPossible(Dictionary dict, NamespaceEntry ns) + { + while (ns.ClassCount == 0 && ns.SubNamespaceCount == 0) { + dict.Remove(ns.Name); + ns = ns.Parent; + if (ns == null) + break; + ns.SubNamespaceCount--; + } + } #endregion #region UpdateType @@ -275,18 +332,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (typeDefinition == null) throw new ArgumentNullException("typeDefinition"); var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount); + // Set isNew on addition in the ordinal comparison. + // This keeps the ClassCount consistent when there are name clashes. bool isNew = !_typeDicts[0].ContainsKey(key); foreach (var dict in _typeDicts) { dict[key] = typeDefinition; } if (isNew) { foreach (var dict in _namespaceDicts) { - NamespaceEntry ns; - if (dict.TryGetValue(typeDefinition.Namespace, out ns)) { - ++ns.ClassCount; - } else { - dict.Add(typeDefinition.Namespace, new NamespaceEntry(typeDefinition.Namespace) { ClassCount = 1 }); - } + NamespaceEntry ns = GetOrCreateNamespaceEntry(dict, typeDefinition.Namespace); + ++ns.ClassCount; } } } diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index c23431a2b8..688dc38932 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -63,8 +63,14 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override Nullable IsReferenceType { - get { return null; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + foreach (var t in types) { + bool? isReferenceType = t.IsReferenceType(context); + if (isReferenceType.HasValue) + return isReferenceType.Value; + } + return null; } public override int GetHashCode() diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs index 6f2fd7165a..11809396eb 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs @@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (context == null) throw new ArgumentNullException("context"); - ITypeDefinition nullable = context.GetClass("System", "Nullable", 1, StringComparer.Ordinal); + ITypeDefinition nullable = context.GetTypeDefinition("System", "Nullable", 1, StringComparer.Ordinal); if (nullable != null) return new ParameterizedType(nullable, new [] { elementType }); else diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index f51fb1ea8a..a75fb7c217 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -78,8 +78,9 @@ namespace ICSharpCode.NRefactory.TypeSystem this.typeArguments = typeArguments; } - public bool? IsReferenceType { - get { return genericType.IsReferenceType; } + public bool? IsReferenceType(ITypeResolveContext context) + { + return genericType.IsReferenceType(context); } public IType DeclaringType { @@ -156,6 +157,15 @@ namespace ICSharpCode.NRefactory.TypeSystem return type.AcceptVisitor(new Substitution(typeArguments)); } + /// + /// Gets a type visitor that performs the substitution of class type parameters with the type arguments + /// of this parameterized type. + /// + public TypeVisitor GetSubstitution() + { + return new Substitution(typeArguments); + } + public IEnumerable GetBaseTypes(ITypeResolveContext context) { Substitution substitution = new Substitution(typeArguments); @@ -183,7 +193,7 @@ namespace ICSharpCode.NRefactory.TypeSystem // (partially) parameterize the nested type definition IType[] newTypeArgs = new IType[def.TypeParameterCount]; for (int j = 0; j < newTypeArgs.Length; j++) { - if (j < typeArguments.Length) + if (i < typeArguments.Length) newTypeArgs[j] = typeArguments[i]; else newTypeArgs[j] = def.TypeParameters[j]; @@ -199,11 +209,12 @@ namespace ICSharpCode.NRefactory.TypeSystem public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) { Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); List methods = genericType.GetMethods(context, filter).ToList(); for (int i = 0; i < methods.Count; i++) { SpecializedMethod m = new SpecializedMethod(methods[i]); m.SetDeclaringType(this); - m.SubstituteTypes(context, substitution); + m.SubstituteTypes(substitutionFunc); methods[i] = m; } return methods; @@ -212,11 +223,12 @@ namespace ICSharpCode.NRefactory.TypeSystem public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) { Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); List methods = genericType.GetConstructors(context, filter).ToList(); for (int i = 0; i < methods.Count; i++) { SpecializedMethod m = new SpecializedMethod(methods[i]); m.SetDeclaringType(this); - m.SubstituteTypes(context, substitution); + m.SubstituteTypes(substitutionFunc); methods[i] = m; } return methods; @@ -225,11 +237,12 @@ namespace ICSharpCode.NRefactory.TypeSystem public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) { Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); List properties = genericType.GetProperties(context, filter).ToList(); for (int i = 0; i < properties.Count; i++) { SpecializedProperty p = new SpecializedProperty(properties[i]); p.SetDeclaringType(this); - p.SubstituteTypes(context, substitution); + p.SubstituteTypes(substitutionFunc); properties[i] = p; } return properties; @@ -261,6 +274,50 @@ namespace ICSharpCode.NRefactory.TypeSystem return events; } + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + List members = genericType.GetMembers(context, filter).ToList(); + for (int i = 0; i < members.Count; i++) { + members[i] = Specialize(members[i], substitutionFunc); + } + return members; + } + + IMember Specialize(IMember member, Func substitution) + { + IMethod method = member as IMethod; + if (method != null) { + SpecializedMethod m = new SpecializedMethod(method); + m.SetDeclaringType(this); + m.SubstituteTypes(substitution); + return m; + } + IProperty property = member as IProperty; + if (property != null) { + SpecializedProperty p = new SpecializedProperty(property); + p.SetDeclaringType(this); + p.SubstituteTypes(substitution); + return p; + } + IField field = member as IField; + if (field != null) { + SpecializedField f = new SpecializedField(field); + f.SetDeclaringType(this); + f.ReturnType = substitution(f.ReturnType); + return f; + } + IEvent ev = member as IEvent; + if (ev != null) { + SpecializedEvent e = new SpecializedEvent(ev); + e.SetDeclaringType(this); + e.ReturnType = substitution(e.ReturnType); + return e; + } + throw new ArgumentException("Unknown member"); + } + public override bool Equals(object obj) { return Equals(obj as IType); diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs index 12b4736201..692e814793 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -18,8 +18,9 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override Nullable IsReferenceType { - get { return null; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; } public override int GetHashCode() diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs index 61b22bc7b6..7decbb8004 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -23,12 +23,16 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public sealed class Dynamic {} - #region ITypeResolveContext.GetClass(Type) + #region ITypeResolveContext.GetTypeDefinition(Type) /// - /// Retrieves a class. + /// Retrieves a type definition. /// - /// Returns the class; or null if it is not found. - public static ITypeDefinition GetClass(this ITypeResolveContext context, Type type) + /// Returns the type definition; or null if it is not found. + /// + /// This method retrieves the type definition; consider using type.ToTypeReference().Resolve(context) instead + /// if you need an . + /// + public static ITypeDefinition GetTypeDefinition(this ITypeResolveContext context, Type type) { if (type == null) return null; @@ -39,14 +43,14 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type.IsGenericParameter) return null; if (type.DeclaringType != null) { - ITypeDefinition declaringType = GetClass(context, type.DeclaringType); + ITypeDefinition declaringType = GetTypeDefinition(context, type.DeclaringType); if (declaringType != null) { int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); typeParameterCount += declaringType.TypeParameterCount; - foreach (ITypeDefinition innerClass in declaringType.InnerClasses) { - if (innerClass.Name == name && innerClass.TypeParameterCount == typeParameterCount) { - return innerClass; + foreach (ITypeDefinition nestedType in declaringType.NestedTypes) { + if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount) { + return nestedType; } } } @@ -54,7 +58,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } else { int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - return context.GetClass(type.Namespace, name, typeParameterCount, StringComparer.Ordinal); + return context.GetTypeDefinition(type.Namespace, name, typeParameterCount, StringComparer.Ordinal); } } #endregion diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs index 6c8cf7eafb..f72e5fc15e 100644 --- a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs @@ -57,8 +57,9 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return "?"; } } - public override bool? IsReferenceType { - get { return null; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; } public override bool Equals(IType other) @@ -81,8 +82,9 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return "null"; } } - public override bool? IsReferenceType { - get { return true; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; } public override bool Equals(IType other) @@ -105,8 +107,9 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return "dynamic"; } } - public override bool? IsReferenceType { - get { return true; } + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; } public override bool Equals(IType other) diff --git a/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Utils/Platform.cs b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Utils/Platform.cs new file mode 100644 index 0000000000..1e512330d4 --- /dev/null +++ b/src/Libraries/NewNRefactory/ICSharpCode.NRefactory/Utils/Platform.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Platform-specific code. + /// + static class Platform + { + public static StringComparer FileNameComparer { + get { + switch (Environment.OSVersion.Platform) { + case PlatformID.Unix: + case PlatformID.MacOSX: + return StringComparer.Ordinal; + default: + return StringComparer.OrdinalIgnoreCase; + } + } + } + } +} diff --git a/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs b/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs index 28d57bcc19..4d0ead5521 100644 --- a/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs +++ b/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs @@ -21,6 +21,8 @@ namespace ICSharpCode.SharpDevelop.Bookmarks /// Redraws the bookmark margin. Bookmarks need to call this method when the Image changes. /// void Redraw(); + + event EventHandler RedrawRequested; } /// diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs index d4047b6e4a..9aa41fc6c7 100644 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs +++ b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs @@ -140,7 +140,8 @@ namespace ICSharpCode.SharpDevelop.Bookmarks void BookmarkManagerRemoved(object sender, BookmarkEventArgs e) { - listView.Remove(new ListViewPadItemModel(e.Bookmark)); + if (ShowBookmarkInThisPad(e.Bookmark)) + listView.Remove(new ListViewPadItemModel(e.Bookmark)); } void listView_ItemActivated(object sender, EventArgs e) diff --git a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs index 3502189916..9682faaaf0 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs @@ -3,6 +3,7 @@ using System; using System.Windows.Media; +using ICSharpCode.AvalonEdit.Document; using ICSharpCode.Core; using ICSharpCode.NRefactory; using ICSharpCode.SharpDevelop.Bookmarks; @@ -23,14 +24,21 @@ namespace ICSharpCode.SharpDevelop.Debugging public static void SetPosition(IViewContent viewContent, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn) { ITextEditorProvider tecp = viewContent as ITextEditorProvider; - if (tecp != null) + if (tecp != null) { SetPosition(tecp.TextEditor.FileName, tecp.TextEditor.Document, makerStartLine, makerStartColumn, makerEndLine, makerEndColumn); - else - Remove(); + } else { + dynamic codeView = viewContent.Control; + SetPosition(null, codeView.TextEditor.Document as IDocument, makerStartLine, makerStartColumn, makerEndLine, makerEndColumn); + codeView.IconBarManager.Bookmarks.Add(CurrentLineBookmark.instance); + codeView.UnfoldAndScroll(makerStartLine); + CurrentLineBookmark.instance.Document = codeView.TextEditor.Document as IDocument; + } } public static void SetPosition(FileName fileName, IDocument document, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn) { + if (document == null) + return; Remove(); startLine = makerStartLine; diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs index 55c60abe1d..6dc440d0ad 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Text; using System.Windows.Forms; + using ICSharpCode.Core; using ICSharpCode.NRefactory; using ICSharpCode.SharpDevelop.Bookmarks; @@ -13,6 +15,7 @@ using ICSharpCode.SharpDevelop.Dom.VBNet; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; +using Mono.Cecil; namespace ICSharpCode.SharpDevelop.Debugging { @@ -98,6 +101,21 @@ namespace ICSharpCode.SharpDevelop.Debugging get { return debuggerStarted; } } + #region Debug third party code + + /// + /// Gets or sets the external debug information. + /// This constains the code mappings and local variables. + /// + public static object ExternalDebugInformation { get; set; } + + /// + /// Gets or sets the current token and IL offset. Used for step in/out. + /// + public static Tuple DebugStepInformation { get; set; } + + #endregion + public static event EventHandler DebugStarting; public static event EventHandler DebugStarted; public static event EventHandler DebugStopped; @@ -264,9 +282,18 @@ namespace ICSharpCode.SharpDevelop.Debugging return; Location logicPos = e.LogicalPosition; var doc = e.Editor.Document; - IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(e.Editor.FileName); + string fileName; + if (string.IsNullOrEmpty(e.Editor.FileName)) { + dynamic viewContent = WorkbenchSingleton.Workbench.ActiveViewContent; + fileName = string.Format("decompiled/{0}.cs", viewContent.FullTypeName); + } else { + fileName = e.Editor.FileName; + } + + IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); if (expressionFinder == null) return; + var currentLine = doc.GetLine(logicPos.Y); if (logicPos.X > currentLine.Length) return; @@ -275,7 +302,7 @@ namespace ICSharpCode.SharpDevelop.Debugging string expression = (expressionResult.Expression ?? "").Trim(); if (expression.Length > 0) { // Look if it is variable - ResolveResult result = ParserService.Resolve(expressionResult, logicPos.Y, logicPos.X, e.Editor.FileName, textContent); + ResolveResult result = ParserService.Resolve(expressionResult, logicPos.Y, logicPos.X, fileName, textContent); bool debuggerCanShowValue; string toolTipText = GetText(result, expression, out debuggerCanShowValue); if (Control.ModifierKeys == Keys.Control) { diff --git a/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs b/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs index 91ad361845..cf42a58d4e 100644 --- a/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs +++ b/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; +using Mono.Cecil; namespace ICSharpCode.SharpDevelop { @@ -90,7 +91,7 @@ namespace ICSharpCode.SharpDevelop #region Public Properties /// - /// true if we can navigate back to a previous point; false + /// true if we can navigate back to a previous point; false /// if there are no points in the history. /// public static bool CanNavigateBack { @@ -99,7 +100,7 @@ namespace ICSharpCode.SharpDevelop /// /// true if we can navigate forwards to a point prevously left - /// via navigating backwards; false if all the points in the + /// via navigating backwards; false if all the points in the /// history are in the "past". /// public static bool CanNavigateForwards { @@ -110,7 +111,7 @@ namespace ICSharpCode.SharpDevelop /// Gets the number of points in the navigation history. /// /// - /// Note: jumping forwards or backwards requires at least + /// Note: jumping forwards or backwards requires at least /// two points in the history; otherwise navigating has no meaning. /// public static int Count { @@ -151,12 +152,12 @@ namespace ICSharpCode.SharpDevelop } } -/* static void Log(IWorkbenchWindow window) + /* static void Log(IWorkbenchWindow window) { if (window==null) return; Log(window.ActiveViewContent); } -*/ + */ /// @@ -189,7 +190,7 @@ namespace ICSharpCode.SharpDevelop /// /// Refactoring this out of Log() allows the NavigationService /// to call this and ensure it will work regardless of the - /// requested state of loggingSuspended, as in + /// requested state of loggingSuspended, as in /// where we want to log /// the current position after clearing the /// history. @@ -199,7 +200,7 @@ namespace ICSharpCode.SharpDevelop if (p == null || String.IsNullOrEmpty(p.FileName) ) - { + { return; } if (currentNode==null) { @@ -228,7 +229,7 @@ namespace ICSharpCode.SharpDevelop } /// - /// Gets a of the INavigationPoints that + /// Gets a of the INavigationPoints that /// are currently in the collection. /// public static ICollection Points @@ -251,11 +252,11 @@ namespace ICSharpCode.SharpDevelop /// /// Do we clear the current position as well as the rest of the history? /// - /// The current position is often used to "seed" the next history to ensure + /// The current position is often used to "seed" the next history to ensure /// that the first significant movement after clearing the history allows /// us to jump "back" immediately. /// Remembering the current position across requests to clear the history - /// does not always make sense, however, such as when a solution is closing, + /// does not always make sense, however, such as when a solution is closing, /// hence the ability to explicitly control it's retention. /// public static void ClearHistory(bool clearCurrentPosition) @@ -270,10 +271,10 @@ namespace ICSharpCode.SharpDevelop } /// - /// Navigates to an that is an arbitrary + /// Navigates to an that is an arbitrary /// number of points away from the . /// - /// Number of points to move; negative deltas move + /// Number of points to move; negative deltas move /// backwards while positive deltas move forwards through the history. public static void Go(int delta) { @@ -323,7 +324,7 @@ namespace ICSharpCode.SharpDevelop /// /// Navigates the view (i.e. the workbench) to whatever - /// is the current + /// is the current /// position in the internal model. /// /// Factoring this out of code that manipulates @@ -396,8 +397,8 @@ namespace ICSharpCode.SharpDevelop { IViewContent vc = WorkbenchSingleton.Workbench.ActiveViewContent; if (vc == null) return; - LoggingService.DebugFormatted("NavigationService\n\tActiveViewContent: {0}\n\t Subview: {1}", - vc.TitleName, + LoggingService.DebugFormatted("NavigationService\n\tActiveViewContent: {0}\n\t Subview: {1}", + vc.TitleName, vc.TabPageText); Log(vc); } @@ -407,7 +408,7 @@ namespace ICSharpCode.SharpDevelop /// to reflect the change. /// /// - /// describing + /// describing /// the file rename. static void FileService_FileRenamed(object sender, FileRenameEventArgs e) { @@ -427,7 +428,7 @@ namespace ICSharpCode.SharpDevelop } #endregion - + #region Public Events /// @@ -462,7 +463,7 @@ namespace ICSharpCode.SharpDevelop if (cu == null || string.IsNullOrEmpty(cu.FileName) || region.IsEmpty) { foreach (var item in AddInTree.BuildItems("/SharpDevelop/Services/NavigateToEntityService", null, false)) { - if (item.NavigateTo(entity)) + if (item.NavigateToEntity(entity)) return true; } return false; @@ -471,6 +472,25 @@ namespace ICSharpCode.SharpDevelop } } #endregion + + #region Navigate to Member + + public static bool NavigateTo(string assemblyFile, string typeName, string entityTag) + { + if (string.IsNullOrEmpty(assemblyFile)) + throw new ArgumentException("assemblyFile is null or empty"); + + if (string.IsNullOrEmpty(typeName)) + throw new ArgumentException("typeName is null or empty"); + + foreach (var item in AddInTree.BuildItems("/SharpDevelop/Services/NavigateToEntityService", null, false)) { + if (item.NavigateToMember(assemblyFile, typeName, entityTag)) + return true; + } + return false; + } + + #endregion } /// @@ -481,6 +501,17 @@ namespace ICSharpCode.SharpDevelop /// public interface INavigateToEntityService { - bool NavigateTo(Dom.IEntity entity); + bool NavigateToEntity(Dom.IEntity entity); + } + + /// + /// Called by when the member reference is not defined in source code. + /// + /// + /// Loaded from addin tree path "/SharpDevelop/Services/NavigateToEntityService" + /// + public interface INavigateToMemberService + { + bool NavigateToMember(string assemblyFile, string typeName, string entityTag); } }