This commit is contained in:
Don Syme 2018-03-14 17:29:55 +00:00
Родитель 375b4225f0
Коммит 1ffbee73fa
25 изменённых файлов: 390 добавлений и 161 удалений

Просмотреть файл

@ -215,12 +215,23 @@ For **Release**:
- We use the proto compiler to compile the source for `FSharp.Core.dll` in this distribution.
- We use the proto compiler to compile the source for `FSharp.Compiler.dll`, `fsc.exe`, `fsi.exe`, and other binaries found in this distribution.
#### Updating FSComp.fs
#### Updating FSComp.fs, FSComp.resx and XLF
If you change error messages you may need to update FSComp.fs in `src\buildfromsource\FSharp.Compiler.Private`.
To do this, build the non-buildfromsource version of FSharp.Compiler.Private (src\fsharp\FSharp.Compiler.Private) then check its obj\ directory for `FSComp.fs` and manually copy that into the buildfromsource directory.
copy /y src\fsharp\FSharp.Compiler.Private\obj\Debug\net40\FSComp.fs src\buildfromsource\FSharp.Compiler.Private\
copy /y src\fsharp\FSharp.Compiler.Private\obj\Debug\net40\FSComp.resx src\buildfromsource\FSharp.Compiler.Private\
If your changes involve modifying the list of language keywords in any way, (e.g. when implementing a new keyword), the XLF localization files need to be synced with the corresponding resx files. This can be done automatically by running
pushd src\fsharp\FSharp.Compiler.Private
msbuild FSharp.Compiler.Private.fsproj /t:UpdateXlf
popd
This only works on Windows/.NETStandard framework, so changing this from any other platform requires editing and syncing all of the XLF files manually.
#### Configuring proxy server
@ -232,11 +243,6 @@ If you are behind a proxy server, NuGet client tool must be configured to use it
Where you should set proper proxy address, user name and password.
#### When modifying, adding, or removing keywords or compiler messages
If your changes involve modifying the list of language keywords in any way, (e.g. when implementing a new keyword), the XLF localization files need to be synced with the corresponding resx files. This can be done automatically by running `msbuild FSharp.Compiler.Private.fsproj /t:UpdateXlf` (located in [src\fsharp\FSharp.Compiler.Private](https://github.com/Microsoft/visualfsharp/tree/master/src/fsharp/FSharp.Compiler.Private)). This only works on Windows/.NETStandard framework, so changing this from any other platform requires editing and syncing all of the XLF files manually.
After this, you must copy any differing `resx` files from the output directory into the corresponding subdirectory in [src\buildfromsource](https://github.com/Microsoft/visualfsharp/tree/master/src/fsharp/FSharp.Compiler.Private). This step will soon be eliminated (see issue [#3905](https://github.com/Microsoft/visualfsharp/issues/3905)).
#### Resources

Просмотреть файл

@ -4057,273 +4057,276 @@ type internal SR private() =
/// Two anonymous record types are from different assemblies '%s' and '%s'
/// (Originally from ..\FSComp.txt:1343)
static member tcAnonRecdCcuMismatch(a0 : System.String, a1 : System.String) = (GetStringFunc("tcAnonRecdCcuMismatch",",,,%s,,,%s,,,") a0 a1)
/// One anonymous record type is assembly-bound to '%s' (syntax 'new {| ... |}'), the other is assembly-neutral (syntax '{| ... |}')
/// Two anonymous record types have mismatched sets of field names '%s' and '%s'
/// (Originally from ..\FSComp.txt:1344)
static member tcAnonRecdFieldNameMismatch(a0 : System.String, a1 : System.String) = (GetStringFunc("tcAnonRecdFieldNameMismatch",",,,%s,,,%s,,,") a0 a1)
/// Indicates a method that either has no implementation in the type in which it is declared or that is virtual and has a default implementation.
/// (Originally from ..\FSComp.txt:1346)
/// (Originally from ..\FSComp.txt:1345)
static member keywordDescriptionAbstract() = (GetStringFunc("keywordDescriptionAbstract",",,,") )
/// Used in mutually recursive bindings, in property declarations, and with multiple constraints on generic parameters.
/// (Originally from ..\FSComp.txt:1347)
/// (Originally from ..\FSComp.txt:1346)
static member keyworkDescriptionAnd() = (GetStringFunc("keyworkDescriptionAnd",",,,") )
/// Used to give the current class object an object name. Also used to give a name to a whole pattern within a pattern match.
/// (Originally from ..\FSComp.txt:1348)
/// (Originally from ..\FSComp.txt:1347)
static member keywordDescriptionAs() = (GetStringFunc("keywordDescriptionAs",",,,") )
/// Used to verify code during debugging.
/// (Originally from ..\FSComp.txt:1349)
/// (Originally from ..\FSComp.txt:1348)
static member keywordDescriptionAssert() = (GetStringFunc("keywordDescriptionAssert",",,,") )
/// Used as the name of the base class object.
/// (Originally from ..\FSComp.txt:1350)
/// (Originally from ..\FSComp.txt:1349)
static member keywordDescriptionBase() = (GetStringFunc("keywordDescriptionBase",",,,") )
/// In verbose syntax, indicates the start of a code block.
/// (Originally from ..\FSComp.txt:1351)
/// (Originally from ..\FSComp.txt:1350)
static member keywordDescriptionBegin() = (GetStringFunc("keywordDescriptionBegin",",,,") )
/// In verbose syntax, indicates the start of a class definition.
/// (Originally from ..\FSComp.txt:1352)
/// (Originally from ..\FSComp.txt:1351)
static member keywordDescriptionClass() = (GetStringFunc("keywordDescriptionClass",",,,") )
/// Indicates an implementation of an abstract method; used together with an abstract method declaration to create a virtual method.
/// (Originally from ..\FSComp.txt:1353)
/// (Originally from ..\FSComp.txt:1352)
static member keywordDescriptionDefault() = (GetStringFunc("keywordDescriptionDefault",",,,") )
/// Used to declare a delegate.
/// (Originally from ..\FSComp.txt:1354)
/// (Originally from ..\FSComp.txt:1353)
static member keywordDescriptionDelegate() = (GetStringFunc("keywordDescriptionDelegate",",,,") )
/// Used in looping constructs or to execute imperative code.
/// (Originally from ..\FSComp.txt:1355)
/// (Originally from ..\FSComp.txt:1354)
static member keywordDescriptionDo() = (GetStringFunc("keywordDescriptionDo",",,,") )
/// In verbose syntax, indicates the end of a block of code in a looping expression.
/// (Originally from ..\FSComp.txt:1356)
/// (Originally from ..\FSComp.txt:1355)
static member keywordDescriptionDone() = (GetStringFunc("keywordDescriptionDone",",,,") )
/// Used to convert to a type that is lower in the inheritance chain.
/// (Originally from ..\FSComp.txt:1357)
/// (Originally from ..\FSComp.txt:1356)
static member keywordDescriptionDowncast() = (GetStringFunc("keywordDescriptionDowncast",",,,") )
/// In a for expression, used when counting in reverse.
/// (Originally from ..\FSComp.txt:1358)
/// (Originally from ..\FSComp.txt:1357)
static member keywordDescriptionDownto() = (GetStringFunc("keywordDescriptionDownto",",,,") )
/// Used in conditional branching. A short form of else if.
/// (Originally from ..\FSComp.txt:1359)
/// (Originally from ..\FSComp.txt:1358)
static member keywordDescriptionElif() = (GetStringFunc("keywordDescriptionElif",",,,") )
/// Used in conditional branching.
/// (Originally from ..\FSComp.txt:1360)
/// (Originally from ..\FSComp.txt:1359)
static member keywordDescriptionElse() = (GetStringFunc("keywordDescriptionElse",",,,") )
/// In type definitions and type extensions, indicates the end of a section of member definitions. In verbose syntax, used to specify the end of a code block that starts with the begin keyword.
/// (Originally from ..\FSComp.txt:1361)
/// (Originally from ..\FSComp.txt:1360)
static member keywordDescriptionEnd() = (GetStringFunc("keywordDescriptionEnd",",,,") )
/// Used to declare an exception type.
/// (Originally from ..\FSComp.txt:1362)
/// (Originally from ..\FSComp.txt:1361)
static member keywordDescriptionException() = (GetStringFunc("keywordDescriptionException",",,,") )
/// Indicates that a declared program element is defined in another binary or assembly.
/// (Originally from ..\FSComp.txt:1363)
/// (Originally from ..\FSComp.txt:1362)
static member keywordDescriptionExtern() = (GetStringFunc("keywordDescriptionExtern",",,,") )
/// Used as a Boolean literal.
/// (Originally from ..\FSComp.txt:1364)
/// (Originally from ..\FSComp.txt:1363)
static member keywordDescriptionTrueFalse() = (GetStringFunc("keywordDescriptionTrueFalse",",,,") )
/// Used together with try to introduce a block of code that executes regardless of whether an exception occurs.
/// (Originally from ..\FSComp.txt:1365)
/// (Originally from ..\FSComp.txt:1364)
static member keywordDescriptionFinally() = (GetStringFunc("keywordDescriptionFinally",",,,") )
/// Used in looping constructs.
/// (Originally from ..\FSComp.txt:1366)
/// (Originally from ..\FSComp.txt:1365)
static member keywordDescriptionFor() = (GetStringFunc("keywordDescriptionFor",",,,") )
/// Used in lambda expressions, also known as anonymous functions.
/// (Originally from ..\FSComp.txt:1367)
/// (Originally from ..\FSComp.txt:1366)
static member keywordDescriptionFun() = (GetStringFunc("keywordDescriptionFun",",,,") )
/// Used as a shorter alternative to the fun keyword and a match expression in a lambda expression that has pattern matching on a single argument.
/// (Originally from ..\FSComp.txt:1368)
/// (Originally from ..\FSComp.txt:1367)
static member keywordDescriptionFunction() = (GetStringFunc("keywordDescriptionFunction",",,,") )
/// Used to reference the top-level .NET namespace.
/// (Originally from ..\FSComp.txt:1369)
/// (Originally from ..\FSComp.txt:1368)
static member keywordDescriptionGlobal() = (GetStringFunc("keywordDescriptionGlobal",",,,") )
/// Used in conditional branching constructs.
/// (Originally from ..\FSComp.txt:1370)
/// (Originally from ..\FSComp.txt:1369)
static member keywordDescriptionIf() = (GetStringFunc("keywordDescriptionIf",",,,") )
/// Used for sequence expressions and, in verbose syntax, to separate expressions from bindings.
/// (Originally from ..\FSComp.txt:1371)
/// (Originally from ..\FSComp.txt:1370)
static member keywordDescriptionIn() = (GetStringFunc("keywordDescriptionIn",",,,") )
/// Used to specify a base class or base interface.
/// (Originally from ..\FSComp.txt:1372)
/// (Originally from ..\FSComp.txt:1371)
static member keywordDescriptionInherit() = (GetStringFunc("keywordDescriptionInherit",",,,") )
/// Used to indicate a function that should be integrated directly into the caller's code.
/// (Originally from ..\FSComp.txt:1373)
/// (Originally from ..\FSComp.txt:1372)
static member keywordDescriptionInline() = (GetStringFunc("keywordDescriptionInline",",,,") )
/// Used to declare and implement interfaces.
/// (Originally from ..\FSComp.txt:1374)
/// (Originally from ..\FSComp.txt:1373)
static member keywordDescriptionInterface() = (GetStringFunc("keywordDescriptionInterface",",,,") )
/// Used to specify that a member is visible inside an assembly but not outside it.
/// (Originally from ..\FSComp.txt:1375)
/// (Originally from ..\FSComp.txt:1374)
static member keywordDescriptionInternal() = (GetStringFunc("keywordDescriptionInternal",",,,") )
/// Used to specify a computation that is to be performed only when a result is needed.
/// (Originally from ..\FSComp.txt:1376)
/// (Originally from ..\FSComp.txt:1375)
static member keywordDescriptionLazy() = (GetStringFunc("keywordDescriptionLazy",",,,") )
/// Used to associate, or bind, a name to a value or function.
/// (Originally from ..\FSComp.txt:1377)
/// (Originally from ..\FSComp.txt:1376)
static member keywordDescriptionLet() = (GetStringFunc("keywordDescriptionLet",",,,") )
/// Used in asynchronous workflows to bind a name to the result of an asynchronous computation, or, in other computation expressions, used to bind a name to a result, which is of the computation type.
/// (Originally from ..\FSComp.txt:1378)
/// (Originally from ..\FSComp.txt:1377)
static member keywordDescriptionLetBang() = (GetStringFunc("keywordDescriptionLetBang",",,,") )
/// Used to branch by comparing a value to a pattern.
/// (Originally from ..\FSComp.txt:1379)
/// (Originally from ..\FSComp.txt:1378)
static member keywordDescriptionMatch() = (GetStringFunc("keywordDescriptionMatch",",,,") )
/// Used to declare a property or method in an object type.
/// (Originally from ..\FSComp.txt:1380)
/// (Originally from ..\FSComp.txt:1379)
static member keywordDescriptionMember() = (GetStringFunc("keywordDescriptionMember",",,,") )
/// Used to associate a name with a group of related types, values, and functions, to logically separate it from other code.
/// (Originally from ..\FSComp.txt:1381)
/// (Originally from ..\FSComp.txt:1380)
static member keywordDescriptionModule() = (GetStringFunc("keywordDescriptionModule",",,,") )
/// Used to declare a variable, that is, a value that can be changed.
/// (Originally from ..\FSComp.txt:1382)
/// (Originally from ..\FSComp.txt:1381)
static member keywordDescriptionMutable() = (GetStringFunc("keywordDescriptionMutable",",,,") )
/// Used to associate a name with a group of related types and modules, to logically separate it from other code.
/// (Originally from ..\FSComp.txt:1383)
/// (Originally from ..\FSComp.txt:1382)
static member keywordDescriptionNamespace() = (GetStringFunc("keywordDescriptionNamespace",",,,") )
/// Used to declare, define, or invoke a constructor that creates or that can create an object. Also used in generic parameter constraints to indicate that a type must have a certain constructor.
/// (Originally from ..\FSComp.txt:1384)
/// (Originally from ..\FSComp.txt:1383)
static member keywordDescriptionNew() = (GetStringFunc("keywordDescriptionNew",",,,") )
/// Not actually a keyword. However, not struct in combination is used as a generic parameter constraint.
/// (Originally from ..\FSComp.txt:1385)
/// (Originally from ..\FSComp.txt:1384)
static member keywordDescriptionNot() = (GetStringFunc("keywordDescriptionNot",",,,") )
/// Indicates the absence of an object. Also used in generic parameter constraints.
/// (Originally from ..\FSComp.txt:1386)
/// (Originally from ..\FSComp.txt:1385)
static member keywordDescriptionNull() = (GetStringFunc("keywordDescriptionNull",",,,") )
/// Used in discriminated unions to indicate the type of categories of values, and in delegate and exception declarations.
/// (Originally from ..\FSComp.txt:1387)
/// (Originally from ..\FSComp.txt:1386)
static member keywordDescriptionOf() = (GetStringFunc("keywordDescriptionOf",",,,") )
/// Used to make the contents of a namespace or module available without qualification.
/// (Originally from ..\FSComp.txt:1388)
/// (Originally from ..\FSComp.txt:1387)
static member keywordDescriptionOpen() = (GetStringFunc("keywordDescriptionOpen",",,,") )
/// Used with Boolean conditions as a Boolean or operator. Equivalent to ||. Also used in member constraints.
/// (Originally from ..\FSComp.txt:1389)
/// (Originally from ..\FSComp.txt:1388)
static member keywordDescriptionOr() = (GetStringFunc("keywordDescriptionOr",",,,") )
/// Used to implement a version of an abstract or virtual method that differs from the base version.
/// (Originally from ..\FSComp.txt:1390)
/// (Originally from ..\FSComp.txt:1389)
static member keywordDescriptionOverride() = (GetStringFunc("keywordDescriptionOverride",",,,") )
/// Restricts access to a member to code in the same type or module.
/// (Originally from ..\FSComp.txt:1391)
/// (Originally from ..\FSComp.txt:1390)
static member keywordDescriptionPrivate() = (GetStringFunc("keywordDescriptionPrivate",",,,") )
/// Allows access to a member from outside the type.
/// (Originally from ..\FSComp.txt:1392)
/// (Originally from ..\FSComp.txt:1391)
static member keywordDescriptionPublic() = (GetStringFunc("keywordDescriptionPublic",",,,") )
/// Used to indicate that a function is recursive.
/// (Originally from ..\FSComp.txt:1393)
/// (Originally from ..\FSComp.txt:1392)
static member keywordDescriptionRec() = (GetStringFunc("keywordDescriptionRec",",,,") )
/// Used to indicate a value to provide as the result of a computation expression.
/// (Originally from ..\FSComp.txt:1394)
/// (Originally from ..\FSComp.txt:1393)
static member keywordDescriptionReturn() = (GetStringFunc("keywordDescriptionReturn",",,,") )
/// Used to indicate a computation expression that, when evaluated, provides the result of the containing computation expression.
/// (Originally from ..\FSComp.txt:1395)
/// (Originally from ..\FSComp.txt:1394)
static member keywordDescriptionReturnBang() = (GetStringFunc("keywordDescriptionReturnBang",",,,") )
/// Used in query expressions to specify what fields or columns to extract. Note that this is a contextual keyword, which means that it is not actually a reserved word and it only acts like a keyword in appropriate context.
/// (Originally from ..\FSComp.txt:1396)
/// (Originally from ..\FSComp.txt:1395)
static member keywordDescriptionSelect() = (GetStringFunc("keywordDescriptionSelect",",,,") )
/// Used to indicate a method or property that can be called without an instance of a type, or a value member that is shared among all instances of a type.
/// (Originally from ..\FSComp.txt:1397)
/// (Originally from ..\FSComp.txt:1396)
static member keywordDescriptionStatic() = (GetStringFunc("keywordDescriptionStatic",",,,") )
/// Used to declare a structure type. Also used in generic parameter constraints. Used for OCaml compatibility in module definitions.
/// (Originally from ..\FSComp.txt:1398)
/// (Originally from ..\FSComp.txt:1397)
static member keywordDescriptionStruct() = (GetStringFunc("keywordDescriptionStruct",",,,") )
/// Used in conditional expressions. Also used to perform side effects after object construction.
/// (Originally from ..\FSComp.txt:1399)
/// (Originally from ..\FSComp.txt:1398)
static member keywordDescriptionThen() = (GetStringFunc("keywordDescriptionThen",",,,") )
/// Used in for loops to indicate a range.
/// (Originally from ..\FSComp.txt:1400)
/// (Originally from ..\FSComp.txt:1399)
static member keywordDescriptionTo() = (GetStringFunc("keywordDescriptionTo",",,,") )
/// Used to introduce a block of code that might generate an exception. Used together with with or finally.
/// (Originally from ..\FSComp.txt:1401)
/// (Originally from ..\FSComp.txt:1400)
static member keywordDescriptionTry() = (GetStringFunc("keywordDescriptionTry",",,,") )
/// Used to declare a class, record, structure, discriminated union, enumeration type, unit of measure, or type abbreviation.
/// (Originally from ..\FSComp.txt:1402)
/// (Originally from ..\FSComp.txt:1401)
static member keywordDescriptionType() = (GetStringFunc("keywordDescriptionType",",,,") )
/// Used to convert to a type that is higher in the inheritance chain.
/// (Originally from ..\FSComp.txt:1403)
/// (Originally from ..\FSComp.txt:1402)
static member keywordDescriptionUpcast() = (GetStringFunc("keywordDescriptionUpcast",",,,") )
/// Used instead of let for values that require Dispose to be called to free resources.
/// (Originally from ..\FSComp.txt:1404)
/// (Originally from ..\FSComp.txt:1403)
static member keywordDescriptionUse() = (GetStringFunc("keywordDescriptionUse",",,,") )
/// Used instead of let! in asynchronous workflows and other computation expressions for values that require Dispose to be called to free resources.
/// (Originally from ..\FSComp.txt:1405)
/// (Originally from ..\FSComp.txt:1404)
static member keywordDescriptionUseBang() = (GetStringFunc("keywordDescriptionUseBang",",,,") )
/// Used in a signature to indicate a value, or in a type to declare a member, in limited situations.
/// (Originally from ..\FSComp.txt:1406)
/// (Originally from ..\FSComp.txt:1405)
static member keywordDescriptionVal() = (GetStringFunc("keywordDescriptionVal",",,,") )
/// Indicates the .NET void type. Used when interoperating with other .NET languages.
/// (Originally from ..\FSComp.txt:1407)
/// (Originally from ..\FSComp.txt:1406)
static member keywordDescriptionVoid() = (GetStringFunc("keywordDescriptionVoid",",,,") )
/// Used for Boolean conditions (when guards) on pattern matches and to introduce a constraint clause for a generic type parameter.
/// (Originally from ..\FSComp.txt:1408)
/// (Originally from ..\FSComp.txt:1407)
static member keywordDescriptionWhen() = (GetStringFunc("keywordDescriptionWhen",",,,") )
/// Introduces a looping construct.
/// (Originally from ..\FSComp.txt:1409)
/// (Originally from ..\FSComp.txt:1408)
static member keywordDescriptionWhile() = (GetStringFunc("keywordDescriptionWhile",",,,") )
/// Used together with the match keyword in pattern matching expressions. Also used in object expressions, record copying expressions, and type extensions to introduce member definitions, and to introduce exception handlers.
/// (Originally from ..\FSComp.txt:1410)
/// (Originally from ..\FSComp.txt:1409)
static member keywordDescriptionWith() = (GetStringFunc("keywordDescriptionWith",",,,") )
/// Used in a sequence expression to produce a value for a sequence.
/// (Originally from ..\FSComp.txt:1411)
/// (Originally from ..\FSComp.txt:1410)
static member keywordDescriptionYield() = (GetStringFunc("keywordDescriptionYield",",,,") )
/// Used in a computation expression to append the result of a given computation expression to a collection of results for the containing computation expression.
/// (Originally from ..\FSComp.txt:1412)
/// (Originally from ..\FSComp.txt:1411)
static member keywordDescriptionYieldBang() = (GetStringFunc("keywordDescriptionYieldBang",",,,") )
/// In function types, delimits arguments and return values. Yields an expression (in sequence expressions); equivalent to the yield keyword. Used in match expressions
/// (Originally from ..\FSComp.txt:1413)
/// (Originally from ..\FSComp.txt:1412)
static member keywordDescriptionRightArrow() = (GetStringFunc("keywordDescriptionRightArrow",",,,") )
/// Assigns a value to a variable.
/// (Originally from ..\FSComp.txt:1414)
/// (Originally from ..\FSComp.txt:1413)
static member keywordDescriptionLeftArrow() = (GetStringFunc("keywordDescriptionLeftArrow",",,,") )
/// Converts a type to type that is higher in the hierarchy.
/// (Originally from ..\FSComp.txt:1415)
/// (Originally from ..\FSComp.txt:1414)
static member keywordDescriptionCast() = (GetStringFunc("keywordDescriptionCast",",,,") )
/// Converts a type to a type that is lower in the hierarchy.
/// (Originally from ..\FSComp.txt:1416)
/// (Originally from ..\FSComp.txt:1415)
static member keywordDescriptionDynamicCast() = (GetStringFunc("keywordDescriptionDynamicCast",",,,") )
/// Delimits a typed code quotation.
/// (Originally from ..\FSComp.txt:1417)
/// (Originally from ..\FSComp.txt:1416)
static member keywordDescriptionTypedQuotation() = (GetStringFunc("keywordDescriptionTypedQuotation",",,,") )
/// Delimits a untyped code quotation.
/// (Originally from ..\FSComp.txt:1418)
/// (Originally from ..\FSComp.txt:1417)
static member keywordDescriptionUntypedQuotation() = (GetStringFunc("keywordDescriptionUntypedQuotation",",,,") )
/// %s '%s' not found in assembly '%s'. A possible cause may be a version incompatibility. You may need to explicitly reference the correct version of this assembly to allow all referenced components to use the correct version.
/// (Originally from ..\FSComp.txt:1419)
/// (Originally from ..\FSComp.txt:1418)
static member itemNotFoundDuringDynamicCodeGen(a0 : System.String, a1 : System.String, a2 : System.String) = (3216, GetStringFunc("itemNotFoundDuringDynamicCodeGen",",,,%s,,,%s,,,%s,,,") a0 a1 a2)
/// %s '%s' not found in type '%s' from assembly '%s'. A possible cause may be a version incompatibility. You may need to explicitly reference the correct version of this assembly to allow all referenced components to use the correct version.
/// (Originally from ..\FSComp.txt:1420)
/// (Originally from ..\FSComp.txt:1419)
static member itemNotFoundInTypeDuringDynamicCodeGen(a0 : System.String, a1 : System.String, a2 : System.String, a3 : System.String) = (3216, GetStringFunc("itemNotFoundInTypeDuringDynamicCodeGen",",,,%s,,,%s,,,%s,,,%s,,,") a0 a1 a2 a3)
/// is
/// (Originally from ..\FSComp.txt:1421)
/// (Originally from ..\FSComp.txt:1420)
static member descriptionWordIs() = (GetStringFunc("descriptionWordIs",",,,") )
/// This value is not a function and cannot be applied.
/// (Originally from ..\FSComp.txt:1422)
/// (Originally from ..\FSComp.txt:1421)
static member notAFunction() = (GetStringFunc("notAFunction",",,,") )
/// This value is not a function and cannot be applied. Did you intend to access the indexer via %s.[index] instead?
/// (Originally from ..\FSComp.txt:1423)
/// (Originally from ..\FSComp.txt:1422)
static member notAFunctionButMaybeIndexerWithName(a0 : System.String) = (GetStringFunc("notAFunctionButMaybeIndexerWithName",",,,%s,,,") a0)
/// This expression is not a function and cannot be applied. Did you intend to access the indexer via expr.[index] instead?
/// (Originally from ..\FSComp.txt:1424)
/// (Originally from ..\FSComp.txt:1423)
static member notAFunctionButMaybeIndexer() = (GetStringFunc("notAFunctionButMaybeIndexer",",,,") )
///
/// (Originally from ..\FSComp.txt:1425)
/// (Originally from ..\FSComp.txt:1424)
static member notAFunctionButMaybeIndexerErrorCode() = (3217, GetStringFunc("notAFunctionButMaybeIndexerErrorCode",",,,") )
/// This value is not a function and cannot be applied. Did you forget to terminate a declaration?
/// (Originally from ..\FSComp.txt:1426)
/// (Originally from ..\FSComp.txt:1425)
static member notAFunctionButMaybeDeclaration() = (GetStringFunc("notAFunctionButMaybeDeclaration",",,,") )
/// The argument names in the signature '%s' and implementation '%s' do not match. The argument name from the signature file will be used. This may cause problems when debugging or profiling.
/// (Originally from ..\FSComp.txt:1427)
/// (Originally from ..\FSComp.txt:1426)
static member ArgumentsInSigAndImplMismatch(a0 : System.String, a1 : System.String) = (3218, GetStringFunc("ArgumentsInSigAndImplMismatch",",,,%s,,,%s,,,") a0 a1)
/// An error occurred while reading the F# metadata of assembly '%s'. A reserved construct was utilized. You may need to upgrade your F# compiler or use an earlier version of the assembly that doesn't make use of a specific construct.
/// (Originally from ..\FSComp.txt:1428)
/// (Originally from ..\FSComp.txt:1427)
static member pickleUnexpectedNonZero(a0 : System.String) = (3219, GetStringFunc("pickleUnexpectedNonZero",",,,%s,,,") a0)
/// This method or property is not normally used from F# code, use an explicit tuple pattern for deconstruction instead.
/// (Originally from ..\FSComp.txt:1429)
/// (Originally from ..\FSComp.txt:1428)
static member tcTupleMemberNotNormallyUsed() = (3220, GetStringFunc("tcTupleMemberNotNormallyUsed",",,,") )
/// This expression returns a value of type '%s' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'.
/// (Originally from ..\FSComp.txt:1430)
/// (Originally from ..\FSComp.txt:1429)
static member implicitlyDiscardedInSequenceExpression(a0 : System.String) = (3221, GetStringFunc("implicitlyDiscardedInSequenceExpression",",,,%s,,,") a0)
/// This expression returns a value of type '%s' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'.
/// (Originally from ..\FSComp.txt:1431)
/// (Originally from ..\FSComp.txt:1430)
static member implicitlyDiscardedSequenceInSequenceExpression(a0 : System.String) = (3222, GetStringFunc("implicitlyDiscardedSequenceInSequenceExpression",",,,%s,,,") a0)
/// Invalid anonymous record expression
/// (Originally from ..\FSComp.txt:1432)
/// (Originally from ..\FSComp.txt:1431)
static member parsInvalidAnonRecdExpr() = (3223, GetStringFunc("parsInvalidAnonRecdExpr",",,,") )
/// Invalid anonymous record type
/// (Originally from ..\FSComp.txt:1433)
/// (Originally from ..\FSComp.txt:1432)
static member parsInvalidAnonRecdType() = (3224, GetStringFunc("parsInvalidAnonRecdType",",,,") )
/// The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record
/// (Originally from ..\FSComp.txt:1433)
static member tcCopyAndUpdateNeedsRecordType() = (3225, GetStringFunc("tcCopyAndUpdateNeedsRecordType",",,,") )
/// Call this method once to validate that all known resources are valid; throws if not
static member RunStartupValidation() =
@ -5730,4 +5733,5 @@ type internal SR private() =
ignore(GetString("implicitlyDiscardedSequenceInSequenceExpression"))
ignore(GetString("parsInvalidAnonRecdExpr"))
ignore(GetString("parsInvalidAnonRecdType"))
ignore(GetString("tcCopyAndUpdateNeedsRecordType"))
()

Просмотреть файл

@ -4327,4 +4327,7 @@
<data name="parsInvalidAnonRecdType" xml:space="preserve">
<value>Invalid anonymous record type</value>
</data>
<data name="tcCopyAndUpdateNeedsRecordType" xml:space="preserve">
<value>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</value>
</data>
</root>

Просмотреть файл

@ -1430,3 +1430,4 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
3222,implicitlyDiscardedSequenceInSequenceExpression,"This expression returns a value of type '%s' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'."
3223,parsInvalidAnonRecdExpr,"Invalid anonymous record expression"
3224,parsInvalidAnonRecdType,"Invalid anonymous record type"
3225,tcCopyAndUpdateNeedsRecordType,"The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record"

Просмотреть файл

@ -674,7 +674,6 @@ type LexFilterImpl (lightSyntaxStatus:LightSyntaxStatus, compilingFsLib, lexer,
| _,(CtxtSeqBlock _ :: CtxtParen(LBRACE,_) :: CtxtVanilla _ :: CtxtSeqBlock _ :: rest)
-> unindentationLimit false rest
// MAJOR PERMITTED UNDENTATION This is allowing:
// if x then y else
// let x = 3 + 4
@ -768,7 +767,7 @@ type LexFilterImpl (lightSyntaxStatus:LightSyntaxStatus, compilingFsLib, lexer,
// REVIEW: document these
| _,(CtxtSeqBlock _ :: CtxtParen((BEGIN | LPAREN | LBRACK | LBRACK_BAR),_) :: CtxtVanilla _ :: (CtxtSeqBlock _ as limitCtxt) :: _)
| (CtxtSeqBlock _),(CtxtParen ((BEGIN | LPAREN | LBRACE | LBRACK | LBRACK_BAR) ,_) :: CtxtSeqBlock _ :: ((CtxtTypeDefns _ | CtxtLetDecl _ | CtxtMemberBody _ | CtxtWithAsLet _) as limitCtxt) :: _)
| (CtxtSeqBlock _),(CtxtParen ((BEGIN | LPAREN | LBRACE | LBRACE_BAR | LBRACK | LBRACK_BAR) ,_) :: CtxtSeqBlock _ :: ((CtxtTypeDefns _ | CtxtLetDecl _ | CtxtMemberBody _ | CtxtWithAsLet _) as limitCtxt) :: _)
-> PositionWithColumn(limitCtxt.StartPos,limitCtxt.StartCol + 1)
// Permitted inner-construct (e.g. "then" block and "else" block in overall
@ -998,7 +997,7 @@ type LexFilterImpl (lightSyntaxStatus:LightSyntaxStatus, compilingFsLib, lexer,
// WITH balances except in the following contexts.... Phew - an overused keyword!
| WITH , ( ((CtxtMatch _ | CtxtException _ | CtxtMemberHead _ | CtxtInterfaceHead _ | CtxtTry _ | CtxtTypeDefns _ | CtxtMemberBody _) :: _)
// This is the nasty record/object-expression case
| (CtxtSeqBlock _ :: CtxtParen(LBRACE,_) :: _) )
| (CtxtSeqBlock _ :: CtxtParen((LBRACE | LBRACE_BAR),_) :: _) )
| FINALLY , (CtxtTry _ :: _) ->
true
@ -1796,7 +1795,7 @@ type LexFilterImpl (lightSyntaxStatus:LightSyntaxStatus, compilingFsLib, lexer,
// '{ id1 = 1
// M.id2 = ... ' ~~~> CtxtSeqBlock
| EQUALS, ((CtxtWithAsLet _) :: _) // This detects 'with = '.
| EQUALS, ((CtxtVanilla (_,true)) :: (CtxtSeqBlock _) :: (CtxtWithAsLet _ | CtxtParen(LBRACE,_)) :: _) ->
| EQUALS, ((CtxtVanilla (_,true)) :: (CtxtSeqBlock _) :: (CtxtWithAsLet _ | CtxtParen((LBRACE | LBRACE_BAR),_)) :: _) ->
if debug then dprintf "CtxtLetDecl/CtxtWithAsLet: EQUALS, pushing CtxtSeqBlock\n"
// We don't insert begin/end block tokens for single-line bindings since we can't properly distinguish single-line *)
// record update expressions such as "{ t with gbuckets=Array.copy t.gbuckets; gcount=t.gcount }" *)
@ -1897,7 +1896,7 @@ type LexFilterImpl (lightSyntaxStatus:LightSyntaxStatus, compilingFsLib, lexer,
returnToken tokenLexbufState token
| WITH, (((CtxtException _ | CtxtTypeDefns _ | CtxtMemberHead _ | CtxtInterfaceHead _ | CtxtMemberBody _) as limCtxt) :: _)
| WITH, ((CtxtSeqBlock _) as limCtxt :: CtxtParen(LBRACE,_) :: _) ->
| WITH, ((CtxtSeqBlock _) as limCtxt :: CtxtParen((LBRACE | LBRACE_BAR),_) :: _) ->
let lookaheadTokenTup = peekNextTokenTup()
let lookaheadTokenStartPos = startPosOfTokenTup lookaheadTokenTup
match lookaheadTokenTup.Token with

Просмотреть файл

@ -5821,23 +5821,8 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
let expr = mkAnyTupled cenv.g m tupInfo args' argtys
expr, tpenv
| SynExpr.AnonRecd (isStruct, unsortedArgs, m) ->
let unsortedIds = unsortedArgs |> List.map fst |> List.toArray
let anonInfo, sortedArgTys = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isStruct unsortedIds
// Sort into canonical order
let sortedIndexedArgs = unsortedArgs |> List.indexed |> List.sortBy (fun (i,_) -> unsortedIds.[i].idText)
let sigma = List.map fst sortedIndexedArgs |> List.toArray
let sortedArgs = List.map snd sortedIndexedArgs
sortedArgs |> List.iteri (fun j (x, _) ->
let item = Item.AnonRecdField(anonInfo, sortedArgTys, j, x.idRange)
CallNameResolutionSink cenv.tcSink (x.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights))
let unsortedArgTys = sortedArgTys |> List.indexed |> List.sortBy (fun (j, _) -> sigma.[j]) |> List.map snd
let flexes = unsortedArgTys |> List.map (fun _ -> true)
let unsortedCheckedArgs, tpenv = TcExprs cenv env m tpenv flexes unsortedArgTys (List.map snd unsortedArgs)
let sortedCheckedArgs = unsortedCheckedArgs |> List.indexed |> List.sortBy (fun (i,_) -> unsortedIds.[i].idText) |> List.map snd
mkAnonRecd cenv.g m anonInfo sortedCheckedArgs sortedArgTys, tpenv
| SynExpr.AnonRecd (isStruct, optOrigExpr, unsortedArgs, mWholeExpr) ->
TcAnonRecdExpr cenv overallTy env tpenv (isStruct, optOrigExpr, unsortedArgs, mWholeExpr)
| SynExpr.ArrayOrList (isArray, args, m) ->
CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights)
@ -6685,9 +6670,9 @@ and TcObjectExpr cenv overallTy env tpenv (synObjTy, argopt, binds, extraImpls,
if // record construction ?
isRecordTy ||
// object construction?
(isFSharpObjModelTy cenv.g objTy && not (isInterfaceTy cenv.g objTy) && Option.isNone argopt) then
(isFSharpObjModelTy cenv.g objTy && not (isInterfaceTy cenv.g objTy) && argopt.IsNone) then
if Option.isSome argopt then error(Error(FSComp.SR.tcNoArgumentsForRecordValue(), mWholeExpr))
if argopt.IsSome then error(Error(FSComp.SR.tcNoArgumentsForRecordValue(), mWholeExpr))
if not (isNil extraImpls) then error(Error(FSComp.SR.tcNoInterfaceImplementationForConstructionExpression(), mNewExpr))
if isFSharpObjModelTy cenv.g objTy && GetCtorShapeCounter env <> 1 then
error(Error(FSComp.SR.tcObjectConstructionCanOnlyBeUsedInClassTypes(), mNewExpr))
@ -6894,11 +6879,6 @@ and TcAssertExpr cenv overallTy env (m:range) tpenv x =
TcExpr cenv overallTy env tpenv callDiagnosticsExpr
//-------------------------------------------------------------------------
// TcRecdExpr
//-------------------------------------------------------------------------
and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr) =
let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors
@ -6985,9 +6965,104 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr
expr, tpenv
//-------------------------------------------------------------------------
// TcForEachExpr
//-------------------------------------------------------------------------
// Check '{| .... |}'
and TcAnonRecdExpr cenv overallTy env tpenv (isStruct, optOrigExpr, unsortedArgs, mWholeExpr) =
match optOrigExpr with
| None ->
let unsortedIds = unsortedArgs |> List.map fst |> List.toArray
let anonInfo, sortedArgTys = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedIds
// Sort into canonical order
let sortedIndexedArgs = unsortedArgs |> List.indexed |> List.sortBy (fun (i,_) -> unsortedIds.[i].idText)
let sigma = List.map fst sortedIndexedArgs |> List.toArray
let sortedArgs = List.map snd sortedIndexedArgs
sortedArgs |> List.iteri (fun j (x, _) ->
let item = Item.AnonRecdField(anonInfo, sortedArgTys, j, x.idRange)
CallNameResolutionSink cenv.tcSink (x.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights))
let unsortedArgTys = sortedArgTys |> List.indexed |> List.sortBy (fun (j, _) -> sigma.[j]) |> List.map snd
let flexes = unsortedArgTys |> List.map (fun _ -> true)
let unsortedCheckedArgs, tpenv = TcExprs cenv env mWholeExpr tpenv flexes unsortedArgTys (List.map snd unsortedArgs)
let sortedCheckedArgs = unsortedCheckedArgs |> List.indexed |> List.sortBy (fun (i,_) -> unsortedIds.[i].idText) |> List.map snd
mkAnonRecd cenv.g mWholeExpr anonInfo sortedCheckedArgs sortedArgTys, tpenv
| Some (origExpr, _) ->
// The fairly complex case '{| origExpr with X = 1; Y = 2 |}'
// The origExpr may be either a record or anonymous record.
// The origExpr may be either a struct or not.
// All the properties of origExpr are copied across except where they are overridden.
// The result is a field-sorted anonymous record.
//
// Unlike in the case of record type copy-and-update we do _not_ assume that the origExpr has the same type as the overall expression.
// Unlike in the case of record type copy-and-update {| a with X = 1 |} does not force a.X to exist or have had type 'int'
let origExprTy = NewInferenceType()
let origExprChecked, tpenv = TcExpr cenv origExprTy env tpenv origExpr
let oldv, oldve = mkCompGenLocal mWholeExpr "inputRecord" origExprTy
let mOrigExpr = origExpr.Range
if not (isAppTy cenv.g origExprTy || isAnonRecdTy cenv.g origExprTy) then
error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr))
let origExprIsStruct =
match tryDestAnonRecdTy cenv.g origExprTy with
| Some (anonInfo, _) -> evalTupInfoIsStruct anonInfo.TupInfo
| None ->
let tcref, _ = destAppTy cenv.g origExprTy
tcref.IsStructOrEnumTycon
let wrap, oldveaddr = mkExprAddrOfExpr cenv.g origExprIsStruct false NeverMutates oldve None mOrigExpr
// Put all the expressions in unsorted order. The new bindings come first. The origin of each is tracked using
/// - Choice1Of2 for a new binding
/// - Choice2Of2 for a binding coming from the original expression
let unsortedIdAndExprsAll =
[| for (id, e) in unsortedArgs do
yield (id, Choice1Of2 e)
match tryDestAnonRecdTy cenv.g origExprTy with
| Some (anonInfo, tinst) ->
for (i, id) in Array.indexed anonInfo.SortedIds do
yield id, Choice2Of2 (mkAnonRecdFieldGetViaExprAddr (anonInfo, oldveaddr, tinst, i, mOrigExpr))
| None ->
if isRecdTy cenv.g origExprTy then
let tcref, tinst = destAppTy cenv.g origExprTy
let fspecs = tcref.Deref.TrueInstanceFieldsAsList
for fspec in fspecs do
yield fspec.Id, Choice2Of2 (mkRecdFieldGetViaExprAddr (oldveaddr , tcref.MakeNestedRecdFieldRef fspec, tinst, mOrigExpr))
else
error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr)) |]
|> Array.distinctBy (fst >> textOfId)
let unsortedIdsAll = Array.map fst unsortedIdAndExprsAll
let anonInfo, sortedArgTysAll = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedIdsAll
let sortedIndexedArgsAll = unsortedIdAndExprsAll |> Array.indexed |> Array.sortBy (snd >> fst >> textOfId)
let sigma = Array.map fst sortedIndexedArgsAll // map from sorted indexes to unsorted indexes
let sortedArgsAll = Array.map snd sortedIndexedArgsAll
sortedArgsAll |> Array.iteri (fun j (x, expr) ->
match expr with
| Choice1Of2 _ ->
let item = Item.AnonRecdField(anonInfo, sortedArgTysAll, j, x.idRange)
CallNameResolutionSink cenv.tcSink (x.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, env.eAccessRights)
| Choice2Of2 _ -> ())
let unsortedArgTysNew = sortedArgTysAll |> List.indexed |> List.sortBy (fun (j, _) -> sigma.[j]) |> List.take unsortedArgs.Length |> List.map snd
let flexes = unsortedArgTysNew |> List.map (fun _ -> true)
let unsortedCheckedArgsNew, tpenv = TcExprs cenv env mWholeExpr tpenv flexes unsortedArgTysNew (List.map snd unsortedArgs)
let sortedArgTysAllArray = Array.ofList sortedArgTysAll
let unsortedCheckedArgsNewArray = unsortedCheckedArgsNew |> List.toArray
let sortedCheckedArgsAll =
sortedArgsAll |> Array.mapi (fun j (_, expr) ->
match expr with
| Choice1Of2 _ -> unsortedCheckedArgsNewArray.[sigma.[j]]
| Choice2Of2 subExpr -> UnifyTypes cenv env mOrigExpr (tyOfExpr cenv.g subExpr) sortedArgTysAllArray.[j]; subExpr)
let expr = mkAnonRecd cenv.g mWholeExpr anonInfo (List.ofArray sortedCheckedArgsAll) sortedArgTysAll
let expr = wrap expr
let expr = mkCompGenLet mOrigExpr oldv origExprChecked expr
expr, tpenv
and TcForEachExpr cenv overallTy env tpenv (pat, enumSynExpr, bodySynExpr, mWholeExpr, spForLoop) =
UnifyTypes cenv env mWholeExpr overallTy cenv.g.unit_ty

Просмотреть файл

@ -523,8 +523,8 @@ and
| Tuple of isStruct: bool * exprs:SynExpr list * commaRanges:range list * range:range // "range list" is for interstitial commas, these only matter for parsing/design-time tooling, the typechecker may munge/discard them
/// F# syntax: {| id1=e1; ...; idN=eN |}
/// F# syntax: {| new id1=e1; ...; idN=eN |}
| AnonRecd of isStruct: bool * recordFields:(Ident * SynExpr) list * range:range
/// F# syntax: struct {| id1=e1; ...; idN=eN |}
| AnonRecd of isStruct: bool * copyInfo:(SynExpr * BlockSeparator) option * recordFields:(Ident * SynExpr) list * range:range
/// F# syntax: [ e1; ...; en ], [| e1; ...; en |]
| ArrayOrList of isList:bool * exprs:SynExpr list * range:range
@ -2356,10 +2356,12 @@ let rec synExprContainsError inpExpr =
| SynExpr.Tuple (_,es,_,_) ->
walkExprs es
| SynExpr.AnonRecd (_,flds,_) ->
| SynExpr.AnonRecd (_,origExpr,flds,_) ->
(match origExpr with Some (e,_) -> walkExpr e | None -> false) ||
walkExprs (List.map snd flds)
| SynExpr.Record (_,_,fs,_) ->
| SynExpr.Record (_,origExpr,fs,_) ->
(match origExpr with Some (e,_) -> walkExpr e | None -> false) ||
let flds = fs |> List.choose (fun (_, v, _) -> v)
walkExprs (flds)

Просмотреть файл

@ -3989,14 +3989,17 @@ recdExpr:
let (_, _, inheritsSep) = List.head l
let bindings = List.tail l
(Some ($2,arg,rhs2 parseState 2 4, inheritsSep, rhs parseState 1), None, bindings) }
| recdExprCore
{ let a,b = $1 in (None, a, b) }
recdExprCore:
| appExpr EQUALS declExprBlock recdExprBindings opt_seps_recd
{ match $1 with
| LongOrSingleIdent(false, (LongIdentWithDots(_,_) as f),None,m) ->
let f = mkRecdField f
let l = List.rev $4
let l = rebindRanges (f, Some $3) l $5
(None, None, l)
(None, l)
| _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding()) }
/*
@ -4008,7 +4011,7 @@ recdExpr:
reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName())
reportParseErrorAt m (FSComp.SR.parsFieldBinding())
let f = mkUnderscoreRecdField m
(None, None, [ f, None, None ]) }
(None, [ (f, None, None) ]) }
| UNDERSCORE EQUALS
{ let m = rhs parseState 1
@ -4017,28 +4020,28 @@ recdExpr:
reportParseErrorAt (rhs2 parseState 1 2) (FSComp.SR.parsFieldBinding())
(None, None, [f, None, None]) }
(None, [ (f, None, None) ]) }
| UNDERSCORE EQUALS declExprBlock recdExprBindings opt_seps_recd
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnderscoreInvalidFieldName())
let f = mkUnderscoreRecdField (rhs parseState 1)
let l = List.rev $4
let l = rebindRanges (f, Some $3) l $5
(None, None, l) }
(None, l) }
/* handles case like {x with} */
| appExpr WITH recdBinding recdExprBindings opt_seps_recd
{ let l = List.rev $4
let l = rebindRanges $3 l $5
(None,Some ($1, (rhs parseState 2, None)), l) }
(Some ($1, (rhs parseState 2, None)), l) }
| appExpr OWITH opt_seps_recd OEND
{ (None,Some ($1, (rhs parseState 2, None)), []) }
{ (Some ($1, (rhs parseState 2, None)), []) }
| appExpr OWITH recdBinding recdExprBindings opt_seps_recd OEND
{ let l = List.rev $4
let l = rebindRanges $3 l $5
(None,Some ($1, (rhs parseState 2, None)), l) }
(Some ($1, (rhs parseState 2, None)), l) }
opt_seps_recd:
| seps_recd { Some $1 }
@ -4166,16 +4169,26 @@ braceBarExpr:
{ $1 false }
braceBarExprCore:
| LBRACE_BAR oneOrMoreRecdExprBindings bar_rbrace
{ let flds = $2
| LBRACE_BAR recdExprCore bar_rbrace
{ let orig, flds = $2
let flds =
flds |> List.choose (function
| ((LongIdentWithDots([id],_),_),Some e,_) -> Some (id,e)
| ((LongIdentWithDots([id],_),_),None,_) -> Some (id, arbExpr("anonField",id.idRange))
| _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None)
let m = rhs2 parseState 1 3
(fun isStruct -> SynExpr.AnonRecd(isStruct,flds,m)) }
(fun isStruct -> SynExpr.AnonRecd(isStruct,orig,flds,m)) }
| LBRACE_BAR oneOrMoreRecdExprBindings recover
| LBRACE_BAR recdExprCore recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar())
let flds = $2
let orig, flds = $2
let flds =
flds |> List.choose (function
| ((LongIdentWithDots([id],_),_),Some e,_) -> Some (id,e)
| ((LongIdentWithDots([id],_),_),None,_) -> Some (id, arbExpr("anonField",id.idRange))
| _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None)
let m = rhs2 parseState 1 2
(fun isStruct -> SynExpr.AnonRecd(isStruct,flds,m)) }
(fun isStruct -> SynExpr.AnonRecd(isStruct,orig,flds,m)) }
| LBRACE_BAR error bar_rbrace
{ // silent recovery
@ -4185,19 +4198,11 @@ braceBarExprCore:
| LBRACE_BAR recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar())
let m = rhs2 parseState 1 1
(fun isStruct -> SynExpr.AnonRecd(isStruct,[],m)) }
(fun isStruct -> SynExpr.AnonRecd(isStruct,None,[],m)) }
| LBRACE_BAR bar_rbrace
{ let m = rhs2 parseState 1 2
(fun isStruct -> SynExpr.AnonRecd(isStruct,[],m)) }
oneOrMoreRecdExprBindings:
| recdBinding recdExprBindings
{ (($1, None) :: List.rev $2) |> List.choose (function
| (((LongIdentWithDots([id],_),_),Some e),_) -> Some (id,e)
| (((LongIdentWithDots([id],_),_),None),_) -> Some (id, arbExpr("anonField",id.idRange))
| _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) }
(fun isStruct -> SynExpr.AnonRecd(isStruct,None,[],m)) }
anonLambdaExpr:
| FUN atomicPatterns RARROW typedSeqExprBlock

