Version history
Gathered from commit messages. Trivial changes omitted.Changes to Loyc Core libraries and LES
v30.1: June 15, 2022
- Potentially breaking: support for .NET 4.5 has been removed (.NET 4.7 is still supported temporarily)
Loyc.Syntax:
- Potentially breaking:
LNode.IsSpecialName
now returnstrue
if the name is null or empty. I didn’t record a rationale for the original decision, but it seems to me that it’s better to treat `` as special because (1) a C/C++ port with null-terminated strings can just returnName[0] < '\''
without a length check, and (2) the empty string sure ain’t a normal name. - Add helper methods
LNodeExt.UnwrapBraces
,LNodeExt.Unwrap
methods - Bug fix in LNode:
WithRange
could delete attributes in special cases.
Loyc.Collections:
- Potentially breaking:
INegArray
now implementsIArraySink<T>
andIIndexed<int, T>
(otherwise, no new members) - Added
IAutoNegArray<T>
, a tag interface synonymous withINegArray<T>
- Added
struct InternalDArray<T>
, which is a variation onInternalDList<T>
that implementsIAutoNegArray<T>
. Avoid it: I feel like I gave this structure the wrong name, and I may rename it soon.
Loyc.Essentials:
- Added
TypeDictionaryWithBaseTypeLookups<Value>
, A dictionary whose keys areType
s. It behaves almost like a standard dictionary, except that theTryGetValue
method will find matches on base types and interfaces. InternalDList<T>.Slice(int start, int subcount)
is nowpublic
- Remove redundant method
G.Swap
v30.0: January 26, 2021
Changes to the IEnumerable<T>
extension methods in EnumerableExt:
IndexOfMin
andIndexOfMax
now give you the minimum item instead of the minimum result of the selector. (This allowsMinItemOrDefault
andMaxItemOrDefault
to be simplified by being written in terms ofIndexOfMin
andIndexOfMax
)MinOrDefault
andMaxOrDefault
have been renamed toMinItemOrDefault
andMaxItemOrDefault
to better indicate how they differ from the standardMin
andMax
extension methods.- Added
MaxItem
andMinItem
extension methods
Other changes:
- Implement
ITuple
onMaybe
,Pair
andTriplet
,Equals/GetHashCode/ToString
onMaybe<T>
Either<L,R>
,IEither<L,R>
,Pair<A,B>
andTriplet<A,B,C>
now implementSystem.Runtime.CompilerServices.ITuple
(Either
considers itself a tuple of twoMaybe<>
values.)- Added
IEither<A,B,C>
- Potentially breaking:
Either<L,R>
now implementsIEquatable<ITuple>
instead ofIEquatable<IEither<L,R>>
v2.9.0.3 (a.k.a. v29): January 13, 2021
Potentially breaking changes & deprecations:
Note: it’s not as bad as it looks - most users will be unaffected.
Loyc.Interfaces:
- The
ListChanging
event inINotifyListChanging<T>
and in all classes derived fromAListBase
was changed to use the new typeevent ListChangingHandler<T, IListSource<T>> ListChanging
. - Renamed
AddIfNotPresent<K, V>(this IDictionaryEx<K, V> dict, K key, V value)
toTryAdd
, to match standard .NET methods such asConcurrentDictionary.TryAdd
. The old method is still there, but marked Obsolete. - Added
ListChangingHandler<T, TSender>
, and deprecatedListChangingHandler<T>
in favor ofListChangingHandler<T, IListSource<T>>
. This change helps dictionaries, sets and other non-list collections to provide change notifications (i.e.DictionaryWithChangeEvents
andCollectionWithChangeEvents
). - Added interfaces
ILast
,IMLast
,IFirst
,IMFirst
for immutable and mutableFirst
andLast
properties of collections.IDeque
inherits from these instead of having First/Last properties;IFRange
now inherits fromIHasFirst
;IBRange
now inherits fromIHasLast
;IMFRange
now inherits fromIHasMFirst
;
- Added
IIndexedSink<in K, in V>
interface as base interface ofIDictionarySink<in K, in V>
- Altered
ISourceRange
to useIIndexRange
as its base interface - Added
ISource<T>
as a new base interface ofIListSource<T>
. Because of this, all implementations ofIListSource<T>
now require anIsEmpty
property. - Added
IListAndListSource
andICollectionImpl
as base interfaces ofIListImpl<T>
- Renamed
IHasXxx
interfaces toIXxx
. Rationale: in v28 there were several interfaces likeIContains
,ICount
,IPush
,IOptimize
andIIsEmpty
that are simply named after the method or property they contain. There were also several interfaces with anIHas
pattern, e.g.IHasValue
,IHasLocation
,IHasFileName
. I’ve decided it’s better to have a regular naming scheme, and I simply tend to like the bare names (without ‘Has’) better.- Renamed
IHasLocation
toILocation
(old name is derived and marked obsolete) - Renamed
IHasValue
to `IValue (old name is derived and marked obsolete) - Renamed
IHasMutableValue
toIMValue
(old name is derived and marked obsolete) - Renamed
IHasFileName
toIFileName
(old name is derived and marked obsolete)
- Renamed
- Added
IDictionarySource<K,V>
as a new base interface ofIDictionaryImpl<K,V>
. Because of this, all implementations of this interface andIDictionaryEx<K,V>
must now provide anIsEmpty
property and aTryGet
method in addition toTryGetValue
.TryGet
is better thanTryGetValue
because it supports variance, e.g.ITryGet<object, Symbol>
can be assigned to a variable of typeITryGet<string, object>
. - Added new
ILineToIndex
interface as base interface ofIIndexPositionMapper
- Make appending
UString
toStringBuilder
more discoverable by making non-staticAppendTo
method (it cannot be anAppend
extension method onStringBuilder
becauseStringBuilder.Append(object)
takes priority.) The old static methodAppend
is marked Obsolete. - Added
ISparseListSource<T>.Slice()
method that must returnISparseListSource<T>
- Simplified
IListSource<T>.Slice
return value fromIRange<T>
toIListSource<T>
. Experience has shown that Ranges don’t work as well in C# as they do in D, and changing the return value toIListSource
required no changes to any of the consumers of the lists in this codebase. Later I might remove implementations ofIRange<T>
from the Slice classes, but not yet.
Loyc.Essentials:
EmptyList<T>
is now a singleton andEmptyList<T>.Value
is assigned tonew Repeated<T>(default(T), 0)
so that the rest ofEmptyList<T>
could be deleted.
Loyc.Collections:
- Renamed
AddIfNotPresent
methods inBDictionary<,>
toTryAdd
, to match standard .NET methods such asConcurrentDictionary.TryAdd
. The old methods are still there, but marked Obsolete.
Loyc.Syntax:
- Changes in
Token
:Token.ToStringStrategy
andToken.SetToStringStrategy
now useFunc<Token, ICharSource, string>
instead ofFunc<Token, string>
to allow the original token text to be obtained from source code.Token.ToLNode
was moved toTokenTree
(the only class that uses this method) asTokenTree.TokenToLNode(Token, ISourceFile)
. The old method still exists but is marked Obsolete.- Disabled the setter of the
Value
property.WithValue
can be called to create a new token with a different value.
- Changes to support new literal system in LES2 and LES3 (video on Loyc Literal System):
- Marked
CustomLiteral
as [Obsolete] - Added
ILNodePrinterOptions.LiteralPrinter
property of typeILiteralPrinter
so users can more fully control the printing of literals - Rename
ISerializedLiteral
toIUninterpretedLiteral
. The old name still exists and is marked [Obsolete]. LNode.Equals
now includesTypeMarker
in comparisons between string literals.- LES2 and 3 now recognizes fewer type markers than the previous version: markers using capital letters
_U
,_UL
,_F
,_D
and_Z
are no longer recognized. Such literals will still be included in the Loyc tree and no errors will be reported, but they are left uninterpreted.
- Marked
- Renamed
LNodeFactory.List()
methods toAltList()
. This is done to match the name used inCodeSymbols
and to avoid confusion, sinceList
does not create a JavaScript-style list (the symbolCodeSymbols.Array
is assigned to that purpose.) The old name still exists and is markedObsolete
, but will be removed in the future. NodeStyle
: increaseBaseStyleMask
from 3 to 4 bits and deprecateOneLiner
- Renamed
PrinterState
toLNodePrinterHelper
, which implements the new interfacesILNodePrinterHelperWithRevokableNewlines<LNodePrinterOutputLocation, LNodePrinterHelper>
andILNodePrinterHelper
. The old name still exists (as a derived class) and is marked Obsolete. LNodePrinterHelper.CommitNewlines
returnsthis
instead ofint
.- Class
DefaultNodePrinterWriter
has been deleted, as EC# and LES now useLNodePrinterHelper
instead. - Removed
Les2Printer.Writer
property and renamedParsedValue
toLiteralFromParser
- changes that probably affect no one.
LES2:
- LES2 no longer prints TokenTree with its native syntax
@{...}
, as nothing important relied on this feature, it was lost in the refactor, and it never worked quite right anyway. Les2Lexer.UnescapeString
andUnescapeQuotedString
were moved toLes3Lexer
(the old name still exists and is marked [Obsolete])-123
is no longer a negative number. As in LES3,-123
is a number with a'-
operator attached to it, and you can force it to be interpreted as a negative literal using either the \u2212 minus sign (−123
) or string syntax (_"-123"
). The old interpretation was removed because it could cause unintuitive parsing, e.g.-2**x
used to mean(-2)**x
whereas-a**x
means-(a**x)
.
Non-breaking changes
Loyc.Interfaces
- Added
ILiteralParser
andILiteralPrinter
interfaces, which are implemented byLiteralHandlerTable
in Loyc.Syntax. - Added interfaces for observable collections:
INotifyListChanged<T, TCollection>
which encapsulates aListChanged
eventINotifyListChanged<T>
which acts as an alias forINotifyListChanged<T, IListSource<T>>
IListWithChangeEvents<T>
, which combinesIListAndListSource<T>
withINotifyListChanging<T>
andINotifyListChanged<T>
IListExWithChangeEvents<T>
, which combinesIListEx<T>
withIListWithChangeEvents<T>
IDictionaryWithChangeEvents<K, V>
(which combinesIDictionaryAndReadOnly<K, V>
withINotifyListChanging<KeyValuePair<K, V>, IDictionary<K, V>>
andINotifyListChanged<KeyValuePair<K, V>, IDictionary<K, V>>
)IDictionaryExWithChangeEvents<K, V>
(which combinesIDictionaryEx<K, V>
withIDictionaryWithChangeEvents<K, V>
).
- Brought back the
ISource<T>
interface, which is the same asIReadOnlyCollection<T>
except that it implementsICount
andIIsEmpty
. - Added
TryPopFirst()
andTryPopLast()
methods inUString
- Added
ListChangeInfo<T>.OldItems
property. Also added support for this property to the ALists (classes derived fromAListBase<T>
) - Added
IIndexRange
interface (with integer propertiesStartIndex
,EndIndex
andLength
), and a simple implementation instruct IndexRange
(with methodsOverlaps
,Contains
andGetRangeOfOverlap
). - Added
IMIndexed<K,V>
(mutable derived interface ofIIndexed<K,V>
) - Added
IDictionarySource<K,V>
, which isIReadOnlyDictionary<K,V>
plus minor interfacesIIndexed<K, V>
,ITryGet<K, V>
, andISource<KeyValuePair<K, V>>
. - Add
ILogMessage
interface thatLogMessage
implements - Added static
MessageSink.Write(this IMessageSink<object>, ILogMessage)
andMessageSink.Write(this IMessageSink<object>, LogMessage)
methods - Added overload of
G.With
extension method that allows the lambda to take its value by reference - Added methods to
CheckParam
:ThrowBadArgument
(3 overloads), plus two new overloads ofThrowOutOfRange
, andThrowIfStartOrCountAreBelowZeroAndLimitCountIfNecessary
(which encapsulates a common code sequence from many slice classes.) - Added methods
Equals
,GetHashCode
, andToString
inEither<,>
EmptySourceFile.Synthetic.FileName
is now “" instead of "Synthetic", and `EmptySourceFile.Unknown.FileName` is " " instead of "Unknown". - Workaround: added numerous overloads of the
.TryGet(key)
and.TryGet(key, defaultValue)
extension methods for various interfaces and types derived fromITryGet{K,V}
because C# is “unable to infer” the type parameters ofITryGet{K,V}
itself.
Loyc.Essentials:
- Added wrapper classes with change events:
ListWithChangeEvents
,DictionaryWithChangeEvents
, andCollectionWithChangeEvents
. These classes provide change notifications for changes to ordinary non-observable collections. - Added wrapper classes in Loyc.Essentials:
CollectionWrapper
,ListWrapper
,DictionaryWrapper
, andSetWrapper
- Added
AsSink
extension methods with helper classesCollectionAsSink
,DictionaryAsSink
andListAsSink
- Added
NullMessageSink.Write(Severity)
overload and fixed theCount
andErrorCount
properties, whose values were the reverse of each other. - Added new overloads of
WithoutPrefix
andWithoutSuffix
forUString
inStringExt
- Added
StringComparison
parameter for the existing extension methods forstring
- Added
- Added extension method overload
AsListSource(this IReadOnlyList<T>)
with corresponding adapter classReadOnlyListAsListSource<T>
, plus 3 disambiguating overloads and a no-op (AsListSource<T>(this IListSource<T> c) => c
) - Added
BufferedSequence<T>.BufferedCount
property - Added disambiguating overload
DictionaryExt.TryGetValue(this IDictionaryAndReadOnly...)
- Added
SparseListSourceSlice
which can be used to implement the newSlice
method inISparseListSource<T>
(and is used bySparseAList<T>
). - Bug fix: when
Assert.AreEqual
failed, it sometimes showed...
inappropriately at the end of the shorter of two strings when it did not truncate that string.
Loyc.Collections:
BMultiMap<,>.ValueList
: AddedIsEmpty
,StartIndex
,EndIndex
properties
Loyc.Syntax:
- Add general-purpose classes called
LiteralHandlerTable
andStandardLiteralHandlers
for literal parsing and printing. Also, I made a video about these classes. - Added
LNodeRangeMapper
class, the importance of which is explained by another video - Other changes to
Token
:- Added
TextValue
method,TypeMarker
property, and corresponding constructors that make them work. Tokens that support this method are called “uninterpreted literals” and theirValue
is always null. Documentation of the new constructors explains how they work. - On 32-bit platforms this increases Token size from 16 to 20 bytes.
- On 64-bit platforms the Token size is unchanged at 24 bytes.
Token.Length
is now 32 bits instead of 24 (thoughLNode.Range.Length
is still limited to 0x7FFFFF).- New overload
Token.ToString(ICharSource)
allows you to provide original source code to be used to figure out the string form of the Token. - Deprecated apparently unused method
Token.GetParenPairSymbol
Token
converts implicitly toIndexRange
- Added
- Other changes were made to support new literal system in LES2 and LES3:
Les2Lexer
andLes3Lexer
no longer parse literals (it’s the parser’s job now)- In
LNodeFactory
,Literal(Token)
now automatically parses uninterpreted literals viaStandardLiteralHandlers.Value
. AddedLiteralFromValueOf(Token)
which replicates the old behavior ofLiteral(Token)
, andUninterpretedLiteral(Token)
which creates a literal node from an uninterpreted token without parsing the token (this used to be known as a “custom literal”). All the parser has to do to parse literals correctly now is to setLNodeFactory.ErrorSink
so that it can report literal parsing errors. LNode.Equals
now includesTypeMarker
in comparisons between string literals. TheTextValue
s are also compared when usingCompareMode.Styles
. By default, two literals are considered equal if their Values are equal and either (1) the TypeMarkers are equal, (2) the Values are not strings (nor UString)s, or (3) the Values are strings, but one of the type markers is null and the other is empty (zero-lengthName
). IfEquals
is called with the newCompareMode.TypeMarkers
flag, strict equality of TypeMarkers is required.- LES2 and 3 printers now rely on
StandardLiteralHandlers
, but this requires them to use a more complex process to detect whether a number has valid syntax, because printers no longer know in advance which types will produce valid numeric strings. Instead, a newCanPrintAsNumber
function is used to scan supposedly-numeric printed strings to find out if it’s practical to print them as numbers.
- Changes to
LNodeFactory
:- Added no-arg
LNodeFactory()
constructor, which usesEmptySourceFile.Unknown
as its implicit source file - Added optional
NodeStyle style = NodeStyle.Default
argument on several overloads ofCall
. - Added five new series of methods:
CallPrefix
(4 overloads),CallPrefixOp
(6 overloads),CallInfixOp
(4 overloads),CallSuffixOp
(2 overloads),CallBrackets
(not overloaded). These methods make it easier to create Loyc nodes that have correct values for theRange
property by choosing an appropriate range for the requested kind of operator or call.- Use
CallPrefix
for ordinary calls with argument lists, e.g.Method(x, y)
- Use
CallPrefixOp
for prefix operators and calls that start with an identifying token and end with a child node, e.g.-x
orfrom x in y
- Use
CallInfixOp
for binary and ternary infix operators, e.g.x + y
orc ? a : b
- Use
CallSuffixOp
for suffix operators, e.g.x++
- Use
CallBrackets
for lists delimited by outer tokens, e.g.{ x; y; }
or(x, y)
- Use
- Added a new overload of
Dot
andBraces
that are used similarly to the new methods above - As mentioned earlier,
Literal(Token)
behaves differently and methodsLiteralFromValueOf(Token)
andUninterpretedLiteral(Token)
were added. LNodeFactory
now avoids returning nodes with invalidendIndex
- Bug fix:
InParens
created a node with an incorrect value forRange.EndIndex
- Added no-arg
- Changes to trivia injectors:
AbstractTriviaInjector
no longer usesOneLiner
. Instead it scans into syntax trees recursively even if they are on a single line, giving the derived class an opportunity to inject%appendStatement
trivia. WhileOneLiner
was an interesting optimization, it caused problems in practice when interacting with macros, and therefore several macros had code to strip out theOneLiner
style from their output. By not usingOneLiner
, this will no longer be necessary. Support forOneLiner
has also been stripped out of Enhanced C#, LES2 and LES3.- Renamed
AbstractTriviaInjector.GetAttachedTrivia
toGetTriviaToAttach
to be less confusing - Tweaked
AbstractTriviaInjector
to better handle “reified” newlines, i.e. newlines that are represented as identifiers like'\n
. Given a stream of identifiers like { Ann,'\n
, Bob } where'\n
is also a newline in the trivia stream, the trivia injector used to produce Ann, @%appendStatement
@(%trailing
(%newline
))'\n
, @%appendStatement
Bob but now it will produce Ann, @%appendStatement
'\n
, Bob - If there are two blank lines between nodes
A\n\nB
,AbstractTriviaInjector
now associates both newlines withB
, so that(A; @`%newline` @`%newline` B)
is emitted instead of(@`%trailing`(`%newline`) A; @`%newline` B)
. Its behavior has not changed for the case of three or more newlines (A\n\n\nB
becomes(@`%trailing`(`%newline`, `%newline`) A; @`%newline` B)
or a single newline (A\nB
becomes(A; @`%newline` B)
). I decided that this behavior was more desirable in most cases. Unit tests of LES2, LES3 and EC# were changed to expect the new behavior.
- Changes to
IMacroContext
(with implementation in LeMP):- Added
ICollection<Symbol> OpenMacroNamespaces
property - Add
PreviousSiblings
andAncestorsAndPreviousSiblings
properties toIMacroContext
- Return type of
Ancestors
was expanded fromIReadOnlyList<LNode>
toIListSource<LNode>
(this allows moreLinqToLists
methods to work on it. Arguably the right solution is to write moreLinqToLists
methods, but I took the easy way out.)
- Added
- Added interfaces
IPrinterHelper<out Self>
ILNodePrinterHelper<out Self>
,ILNodePrinterHelperWithRevokableNewlines<Checkpoint, out Self>
andILNodePrinterHelper
, plus extension methods inLNodePrinterHelperExt
, and an extensible enum calledPrinterIndentHint
. - Added overload
LNode.WithArgs(IEnumerable<LNode> args)
- Added
LNodeList.AddIfNotNull(item)
method - Added
ILNodePrinterOptions.SaveRange
property with support in EC#, LES2 and LES3 (in addition toLiteralPrinter
property mentioned earlier) BaseParserForList<,>
andBaseParserForList<,,>
have new constructors that accept aFunc<Token,Token> getEofToken
instead ofFunc<Token,Token> eofToken
. This allows an EOF token to be computed based on the second-to-last token, which is useful in streaming parsers that do not want to compute the correct EOF token up front. Previously, LES2 and LES3 used EOF tokens withStartIndex=0
which is wrong; in error conditions (early EOF), this could cause an incorrect range to be associated with nodes that contain syntax errors. Updated LES2, LES3, and LLLPG parsers to use the new constructor (the EC# parser doesn’t use BaseParserForList).- Added static
SourceRange.New<IndexRange>(ISourceFile, IndexRange)
which returnsnew SourceRange(source, range.StartIndex, range.Length)
, plus an implicit conversion fromSourceRange
toIndexRange
. - Bug fix in
LexerSource.Error(int, string, ...)
- Bug fix in
BaseLexer
: if an error occurred at a certain position P, and then the lexer was Reset, and then another error occurred at P in the new file, the latter error would not be reported.
LES2:
- Custom literals now work in LES2 using basically the same syntax as LES3, e.g.
123myNumber
ormyString"hello"
. As in LES3,StandardLiteralHandlers.Value
is being used to parse and print. - Added
?>
and<?
operators with same precedence as?
and:
- Bug fix: LES2 printer used LES3 precedence for operators that start with
'
LES3:
- LES3 parser now allows you to exit token list mode with a single quote, or begin token list mode after a comma. For example,
(' a b c ' Foo(2), ' d e f)
means(a, b, c, Foo(2), 1, 2, 3)
. - Added
?>
and<?
operators with same precedence as?
and:
- When using
ParsingMode.Expressions
, the LES parser no longer expects a newline between items and will not insert%appendStatement
trivia when the expected newline isn’t there - Refined LES3 logic for detecting “unexpected separator” errors; doing it correctly is difficult. Previously
{ a, b\n }
and{ a, b\n c }
would be treated as errors because the newline was treated like a semicolon; now, the first case is OK and the second case is still an error. - Bug fix:
TokenType.Unknown
mistakenly had the same value asTokenType.EOF
which could mess up error messages and cause LES3 parsing to stop instantly at an invalid token, such as a backslash. - Bug fix:
}
was indented too much if there was a//
comment on the previous line. - Flipped inheritance relationship between
Les2PrecedenceMap
andLes3PrecedenceMap
.
v2.8.3: November 16, 2020
Loyc.Interfaces:
- Bug fix:
default(UString).ToString()
no longer throwsNullReferenceException
Loyc.Essentials:
- Add
G.WordWrap
functions, which break a paragraph into lines using a simple word-wrapping algorithm. There are two overloads, one of which supports variable-width characters. Also added a default character categorization strategyG.GetWordWrapCharType
Loyc.Math:
- Bug fix:
ComputeConvexHull
returned nothing if the input was a single point; it now returns that point.
Loyc.Syntax:
- Add
<>
operator to LES (#87) - Added
LNodeExt
extension methods:LNode.Unsplice
,LNodeList.IncludingAttributes
,LNode.IncludingTriviaFrom
. In macros,IncludingTriviaFrom
should be used to copy comments and newlines from the original macro call to the output code.
v2.8.2: July 24, 2020
Loyc.Syntax:
- Add
ParsingOptions
class to implementIParsingOptions
(it was unintentionallyinternal
in the previous release) LNodeList.AddRange
now acceptsIReadOnlyList<>
. It unintentionally acceptedIList<>
in the previous release.
v2.8.1: July 6, 2020
Loyc.Essentials:
- Add
G.Do<T, R>(this T obj, Func<T, R> action)
extension method for running a statement or block of statements inside an expression. - Add
string
extension methodsWithoutPrefix
andWithoutSuffix
for trimming off a specific prefix or suffix (if found) from a string.
Loyc.Collections:
- The
SmartSelectMany
methods ofFWList
,VList
,WList
now acceptIReadOnlyList<>
instead ofIList<>
in order to enable new APIs inLNode
. Technically these changes are breaking but in practice, VLists have few users so breakage should be minimal, and the change seems justifiable since most collections implement both interfaces (IList and IReadOnlyList) andLNode
is the main user ofVList
. - The
AddRange
andInsertRange
methods inFWList
,VList
, andWList
now acceptIReadOnlyList<>
instead ofIList<>
, as a necessary side effect of the change toSmartSelectMany
.
Loyc.Syntax:
- Added new
SelectMany
andRecursiveReplace
methods inLNode
. There are now confusingly similar methodsRecursiveReplace
and thisReplaceRecursive
. The reason for this confusing situation is that if the old method and the new method have the same name, the lambda you pass to it may be ambiguous between the two methods and cause a compiler error, so the names need to be different somehow to avoid this annoyance. LNodeList.InsertRange
andLNodeList.AddRange
now acceptIReadOnlyList<>
instead ofIList<>
.
v2.8.0: July 3, 2020
Potentially breaking changes:
General:
- .NET 3.5 and .NET 4 versions have been dropped, leaving .NET 4.5 and .NET Standard versions.
Loyc.Interfaces:
- Introduce
IIndexed<K,V>
and include it as a base interface ofIListSource<T>
andIDictionaryAndReadOnly<K,V>
. It is also included indirectly inIDictionaryEx<,>
andIDictionaryImpl<,>
. - Add
ITryGet<in K, out V>
and use it all overIListSource<T>
now implementsITryGet<int, T>, IIndexed<int, T>
. This may break existing explicit interface implementations.INegListSource<T>
now implementsITryGet<int, T>, IIndexed<int, T>
This may break existing explicit interface implementations.IDictionaryEx<K,V>
now implementsITryGet<K,V>
(and its base interfaceIDictionaryAndReadOnly<K,V>
implementsIIndexed<K,V>
). This may break existing implementations.
- Change
IIndexToLine
,IIndexPositionMapper
, andILNode
to use new interfacesIHasFileName
,ISourceRange
,ILineAndColumn
, andILineColumnFile
- This allowed
SourceRange
to be moved from Loyc.Interfaces back to Loyc.Syntax - This change also breaks implementors of
ISourceFile
- This allowed
Loyc.Essentials:
- Move disambiguating
TryGet<T>(this IListAndListSource<T> list...)
extension methods toMutableListExtensionMethods
namespace
Loyc.Syntax:
- Introduced
LNodeList
to replaceVList<LNode>
(#100) with automatic implicit conversions between the old and new collection types to minimize breakage.LNodeList
is currently a wrapper aroundVList<LNode>
, but the implementation could (of course) change later. - Rename
CodeSymbols.PtrArrow
toRightArrow
(old name marked Obsolete) - Rename
CodeSymbols._RightArrow
toRightArrow
(old name marked Obsolete) - Rename
LineAndCol
,SourcePos
,SourcePosAndIndex
- Introduce derived class
LineAndColumn
as new name forLineAndCol
- Introduce derived class
LineColumnFile
as new name forSourcePos
- Introduce derived class
LineColumnFileAndIndex
as new name forSourcePosAndIndex
- Introduce derived class
ISourceRange.Start
andISourceRange.End
became extension methods instead of properties, due to limitations of standard C# + 4.5 Framework (on Core I would’ve used default-implemented properties)LNodeFactory.Literal(null)
now produces a compiler (ambigity) error; useLNodeFactory.Null
insteadIParsingService
now acceptsIParsingOptions
instead ofParsingMode mode = null, bool preserveComments = true
arguments. Extension methods have been added to replace the old methods, so existing users should recompile successfully, but if there are any external implementations, they will break.
Changes to LES3 (beta):
- Arbitrary acyclic graphs are supported by the parser (#75). There is still no support in the printer.
@@double-at-literals
have been removed since@@
now means “backreference”.@@inf.d
is now_d"inf"
,@@nan.f
is now_f"nan"
, etc.
- Custom numeric literals in LES3 now implicitly add an underscore to the beginning of their type marker (#76)
- Allow keyword-expressions begin with a comma-separated list of expressions (#85)
- Add support for line continuator
|
(parser only) (#86) - Raised precedence of
**
above prefix operators, to match Python (#87) - Add support for prefix and suffix unary operators marked with apostrophes (#106)
- Add support for backquote suffix operators (shorthand for binary IS operator) (#106)
- Consequently,
123`foo`
is no longer a valid number format
- Consequently,
- Eliminated keyword tokens so that
a .b!T
can parse (#108) - Rearrange lexer to allow
true
,false
andnull
as type markers, which makes it slightly simpler - Bug fix: for proper round-tripping,
%appendStatement
attribute should not cause a statement to be appended if the printer was given thePrintTriviaExplicitly
flag - Move
Les3PrinterOptions
andTokenTree
to separate files. - Tweak grammar of
MLComment
so that an unclosed multiline comment cannot be treated as an operator.
Changes to LES2 precedence table, matching changes in LES3:
- Raised precedence of
**
above prefix operators, to match Python (#87) - Raised precedence of
..
above multiplication operator, to match C# (#87) - A backquoted unary operator whose name start with an apostrophe will pick up the same precedence that it has in LES3.
Other changes:
Loyc.Interfaces:
- Add
ISerializedLiteral
to represent a serialized text form of a literal value (TextValue
andTypeMarker
properties) - Add
ILiteralValue
which adds anobject Value
property toISerializedLiteral
ILNode
(andLNode
) now includesILiteralValue
(TextValue
andTypeMarker
properties)IEither<L,R>
: added twoMaybe.Or
extension methods and twoMaybe.Then
extension methodsEither<L,R>
: addedOr(T defaultValue)
method- Add
UString.IsNull
property - Rename
LCExt
inLoyc.Interfaces
toCollectionSource
to avoid causing ambiguity errors when referring toLCExt
, which also exists inLoyc.Essentials
- Optimize conversion from
UString
toSymbol
- Add
EmptySourceFile.Synthetic
and markEmptySourceFile.Default
as Obsolete.
Loyc.Essentials:
DictionaryExt
: addedGetOrAdd
andAddOrUpdate
extension methods forIDictionary<,>
that behave like the synonymous methods inConcurrentDictionary
LinqToLists
: AddConcatNow()
methodsStringExt.FormatCore
: a recent change toLocalize
broke this method in the case that it is used as theLocalize.Formatter
and you call something like"Hello {name}".Localize("name", "Joe")
. The problem is that for the sake of its own simplicity,Localize
rounds up the number of arguments to 3 so thatFormatCore
always receives at least 3 arguments.FormatCore
was programmed to assume the last N arguments are name-value pairs for some even number N. If you wrote"{0} {name}".Localize(1, 2, "name", "Joe")
, for example, since there is a numeric argument {0} and 4 arguments total, it would assume the named arguments start at index 2. This round-up behavior has been removed. Instead, now it is simply assumes that the first named argument appears after all the numeric ones; if the number of remaining arguments is odd then the last argument is simply ignored.
Loyc.Collections:
- Cancel obsolescence of
BDictionary.AddIfNotPresent
since it actually provides more functionality than theGetOrAdd
extension method (i.e. its boolean result) Bijection<,>
: implementIDictionaryImpl
instead ofIDictionaryAndReadOnly
, thus includingIDictionarySink
- Cancel obsolescence of
BDictionary.AddIfNotPresent
since it actually provides more functionality than theGetOrAdd
extension method (i.e. its boolean result) - In
BDictionary
andDictionaryExt
(IDictionary
extension method): renamedSetAndGet
toGetAndSet
to help convey a sense that it gets the old value before overwriting it. - Implement
ITryGet<K, V>
in a few collections (sometimes implicitly viaIListSource<T>
orIDictionaryEx<K,V>
) - Also implement
IIndexed<K,V>
on several collections (this required no new methods, since collections already have indexers) - Methods of the form
TryGet(K k, ref V v)
are now deprecated ([Obsolete]) - Remove a few implementations of
TryGet
that are no longer needed (or weren’t really needed in the first place)
Loyc.Syntax:
- Various APIs now generally refer to
LNodeList
instead ofVList<LNode>
andmatchCode
macro now emits references toLNodeList
instead ofVList<LNode>
. SourceRange.ToString
now prints line/column numbers, to improve the default way that message sinks print locations in source code.- LES3 parser now records the fact that literals are hex or binary (#46)
- Add
ILiteralValueProvider
and public implementationsLiteralValue
andParsedValue
. There is also an internal implementationSimpleValue<V>
which is used for simple literals that are instantiated with a value V and no source text. - Added new overloads of
LNode.Literal(...)
- Add
IParsingOptions
,ParsingOptions
- Note:
CustomLiteral
will be deprecated soon.LNode
itself now includesTypeMarker
andTextValue
properties which eliminate the need for it. Use the new overloads ofLNode.Literal()
that acceptILiteralValueProvider
orLiteralValue
to produce nodes that provide values in the new properties.
v2.7.2: April 4, 2020
- Add
IMaybe<T>
and tweak the newIEither<L,R>
interface to use it, so that generic variance works with the interface. - Added static
Either<ToL,ToR>.From(Either<L,T>)
method for achieving variance without using the interface. Also addedSelect()
for more complicated conversions. - Tweaked return type of
ArraySlice<T>.GetEnumerator
for likely higher efficiency - Tweaked type of
EmptyEnumerator<T>.Empty
to beIEnumerator<T>
to help C# choose the correct type when it is used with the? :
operator. - Fix potential overflow in
Statistic.Variance()
v2.7.1.4: March 29, 2020
- Belatedly added
Either<L,R>
, a struct that holds “one” of two types (really both, with a boolean indicating which one.) Should’ve added this years ago. TheLeft
andRight
properties return aMaybe<L>
andMaybe<R>
respectively, and there’s aValue
property that returns eitherLeft.Value
orRight.Value
as appropriate. Also added interfaceIEither<L,R>
. - Add
ROLSlice<TList,T>
for slicingIReadOnlyList<T>
types. This is an improvement over Slice_which can't slice BCL lists. - Add
ILineAndColumn
,ILineColumnFile
, andISourceRange
which will be used in breaking changes in v2.8.0. Specifically, theIIndexToLine
,IIndexPositionMapper
,ISourceFile
andILNode
interfaces will returns these interfaces instead of the concrete typesLineAndCol
,SourcePos
, andSourceRange
. - Renamed
AbstractTriviaInjector.AttachTriviaTo
toGetAttachedTrivia
. Technically it’s a breaking change, but in a location obscure enough that probably no one is affected.
v2.7.0.4: March 10, 2020 (re-release of 2.7.0.3)
There are a bunch of breaking changes here, most notably the fact that you need to add a reference to Loyc.Interfaces.dll. This is also a transitionary release: more breaking changes will occur in v2.8.0.0 (semantic version 28.0.0), and it’s probably wise to upgrade just one semantic version at a time.
Apologies: the new Loyc.Interfaces package was broken in NuGet in v2.7.0.3
Regularization of collection interfaces
Several changes were made to the collection interfaces to make the set more complete, consistent and useful.
Each of the three common types of collection (collection, list, dictionary) now has 3-4 interfaces:
- “AndReadOnly” interfaces (
IListAndReadOnly<T>
,ICollectionAndReadOnly<T>
,IDictionaryAndReadOnly<K,V>
) are to be implemented by read-only sequences that want to implement the writable interface (IList<T>
,IDictionary<K,V>
) for compatibility reasons. - “AndSource” interfaces (
ICollectionAndSource<T>
,IListAndListSource<T>
) implement “AndReadOnly” (e.g.IListAndListSource<T>
implementsIListAndReadOnly<T>
) but include an enhanced Loyc interface (IListSource<T>
is the enhanced version ofIReadOnlyList<T>
andICollectionSource<T>
is the enhanced version ofIReadOnlyCollection<T>
). - An “Impl” interface (
IListImpl<T>
,ICollectionImpl<T>
,IDictionaryImpl<K, V>
) is the main interface that editable Loyc collection types should implement. - Extended interfaces (
ICollectionEx<T>
,IListEx<T>
,IDictionaryEx<T>
) are variations that add extra functionality to allow sophisticated collection types to offer higher performance for some operations.
Categories 1-3 exist mainly for the purpose of disambiguation and you should generally NOT create variables of these types, as explained in the documentation of IListImpl<T>
.
Loyc.Interfaces.dll
Added Loyc.Interfaces.dll (available on NuGet) to hold (almost) all interfaces defined in Loyc.Essentials.dll, Loyc.Syntax.dll, etc. Aside from interfaces, enums, and delegates, it also contains a small number of essential structs and classes, most notably Symbol
, UString
, Maybe<T>
, and Localize
. These are types that the interfaces refer to, or that the concrete types themselves depend on. This new library allows you to use Loyc interfaces without taking a dependency on the heavier Loyc.Essentials library. However, this initial release is heavier than I would like at 84KB, as it includes some concrete types that I would rather not include (they are included because Symbol
, UString
, Maybe<T>
, and/or Localize
depend on them, directly or indirectly). Some of these types will be moved back to Loyc.Essentials in a future version.
- Marked
IAddRange
andIListRangeMethods
as<in T>
. - Added
ICollectionSource<T>
and added it as a base ofISetImm
- Added
ICollectionAndReadOnly<T>
,IListAndReadOnly<T>
,IDictionaryAndReadOnly<T>
- Added
ICollectionAndSource<T>
- Added
IDictionaryEx
interface - Added
IOptimize
as common subinterface ofIAutoSizeArray<T>
andINegAutoSizeArray<T>
IListAndListSource<T>
now includesICollectionSource<T>
(which hasCopyTo
andContains
methods.)
Loyc.Essentials
Changes that are most likely to be breaking:
- Rename
BaseDictionary
toDictionaryBase
for consistency. - Eliminated
StringSlice
(UString
now implements its interface,IRange<char>
) - A new namespace
Loyc.Collections.MutableListExtensionMethods
has been added specifically to contain extension methods forICollection<T>
andIList<T>
that are possibly ambiguous when included in the same namespace as extension methods forIReadOnlyCollection<T>
andIReadOnlyList<T>
. This is needed due to a design flaw in .NET and C#. Issue #84 describes the problem in more detail. Most of the extension methods in this namespace are likely to be deprecated soon.
Other changes:
- Removed
ICollectionEx<T>.RemoveAll
which works well enough as an extension method (none of the existing collection types accelerate it, though AList could theoretically do so) - Added extension methods for
IDictionary
andIDictionaryEx
:GetAndRemove
,AddRange
withDictEditMode
parameter - Added
SetExt
extension methods forISet<K>
- Added
IDictionarySink
andIDictionaryAndReadOnly
. - Added extension method
AddIfNotPresent
forIList<T>
- Added extension method
AsReadOnlyDictionary
withSelectDictionaryFromKeys
adapter - Added extension methods for
IDictionary<K,V>
:TryGetValue(K key)
,AddRange
,SetRange
,RemoveRange
- Added more
LinqToLists.Select
extension methods forICollection
/IReadOnlyCollection
, with corresponding adaptersSelectCollection
andSelectReadOnlyCollection
. - Edit
BDictionary
andMMap
to supportIDictionaryEx
. - Edit
InvertibleSet
to support newCopyTo
method. - Added
ByteArrayInString
class, which encodes and decodes BAIS (Byte Array In String) encoding. BAIS preserves runs of ASCII characters unchanged. It is useful for debugging (since ASCII runs are visible) and for conversion of bytes to JSON. - Added
G.DecodeBase64Digit
,G.EncodeBase64Digit
. - Added overloads of
TryPopFirst
andTryPopLast
inUString
andRangeExt
.
Loyc.Collections:
BMultiMap
now acceptsnull
values for the key and value comparator. A null key comparer means “use the default key comparer”, while a null value comparer means “pretend all values are equal”. If you use the(null, null)
constructor, you should avoid callingthis[key].Remove(value)
orthis[key].Contains(value)
, since these methods will treat any value as a match.
Loyc.Syntax:
- Replaced
#trivia_
prefix with%
(issue #61) - LES2 and LES3 precedence tables have changed (issue #87)
- LES3: Support
:
as prefix operator (not supporting it earlier was accidental) - LES3: Add
initially
(alongsidefinally
) as a continuator - Added
LNode.FlattenBinaryOpSeq()
- Added
CodeSymbols.Matches
('=~
operator) - Rename
#usingCast
to'using
(CodeSymbols.UsingCast
) - Rename
#namedArg
to'::=
(alternate name:<:
) (the nameCodeSymbols.NamedArg
is unchanged) - Rename
#of
to'of
(CodeSymbols.Of
) (issue #96) - Rename
#tuple
to'tuple
(CodeSymbols.Tuple
) (issue #96) - Rename
#is/#as/#cast
to'is/'as/'cast
(CodeSymbols.Is/As/Cast
) (issue #96) - Rename
#default
to'default
(CodeSymbols.Default
) even for the label form,default:
(issue #96) - Rename
#sizeof/#typeof
to'sizeof/'typeof
(CodeSymbols.Sizeof/Typeof
) - Rename suffix operators (
x[], x++, x--
) to have a consistent prefix of'suf
(issue #96) - Rename
CodeSymbols.Neq→NotEq
,NodeStyle.Statement→StatementBlock
- Split
#new
into'new
operator and#new
attribute (CodeSymbols.New
andCodeSymbols.NewAttribute
) - Split
#switch
into'switch
operator and#switch
statement.CodeSymbols.Switch
was split intoCodeSymbols.SwitchStmt
andCodeSymbols.SwitchExpr
. Note: EC# parser does not yet support the switch expression. - Increase block size in
BaseLexer
, mainly to reduce branch mispredictions - Deleted
IToLNode
.ILNode.ToLNode
is now an extension method only, not a core part of the interface.
v2.6.9: January 21, 2020
Loyc.Essentials:
- Enable compiler optimizations (oops)
Loyc.Collections:
- ALists:
- Added
CountSizeInBytes()
methods in all variants of AList (see alsoListBenchmarks.CountSizeInBytes
methods implemented forList<T>, Dictionary<K,V>, SortedDictionary<K,V>
, andLinkedList<T>
) - Added convenience method
SparseAList<T>.AddSpace(count)
AList
andSparseAList
: Change how node splitting works for better bulk-add performance. Specifically, when splitting to add an item to the end of a node, the new left node will be 100% full and the right node will contain only one item, so that repeated calls to Add will naturally build a sequence of full nodes.- Optimize AList insertions by redistributing adjacent children in bulk
- Optimize
AList.AddRange
- Optimize
AList<T>.this[index]
for small lists - Switch internal list from
InternalDList
toInternalList
(InternalDList
may have slightly faster insert/remove, but other operations are faster, most importantlythis[int]
.) - Default inner node size is now 64 to match leaf size
- Node classes: Add debug/test properties
Children
andLeaves
- Hide unimportant properties in debugger
- Added
- Optimize enumerators of InternalList, InternalDList and AList
- InternalList:
yield return
measured to be slow. Avoided it. - DList/AList: Factor out “rare” parts to encourage inlining.
- InternalList:
Loyc.Utilities:
- Add
AListSumTracker
andAListStatisticTracker
classes with extension methods onAListBase<K,T>
v2.6.8: May 12, 2019
- Introduced .NET Standard 2.0 versions. NuGet package now contains four builds: .NET 3.5, .NET 4.0, .NET 4.5 and .NET Standard 2.
v2.6.7: March 17, 2019
- LES: Make
* /
and<< >>
miscible. Precedence of<< >>
is between+ -
and* /
sox << 1 - 1
means(x << 1) - 1
. - LES: Keep
& | ^
immiscible with== != > <
, but give them higher precedence than comparison operators in LES3 only.
v2.6.6: March 16, 2019
- Loyc.Syntax issue #61:
%
is now recognized as a trivia marker byCodeSymbols.IsTriviaSymbol
,LNode.IsTrivia
,LNodeExt.IsTrivia
. - LES: Add triangle operators
|> <|
- LES bug fix: fix precedence of
..<
to match..
- LES3: Allow nonparenthesized attributes to have an argument list (e.g.
@attr(args) expr
)
v2.6.5: February 17, 2019
Loyc.Syntax:
- Design fix: Change
ILNode.Target
to have a more appropriate return type. - Added convenience method for printing
ILNode
inLes2LanguageService
andLes3LanguageService
v2.6.4: September 18, 2018
- Loyc.Collections: Add support for priority queues:
MinHeap
,MaxHeap
,MinHeapInList
,MaxHeapInList
.
v2.6.3: July 23, 2018
Loyc.Syntax:
- Edit the default token-to-string method
TokenExt.ToString()
so it works more sensibly on non-LES tokens that are still based onTokenKind
. - Swap int value of
TokenKind.Spaces
withTokenKind.Other
so that lexers oblivious toTokenKind
will typically have integer values in theTokenKind.Other
region. Token.ToSourceRange
andToken.Range
were duplicate methods; removed the first.
v2.6.2: October 1, 2017
- LESv3: Tweaked the precedence of
->
and<-
. These operators can now be mixed with logical and bitwise operators (|
,&&
,|
,^
,&
,==
,>
, etc.) and are right-associative. - v2.6.2.1: Bug fix in
SparseAList.NextHigherItem
,NextLowerItem
whenindex
is negative orint.MaxValue
.
v2.6.1: September 28, 2017
LES
- Made several changes to LESv3 and LESv2 as discussed in issue #52:
- v3: Added token lists like
'(+ x 1)
to allow custom syntax (comparable to s-expressions) - v3:
.dotKeywords
will be stored as#hashKeywords
- v3:
#
is officially an ID character (but was already treated as such) - v3:
.keyw0rds
can now contain digits - v3: Hexadecimal and binary floating-point numbers no longer require a
p0
suffix - v2/v3: The precedence of non-predefined operators will now be based on the last punctuation character, rather than the first punctuation character. If applicable, the first and last punctuation character still determines the precedence (e.g.
>%>
will still have the same precedence as>>
) - v3: The precedence of
::
has been raised to match.
- v3:
x*.2
will now be parsed asx * .2
rather thanx *. 2
, but0..2
will still be parsed as0 .. 2
. - v2/v3: The precedence of arrow operators like
->
has been lowered. The parser treats their precedence sa above&&
but below| ^
- v3: Modified the set of continuators.
- v3: Added token lists like
v2.6.0: August 30, 2017
Loyc.Essentials
- Added
G.True(T)
,G.True(Action)
,G.Swap(ref dynamic, ref dynamic)
Loyc.Syntax
- LESv2/v3: Operator
..
now has precedence above+- * /
. - LESv2/v3: Change
!!
from an infix to a suffix operator based on Kotlin’s!!
operator. Add!.
operator with precedence of.
. - LESv3: Negative numbers are now written
n"-123"
instead of-123
, (see blog post). Lexer tentatively accepts −123 (en dash). - LESv3: Enable printer to print
- -a
anda. -b
instead of-
’-(a)
anda.(@@ -b)
. - Changed symbols
#[]
,#[,]
,#in
to'[]
,'[,]
,'in
for consistency with other operators.
v2.5.1: January 19, 2017
Loyc.Syntax
- Bug fix:
ParsingService.ParseFile
could causeIOException
that says “Cannot access a closed file” BaseLexer
/BaseParser
: Renamed theError
method that is called byMatch
/MatchExcept
toMatchError
and added an anti-infinite-loop mechanism.
v2.5.0: January 13, 2017
Loyc.Essentials
- Renamed
ISinkCollection
=>ICollectionSink
,ISinkArray
=>IArraySink
,ISinkList
=>IListSink
for consistency withIMessageSink
andIListSource
Localization
- Added
Localize.UseResourceManager()
- Methods of
Localize
that accept a symbol representing the string to translate were renamed fromLocalized
toSymbol
. - Introduced “auto-fallback” behavior in
ThreadLocalVariable
.Localize.Localizer
andFormatter
use it to mitigate .NET’s lack of thread-local propagation.
Message sinks (logging)
MessageSink
: Added extension methodsError
,Warn
,Debug
, etc. Added customizableContextToString
delegate to replaceLocationString
. AddedWithContext
.- Removed setter of
MessageSink.Default
(useSetDefault
instead) - Wrappers
SeverityMessageFilter
andMessageSplitter
now have an optionalTContext
type parameter. ConsoleMessageSink
,TraceMessageSink
andNullMessageSink
have singletonValue
properties now.- Added
MessageSinkWithContext<TContext>
wrapper forIMessageSink
. - Changed argument order of
TraceMessageSink
for consistency with other classes - Removed
Severity.Detail
, replacing it with a separateDetail
version of each member ofSeverity
. - Added
includeDetails
parameter to constructor ofSeverityMessageFilter
in the hope of drawing attention to the possibility of accidentally excluding details, while making some older code behave correctly at the same time. - Renamed
MessageSplitter
toMessageMulticaster
. Renamed some method parameters.
v2.4.2: January 8, 2017
- Rename
LinqToCollections
toLinqToLists
. - Rename some rarely used members of
Severity
to form a group of “frequency signals”:Common
,Uncommon
,Rare
. - Add extension methods for
IServiceProvider
/IServiceContainer
(System.ComponentModel.Design
) in static classLoyc.ServiceProvider
.
LESv3 (prerelease) changed:
- Eliminated block-call expressions
- Eliminated single-quoted operators
- Keywords now have a separate token type
- Syntax of keyword expressions changed. Initial expr now optional; newline allowed before braces/continuators; any expression is allowed after a continuator.
- Parser: introduced token lists (
VList<LNode>
) and eliminated token tree literals (TokenTree
) - Parser: edited to reduce output size
- Parser: tweaked error handling
- Parser:
@@
now acts like an attribute instead of only being allowed after(
- Parser now requires a space after word operators and “combo” operators
v2.4.0.1: December 26, 2016
- Changed LES generic syntax so that
a.b!c
is parsed asa.(b!c)
instead of(a.b)!c
.
v2.3.3: December 21, 2016
- LESv3: added syntax
(@@ expr)
to group an expression without adding#trivia_inParens
- LESv3 parser now requires whitespace after an attribute.
- Bug fix: LES2 and LES3 printers now print
@`'.`(a, -b)
correctly. - Bug fix in
LNodeExt.MatchesPattern
:Foo(...)
did not match pattern$x(...)
- Renamed
IReferenceComparable
toIReferenceEquatable
- Moved
Reverse()
extension method toLinqToCollections
.
v2.3.2: December 12, 2016
- Changed return type of
MessageSink.SetDefault
as intended to be done earlier. - Rename
MathF8
,MathF16
, etc. toMathFPI8
,MathFPI16
, etc.
v2.3.1: December 11, 2016
Loyc.Essentials was split into Loyc.Essentials and Loyc.Math. Loyc.Math contains
- Most of the math stuff, including
Math128
,MathEx
, the fixed point types (FPI8
,FPI16
, etc.),Maths<T>
, and the math helper structs (MathI
,MathD
, etc.) - Most of the geometry stuff, including
BoundingBox<T>
,LineSegment
,Point<T>
, andVector<T>
NumRange<Num,Math>
However, Loyc.Essentials retains most of the math interface definitions.
Loyc.Syntax and Loyc.Collections reference Loyc.Essentials but not Loyc.Math.
Some static classes were split between Loyc.Essentials & Loyc.Math:
Range
was split. The classRange
went to Loyc.Math and contains methods that returnNumRange
. TheIsInRange
andPutInRange
methods went classG
inLoyc.Essentials
MathEx
was split. Most methods remained inMathEx
which went to Loyc.Math. The methodsSwap
andSortPair
went to classG
. WhileCountOnes
,Log2Floor
,ShiftLeft
andShiftRight
are still inMathEx
, certain overloads are implemented inG
or duplicated inG
because they are needed by Loyc.Collections and Loyc.Syntax.
Other changes:
- The rarely-used
CPTrie
types andKeylessHashtable
were moved from Loyc.Collections to Loyc.Utilities - Some geometry stuff was moved from Loyc.Utilities to Loyc.Math.
- The
ParseHelpers
class was split between Loyc.Essentials and Loyc.Syntax, with the conversion-to-string stuff going toPrintHelpers
in Loyc.Essentials and the conversion-from-string stuff going toParseHelpers
in Loyc.Syntax. - Certain classes like Localize were changed to follow the Ambient Service Pattern more closely.
v2.2.0: December 7, 2016
-
Tweaked Ambient Service Pattern
- Renamed
MessageSink.Current
toMessageSink.Default
- Introduced
IHasMutableValue<T>
- Renamed
PushedTLV<T>
toSavedValue<T>
, now operates onIHasMutableValue<T>
- Removed
G.PushTLV()
- Renamed
v2.1.0: December 3, 2016
- Eliminated
LNodePrinter
delegate, replacing it withILNodePrinter
.LNodePrinter
now holds standard extension methods ofILNodePrinter
. IParsingService
no longer includes a printing capability; language services implementILNodePrinter
separately.- Renamed
LesNodePrinter
toLes2Printer
,LesParser
toLes2Parser
, and so on forLesLexer
and LESv2 unit tests. LinqToCollections
: AddedTakeWhile()
andSkipWhile()
extension methods for IList,
IListSource,
INegListSource`.- Added extension method
INegListSource<T>.TryGet(index)
- Added one-param constructor to
MacroProcessor
and switched order of params to other constructor for harmony.
v2.0.0: November 23, 2016
IParsingService.Print
has changed as follows:- Old:
string Print(LNode node, IMessageSink msgs, object mode, string indentString, string lineSeparator);
- New:
string Print(LNode node, IMessageSink msgs, ParsingMode mode, ILNodePrinterOptions options);
- Old:
- Introduced
ILNodePrinterOptions
interface andLNodePrinterOptions
class. This interface is shared among all languages; each language also has its own options type with extra options. The options object eliminates the need for users to create printer objects, so the constructors of the LES/EC# printers have gone internal. - We now avoid using
SourcePos
for the context ofIMessageSink.Write()
;SourceRange
is now used instead. IParsingService.Parse
now preserves comments by default, if possible.LNode.Equals
now has aCompareMode
parameter which can be set to ignore trivia.- Bug fix:
InParens()
no longer creates trivia with a range covering the entire node (it confuses the trivia injector) - Bug fix:
IndexPositionMapper
unit tests were not set up to run, and it was broken - Eliminated
NodeStyle.Alternate2
; addedNodeStyle.InjectedTrivia
which is applied to trivia attributes byAbstractTriviaInjector
. LesNodePrinter
now includes context when an unprintable literal is encountered.- Introduce generic base interfaces of
IMessageSink
.
v1.9.6: November 23, 2016
- Eliminated rarely-used optional arguments of some
LNode
creation methods. LinqToCollections
: AddedSelect(this IList<T>, ...)
andFirstOrDefault(this IList<T>, T)
.- Bug fix in
LNodeFactory
that messed up trivia injector for EC#
v1.9.5: November 14, 2016
- LESv2 and LESv3 can now preserve comments and newlines and round-trip them to their printers.
- Added a few extension methods, most notably
StringBuilderExt
. - Introduced
ILNode
interface for objects that want to pretend to be Loyc trees. AddedLNode.Equals(ILNode, ILNode)
. - LES printers can now print
ILNode
objects directly, but most other functionality still requiresLNode
and this is not planned to change. - Changed the way trivia works (new
#trivia_trailing
attribute) and improved the way the LES2 printer prints trivia - Tweaked the way the trivia injector talks to its derived class.
IParsingService
: Added overloadPrint(IEnumerable<LNode>, ...)
.LNodeFactory
: AddedTriviaNewline
,OnNewLine()
LNodeExt
: AddedGetTrivia()
EscapeC
&EscapeCStyle
: ChangedEscapeC.Default
; addedUnicodeNonCharacters
andUnicodePrivateUse
options. Single quotes are no longer escaped by default but non-characters and private characters are.- Eliminated
SelectNegLists
andSelectNegListSources
, which most likely no one was using. RenamedNegView
toAsNegList
for consistency withAsList
etc. Added methods toLinqToCollections
forINegListSource
. - Renamed
Front
toFirst
andBack
toLast
in theRange
interfaces. - Changed API of
Les3PrettyPrinter
- Updated LESv3 printer to support most of the recent changes to LESv3. Semicolons are no longer printed by default.
- LESv3 now allows
\\
to end single-line comments, to make it easier for the printer to avoid newlines in illegal places.
v1.9.4: October 25, 2016
IParsingService
: addedCanPreserveComments
property and comment preservation flag when parsing- Improved trivia injector (
AbstractTriviaInjector
); addedNodeStyle.OneLiner
- Added
UString.EndsWith()
v1.9.3: October 12, 2016
- Fixed a race condition in
SymbolPool.Get
(issue #43) - Added helper classes for preserving comments (
TriviaSaver
,AbstractTriviaInjector
,StandardTriviaInjector
) - Changed syntax of LESv3, partly in response to the survey results: Newline is now a terminator; added
.keywords
; removed juxtaposition operator; added new kinds of infix operator based on identifiers (e.g.x s> y
,a if c else b
); colon is allowed as a final suffix on any expression. (printer not yet updated)
v1.9.2: September 3, 2016
- Introduced LESv3 parser, printer, unit tests and parsing service (
Les3LanguageService
), plus a pretty-printer (Les3PrettyPrinter
) with colored HTML and console output. - Add
BigInteger
literals to LESv2 and LESv3 (Issue #42) viaz
suffix - Tweaked LESv2 and LESv3 precedence rules. Most code will be unaffected; as LES has few users, it seems better not to fork
LesPrecedence
andLesPrecedenceMap
for v3. LNode
: changed definition ofHasSpecialName
due to LESv3 idea to use ‘.’ to mark keyword-expressions.LNode:
addedPlusAttrBefore()
,PlusAttrsBefore()
NodeStyle.DataType
is unused, so changed name toReserved
(for future use)ParseHelpers
:EscapeCStyle
/UnescapeCStyle
: added support for 5-digit and 6-digit unicode code points and changed APIs to beUString
-centric.- Added
StringExt.AppendCodePoint
,UString.Left
,UString.Right
. AllowUString -> Symbol
conversion. Fixed bugs inStringExt.EliminateNamedArgs
. Eliminated bitwise-not-on-error behavior whenUString
decodes a code point, because the behavior wasn’t wanted in LES parser. - Add
ParseHelpers.IntegerToString
andParseNumberFlag.SkipSingleQuotes
- Tweaked
NodeStyle
to have named values for common literal styles (hex, triple-quoted, etc.) - Bug fix in
MiniTest
: failure was ignored by overloads that took a string message
v1.9.0: July 26, 2016
- Names of operators in LES and EC# now start with an apostrophe (
'
) - Also,
suf
in operator names changed from being a prefix to a suffix - Renamed
CodeSymbols.*Set
toCodeSymbols.*Assign
- Removed ‘Python mode’ from LES; tweaked the lexer
v1.8.1: June 13, 2016
- Bug fix in LES printer:
/*suffix comments*/
were printed incorrectly (with no content).
Minor changes:
- Loyc.Essentials: Changed illogical return value of
LCInterfaces.IndexOf()
to be nullable. - Deleted
G.Assert
in favor ofContract.Assert()
compatibility method in .NET 3.5 builds - Bug fix:
IndentTokenGenerator
(and LES parser) crashed in case of empty input - Bug fix in
LNode
: implementedIReadOnlyCollection.Count
v1.7.6: 2016
- Add extension methods for
LNode
:Without
,WithoutAttr
v1.7.5: April 29, 2016
- VLists: added
SmartSelectMany
; replaced dedicatedWhereSelect
with one based onTransform
; deletedSelect<Out>
; renamedWhere
toSmartWhere
. Replaced a fewPredicate<T>
withFunc<T, bool>
for consistency with LINQ-to-Objects
v1.7.4: April 18, 2016
IParsingService
: changedinputType
parameters to useParsingMode
, a new extensible enumeration. Added additional modes.- Helper methods for parsing and printing tokens and hex digits have been moved from
Loyc.G
toLoyc.Syntax.ParseHelpers
- Renamed
USlice(this string...)
toSlice
- Removed
G.Pair
which was a duplicate ofPair.Create
v1.7.3: April 18, 2016
- Bug fix in MiniTest: some assert methods ignored user-defined message
- Bug fix in
LastIndexWhere()
extension method
v1.7.2: April 1, 2016
- Extension methods: added
Slice(this NumRange)
, and non-allocating overloads ofIsOneOf()
LNode
: Added newReplaceRecursive
overload that can delete items.LNode
perf: All call nodes now cache their hashcode.
v1.6.0: Mar 9, 2016
- Renamed
Range.Single
=>ListExt.Single
,MathEx.InRange
=>Range.PutInRange
,In.*
=>Range.*
,Range.Excl
=>Range.ExcludeHi
,Range.Incl
=>Range.Inclusive
v1.5.1: Mar 5, 2016
- Removed
IntRange
; replaced byNumRange<N,M>
to support the EC#lo..hi
andlo...hi
operators; addedFloor
andCeiling
to Maths types as needed byNumRange
.
v1.5.0: Mar 2, 2016
- Renamed
RVList
toVList
, and renamedRWList
toWList
. LNodeFactory
: RenamedF._Missing
toF.Missing
(and the less-oft-usedLNodeFactory.Missing
to Missing_ to avoid a name collision).LNode
: Added overloads: ofLNode.Calls(string)
,LNode.IsIdNamed(string)
,LNode.List(IEnumerable<LNode>)
.LNodeExt
: AddedWithoutNodeNamed
extension method.- Renamed
LineAndPos
toLineAndCol
v1.4.1: Feb 28, 2016
- (jonathan.vdc) LES: Added named float literals for infinity and NaN.
v1.4.0: Aug 25, 2015
- Renamed
MessageHolder.Message
toLogMessage
(top-level class); introduced a wrapper exceptionLogException
.
July updates: forgot to raise version number
- LESv2: working and mostly tested! All LES-based parsers, lexers and unit tests throughout the codebase have been updated to use the new syntax. JSON compatibility was also added.
- Combined
TokenKind.Number
,TokenKind.String
,TokenKind.OtherLit
into a single thing,TokenKind.Literal
, and removed all distinctions between literals from the parsers for LES, EC# and LLLPG. - Split the symbol for indexing and array types into two separate symbols
_[]
(IndexBracks) and[]
(Array), where previously[]
(Bracks) was used for both. - Bug fix: updated
LNodeFactory
,StdSimpleCallNode
,StdSimpleCallNodeWithAttrs
to support custom source range forTarget
. - LES: Parser rewritten into a completely whitespace-agnostic version with a “juxtaposition operator” instead of superexpressions. However, I don’t think I’ll keep this version, it’s too limiting.
- LES: Removed
TokensToTree
from lexer pipeline. - LES: Language made simpler by removing all operators containing backslash.
v1.3.2: Jun 21, 2015
- Refactored LES parser to use the new
BaseParserForList
as its base class. Added propertyBaseParser.ErrorSink
to matchBaseLexer
(to eliminate the need forParserSourceWorkaround
) - Moved all unit tests from LoycCore assemblies to LoycCore.Tests.csproj (renamed from Tests.csproj). Savings: about 20K in Loyc.Essentials, 61K in Loyc.Collections, 55K in Loyc.Syntax, 25K in Loyc.Utilities.
- LES (v1): “Python mode” (ISM) installed and tested
- Added
IIndexToLine
as part ofILexer<Token>
because certain lexers don’t have aSourceFile
, andBaseLexer
implementsIndexToLine
anyway - Implemented and tested
IndentTokenGenerator
- Changed
IDeque
interface to useMaybe<T>
and eliminated most of the extension methods list.TryGet(i)
extension methods for lists now returnMaybe<T>.NoValue
instead ofdefault(T)
on fail- Defined
IHasValue<T>
- Moved the benchmarks to their own project, LoycCore.Benchmarks.
- Bug fix:
NullReferenceException
inAListIndexer.VerifyCorrectness
v1.3.1: Jun 14, 2015
ILocationString.LocationString
changed toIHasLocation.Location
; now returnsobject
for greater generality- Some names changed in
Maybe<T>
. AddedOr()
,AsMaybe()
&AsNullable()
. ILexer<Token>
now has a type parameter;NextToken()
now returnsMaybe<Token>
instead ofToken?
so thatToken
is not required to be a struct.- Added
BaseILexer<CharSrc,Token>
, and installed it as the new base class ofLesLexer
- Added
BaseLexer.ErrorSink
property; default behavior is still to throwFormatException
LesLexer
no longer producesSpaces
tokens.LesNodePrinter
bug fix: /comments/ were printed twice, once as comments and once as attributes- Bug fix in
ArraySlice.Slice(), ListSlice.Slice()
v1.3.0: May 27, 2015
I’m not attempting to make release notes this far back, although the vast majority of code and features were written well before v1.0.