Просмотреть файл

@ -49,48 +49,63 @@ module public AstTraversal =
/// traverseSynExpr(subExpr) to recurse deeper on some particular sub-expression based on your own logic
/// path helps to track AST nodes that were passed during traversal
abstract VisitExpr : TraversePath * (SynExpr -> 'T option) * (SynExpr -> 'T option) * SynExpr -> 'T option
/// VisitTypeAbbrev(ty,m), defaults to ignoring this leaf of the AST
abstract VisitTypeAbbrev : SynType * range -> 'T option
default this.VisitTypeAbbrev(_ty,_m) = None
/// VisitImplicitInherit(defaultTraverse,ty,expr,m), defaults to just visiting expr
abstract VisitImplicitInherit : (SynExpr -> 'T option) * SynType * SynExpr * range -> 'T option
default this.VisitImplicitInherit(defaultTraverse, _ty, expr, _m) = defaultTraverse expr
/// VisitModuleDecl allows overriding module declaration behavior
abstract VisitModuleDecl : (SynModuleDecl -> 'T option) * SynModuleDecl -> 'T option
default this.VisitModuleDecl(defaultTraverse, decl) = defaultTraverse decl
/// VisitBinding allows overriding binding behavior (note: by default it would defaultTraverse expression)
abstract VisitBinding : (SynBinding -> 'T option) * SynBinding -> 'T option
default this.VisitBinding(defaultTraverse, binding) = defaultTraverse binding
/// VisitMatchClause allows overriding clause behavior (note: by default it would defaultTraverse expression)
abstract VisitMatchClause : (SynMatchClause -> 'T option) * SynMatchClause -> 'T option
default this.VisitMatchClause(defaultTraverse, mc) = defaultTraverse mc
/// VisitInheritSynMemberDefn allows overriding inherit behavior (by default do nothing)
abstract VisitInheritSynMemberDefn : SynComponentInfo * SynTypeDefnKind * SynType * SynMemberDefns * range -> 'T option
default this.VisitInheritSynMemberDefn(_componentInfo, _typeDefnKind, _synType, _members, _range) = None
/// VisitInterfaceSynMemberDefnType allows overriding behavior for visiting interface member in types (by default - do nothing)
abstract VisitInterfaceSynMemberDefnType : SynType -> 'T option
default this.VisitInterfaceSynMemberDefnType(_synType) = None
/// VisitRecordField allows overriding behavior when visiting l.h.s. of constructed record instances
abstract VisitRecordField : TraversePath * SynExpr option * LongIdentWithDots option -> 'T option
default this.VisitRecordField (_path, _copyOpt, _recordField) = None
/// VisitHashDirective allows overriding behavior when visiting hash directives in FSX scripts, like #r, #load and #I.
abstract VisitHashDirective : range -> 'T option
default this.VisitHashDirective (_) = None
/// VisitModuleOrNamespace allows overriding behavior when visiting module or namespaces
abstract VisitModuleOrNamespace : SynModuleOrNamespace -> 'T option
default this.VisitModuleOrNamespace (_) = None
/// VisitComponentInfo allows overriding behavior when visiting type component infos
abstract VisitComponentInfo : SynComponentInfo -> 'T option
default this.VisitComponentInfo (_) = None
/// VisitLetOrUse allows overriding behavior when visiting module or local let or use bindings
abstract VisitLetOrUse : SynBinding list * range -> 'T option
default this.VisitLetOrUse (_, _) = None
/// VisitType allows overriding behavior when visiting simple pats
abstract VisitSimplePats : SynSimplePat list -> 'T option
default this.VisitSimplePats (_) = None
/// VisitPat allows overriding behavior when visiting patterns
abstract VisitPat : (SynPat -> 'T option) * SynPat -> 'T option
default this.VisitPat (defaultTraverse, pat) = defaultTraverse pat
/// VisitType allows overriding behavior when visiting type hints (x: ..., etc.)
abstract VisitType : (SynType -> 'T option) * SynType -> 'T option
default this.VisitType (defaultTraverse, ty) = defaultTraverse ty
@ -194,7 +209,22 @@ module public AstTraversal =
| SynExpr.Tuple(_, synExprList, _, _range)
| SynExpr.ArrayOrList(_, synExprList, _range) -> synExprList |> List.map (fun x -> dive x x.Range traverseSynExpr) |> pick expr
| SynExpr.AnonRecd(_isStruct, synExprList, _range) -> synExprList |> List.map snd |> List.map (fun x -> dive x x.Range traverseSynExpr) |> pick expr
| SynExpr.AnonRecd(_isStruct, copyOpt, synExprList, _range) ->
[ match copyOpt with
| Some(expr, (withRange, _)) ->
yield dive expr expr.Range traverseSynExpr
yield dive () withRange (fun () ->
if posGeq pos withRange.End then
// special case: caret is after WITH
// { x with $ }
visitor.VisitRecordField (path, Some expr, None)
else
None
)
| _ -> ()
for (_,x) in synExprList do
yield dive x x.Range traverseSynExpr
] |> pick expr
| SynExpr.Record(inheritOpt,copyOpt,fields, _range) ->
[
let diveIntoSeparator offsideColumn scPosOpt copyOpt =

Просмотреть файл

@ -227,7 +227,10 @@ type FSharpParseFileResults(errors: FSharpErrorInfo[], input: Ast.ParsedInput op
| None -> ()
yield! walkExprs (fs |> List.choose p23)
| SynExpr.AnonRecd (_isStruct, fs, _) ->
| SynExpr.AnonRecd (_isStruct, copyExprOpt, fs, _) ->
match copyExprOpt with
| Some (e,_) -> yield! walkExpr true e
| None -> ()
yield! walkExprs (fs |> List.map snd)
| SynExpr.ObjExpr (_,_,bs,is,_,_) ->

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7012,6 +7012,11 @@
<target state="new">Invalid anonymous record type</target>
<note />
</trans-unit>
<trans-unit id="tcCopyAndUpdateNeedsRecordType">
<source>The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</source>
<target state="new">The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -65,9 +65,6 @@ module KindB1 =
check "ceoijew90ewcw6" (FSharp.Reflection.FSharpValue.GetRecordFields({| X = 1 |}).Length) 1
check "ceoijew90ewcw7" (FSharp.Reflection.FSharpValue.GetRecordFields({| X = 1 |}).[0]) (box 1)
// TODO: field reordering....
//let test3b() = {| a = 1+1; b = 2 |} = {| b = 1; a = 2 |}
// Equality is possible
check "ceijoewwekcj" {| a = 1-1 |} {| a = Unchecked.defaultof<_> |}
@ -145,10 +142,44 @@ module KindB2 =
check "cew9cwo3" testConstrainedAccess2 (0, 1, 2)
// Copy-and-update may not be used, since C# doesn't allow this on anonymous objects
module CopyAndUpdateOfAnonRecord =
let data = {| X = 1 |}
let data2 = {| data with Y = "1" |}
let data3 = {| data with X = "3" |}
check "fewjkvwno31" data.X 1
check "fewjkvwno32" data2.X 1
check "fewjkvwno33" data2.Y "1"
check "fewjkvwno34" data3.X "3"
// Types _can_ be used outside their assembly, but can _not_ be named in the syntax of types, nor created
module CopyAndUpdateOfAnonRecordStruct =
let data = struct {| X = 1 |}
let data2 = struct {| data with Y = "1" |}
let data3 = struct {| data with X = "3" |}
check "fewjkvwno311" data.X 1
check "fewjkvwno322" data2.X 1
check "fewjkvwno333" data2.Y "1"
check "fewjkvwno344" data3.X "3"
module CopyAndUpdateOfAnonRecordFromRecord =
type Base = { X : int }
let data = { X = 1 }
let data2 = {| data with Y = "1" |}
let data3 = {| data with X = "3" |}
check "fewjkvwno315" data.X 1
check "fewjkvwno326" data2.X 1
check "fewjkvwno337" data2.Y "1"
check "fewjkvwno348" data3.X "3"
module CopyAndUpdateOfAnonRecordFromStructRecord =
[<Struct>]
type Base = { X : int }
let data = { X = 1 }
let data2 = {| data with Y = "1" |}
let data3 = {| data with X = "3" |}
check "fewjkvwno31q" data.X 1
check "fewjkvwno32w" data2.X 1
check "fewjkvwno33e" data2.Y "1"
check "fewjkvwno34r" data3.X "3"
module QuotesNewRecord =