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.IsSpecialNamenow returnstrueif 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.Unwrapmethods - Bug fix in LNode:
WithRangecould delete attributes in special cases.
Loyc.Collections:
- Potentially breaking:
INegArraynow 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 areTypes. It behaves almost like a standard dictionary, except that theTryGetValuemethod 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:
IndexOfMinandIndexOfMaxnow give you the minimum item instead of the minimum result of the selector. (This allowsMinItemOrDefaultandMaxItemOrDefaultto be simplified by being written in terms ofIndexOfMinandIndexOfMax)MinOrDefaultandMaxOrDefaulthave been renamed toMinItemOrDefaultandMaxItemOrDefaultto better indicate how they differ from the standardMinandMaxextension methods.- Added
MaxItemandMinItemextension methods
Other changes:
- Implement
ITupleonMaybe,PairandTriplet,Equals/GetHashCode/ToStringonMaybe<T> Either<L,R>,IEither<L,R>,Pair<A,B>andTriplet<A,B,C>now implementSystem.Runtime.CompilerServices.ITuple(Eitherconsiders 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
ListChangingevent inINotifyListChanging<T>and in all classes derived fromAListBasewas 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.DictionaryWithChangeEventsandCollectionWithChangeEvents). - Added interfaces
ILast,IMLast,IFirst,IMFirstfor immutable and mutableFirstandLastproperties of collections.IDequeinherits from these instead of having First/Last properties;IFRangenow inherits fromIHasFirst;IBRangenow inherits fromIHasLast;IMFRangenow inherits fromIHasMFirst;
- Added
IIndexedSink<in K, in V>interface as base interface ofIDictionarySink<in K, in V> - Altered
ISourceRangeto useIIndexRangeas its base interface - Added
ISource<T>as a new base interface ofIListSource<T>. Because of this, all implementations ofIListSource<T>now require anIsEmptyproperty. - Added
IListAndListSourceandICollectionImplas base interfaces ofIListImpl<T> - Renamed
IHasXxxinterfaces toIXxx. Rationale: in v28 there were several interfaces likeIContains,ICount,IPush,IOptimizeandIIsEmptythat are simply named after the method or property they contain. There were also several interfaces with anIHaspattern, 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
IHasLocationtoILocation(old name is derived and marked obsolete) - Renamed
IHasValueto `IValue (old name is derived and marked obsolete) - Renamed
IHasMutableValuetoIMValue(old name is derived and marked obsolete) - Renamed
IHasFileNametoIFileName(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 anIsEmptyproperty and aTryGetmethod in addition toTryGetValue.TryGetis better thanTryGetValuebecause it supports variance, e.g.ITryGet<object, Symbol>can be assigned to a variable of typeITryGet<string, object>. - Added new
ILineToIndexinterface as base interface ofIIndexPositionMapper - Make appending
UStringtoStringBuildermore discoverable by making non-staticAppendTomethod (it cannot be anAppendextension method onStringBuilderbecauseStringBuilder.Append(object)takes priority.) The old static methodAppendis marked Obsolete. - Added
ISparseListSource<T>.Slice()method that must returnISparseListSource<T> - Simplified
IListSource<T>.Slicereturn 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 toIListSourcerequired 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>.Valueis assigned tonew Repeated<T>(default(T), 0)so that the rest ofEmptyList<T>could be deleted.
Loyc.Collections:
- Renamed
AddIfNotPresentmethods 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.ToStringStrategyandToken.SetToStringStrategynow useFunc<Token, ICharSource, string>instead ofFunc<Token, string>to allow the original token text to be obtained from source code.Token.ToLNodewas 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
Valueproperty.WithValuecan 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
CustomLiteralas [Obsolete] - Added
ILNodePrinterOptions.LiteralPrinterproperty of typeILiteralPrinterso users can more fully control the printing of literals - Rename
ISerializedLiteraltoIUninterpretedLiteral. The old name still exists and is marked [Obsolete]. LNode.Equalsnow includesTypeMarkerin comparisons between string literals.- LES2 and 3 now recognizes fewer type markers than the previous version: markers using capital letters
_U,_UL,_F,_Dand_Zare 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 inCodeSymbolsand to avoid confusion, sinceListdoes not create a JavaScript-style list (the symbolCodeSymbols.Arrayis assigned to that purpose.) The old name still exists and is markedObsolete, but will be removed in the future. NodeStyle: increaseBaseStyleMaskfrom 3 to 4 bits and deprecateOneLiner- Renamed
PrinterStatetoLNodePrinterHelper, which implements the new interfacesILNodePrinterHelperWithRevokableNewlines<LNodePrinterOutputLocation, LNodePrinterHelper>andILNodePrinterHelper. The old name still exists (as a derived class) and is marked Obsolete. LNodePrinterHelper.CommitNewlinesreturnsthisinstead ofint.- Class
DefaultNodePrinterWriterhas been deleted, as EC# and LES now useLNodePrinterHelperinstead. - Removed
Les2Printer.Writerproperty and renamedParsedValuetoLiteralFromParser- 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.UnescapeStringandUnescapeQuotedStringwere moved toLes3Lexer(the old name still exists and is marked [Obsolete])-123is no longer a negative number. As in LES3,-123is 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**xused to mean(-2)**xwhereas-a**xmeans-(a**x).
Non-breaking changes
Loyc.Interfaces
- Added
ILiteralParserandILiteralPrinterinterfaces, which are implemented byLiteralHandlerTablein Loyc.Syntax. - Added interfaces for observable collections:
INotifyListChanged<T, TCollection>which encapsulates aListChangedeventINotifyListChanged<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 implementsICountandIIsEmpty. - Added
TryPopFirst()andTryPopLast()methods inUString - Added
ListChangeInfo<T>.OldItemsproperty. Also added support for this property to the ALists (classes derived fromAListBase<T>) - Added
IIndexRangeinterface (with integer propertiesStartIndex,EndIndexandLength), and a simple implementation instruct IndexRange(with methodsOverlaps,ContainsandGetRangeOfOverlap). - 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
ILogMessageinterface thatLogMessageimplements - Added static
MessageSink.Write(this IMessageSink<object>, ILogMessage)andMessageSink.Write(this IMessageSink<object>, LogMessage)methods - Added overload of
G.Withextension 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, andToStringinEither<,> EmptySourceFile.Synthetic.FileNameis 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
AsSinkextension methods with helper classesCollectionAsSink,DictionaryAsSinkandListAsSink - Added
NullMessageSink.Write(Severity)overload and fixed theCountandErrorCountproperties, whose values were the reverse of each other. - Added new overloads of
WithoutPrefixandWithoutSuffixforUStringinStringExt- Added
StringComparisonparameter 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>.BufferedCountproperty - Added disambiguating overload
DictionaryExt.TryGetValue(this IDictionaryAndReadOnly...) - Added
SparseListSourceSlicewhich can be used to implement the newSlicemethod inISparseListSource<T>(and is used bySparseAList<T>). - Bug fix: when
Assert.AreEqualfailed, 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,EndIndexproperties
Loyc.Syntax:
- Add general-purpose classes called
LiteralHandlerTableandStandardLiteralHandlersfor literal parsing and printing. Also, I made a video about these classes. - Added
LNodeRangeMapperclass, the importance of which is explained by another video - Other changes to
Token:- Added
TextValuemethod,TypeMarkerproperty, and corresponding constructors that make them work. Tokens that support this method are called “uninterpreted literals” and theirValueis 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.Lengthis now 32 bits instead of 24 (thoughLNode.Range.Lengthis 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 Tokenconverts implicitly toIndexRange
- Added
- Other changes were made to support new literal system in LES2 and LES3:
Les2LexerandLes3Lexerno 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.ErrorSinkso that it can report literal parsing errors. LNode.Equalsnow includesTypeMarkerin comparisons between string literals. TheTextValues 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). IfEqualsis called with the newCompareMode.TypeMarkersflag, 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 newCanPrintAsNumberfunction 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.Unknownas its implicit source file - Added optional
NodeStyle style = NodeStyle.Defaultargument 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 theRangeproperty by choosing an appropriate range for the requested kind of operator or call.- Use
CallPrefixfor ordinary calls with argument lists, e.g.Method(x, y) - Use
CallPrefixOpfor prefix operators and calls that start with an identifying token and end with a child node, e.g.-xorfrom x in y - Use
CallInfixOpfor binary and ternary infix operators, e.g.x + yorc ? a : b - Use
CallSuffixOpfor suffix operators, e.g.x++ - Use
CallBracketsfor lists delimited by outer tokens, e.g.{ x; y; }or(x, y)
- Use
- Added a new overload of
DotandBracesthat are used similarly to the new methods above - As mentioned earlier,
Literal(Token)behaves differently and methodsLiteralFromValueOf(Token)andUninterpretedLiteral(Token)were added. LNodeFactorynow avoids returning nodes with invalidendIndex- Bug fix:
InParenscreated a node with an incorrect value forRange.EndIndex
- Added no-arg
- Changes to trivia injectors:
AbstractTriviaInjectorno 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%appendStatementtrivia. WhileOneLinerwas an interesting optimization, it caused problems in practice when interacting with macros, and therefore several macros had code to strip out theOneLinerstyle from their output. By not usingOneLiner, this will no longer be necessary. Support forOneLinerhas also been stripped out of Enhanced C#, LES2 and LES3.- Renamed
AbstractTriviaInjector.GetAttachedTriviatoGetTriviaToAttachto be less confusing - Tweaked
AbstractTriviaInjectorto better handle “reified” newlines, i.e. newlines that are represented as identifiers like'\n. Given a stream of identifiers like { Ann,'\n, Bob } where'\nis also a newline in the trivia stream, the trivia injector used to produce Ann, @%appendStatement@(%trailing(%newline))'\n, @%appendStatementBob but now it will produce Ann, @%appendStatement'\n, Bob - If there are two blank lines between nodes
A\n\nB,AbstractTriviaInjectornow 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\nBbecomes(@`%trailing`(`%newline`, `%newline`) A; @`%newline` B)or a single newline (A\nBbecomes(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> OpenMacroNamespacesproperty - Add
PreviousSiblingsandAncestorsAndPreviousSiblingsproperties toIMacroContext - Return type of
Ancestorswas expanded fromIReadOnlyList<LNode>toIListSource<LNode>(this allows moreLinqToListsmethods to work on it. Arguably the right solution is to write moreLinqToListsmethods, 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.SaveRangeproperty with support in EC#, LES2 and LES3 (in addition toLiteralPrinterproperty mentioned earlier) BaseParserForList<,>andBaseParserForList<,,>have new constructors that accept aFunc<Token,Token> getEofTokeninstead 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=0which 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 fromSourceRangetoIndexRange. - 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.
123myNumberormyString"hello". As in LES3,StandardLiteralHandlers.Valueis 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%appendStatementtrivia 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.Unknownmistakenly had the same value asTokenType.EOFwhich 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
Les2PrecedenceMapandLes3PrecedenceMap.
v2.8.3: November 16, 2020
Loyc.Interfaces:
- Bug fix:
default(UString).ToString()no longer throwsNullReferenceException
Loyc.Essentials:
- Add
G.WordWrapfunctions, 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:
ComputeConvexHullreturned nothing if the input was a single point; it now returns that point.
Loyc.Syntax:
- Add
<>operator to LES (#87) - Added
LNodeExtextension methods:LNode.Unsplice,LNodeList.IncludingAttributes,LNode.IncludingTriviaFrom. In macros,IncludingTriviaFromshould 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
ParsingOptionsclass to implementIParsingOptions(it was unintentionallyinternalin the previous release) LNodeList.AddRangenow 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
stringextension methodsWithoutPrefixandWithoutSuffixfor trimming off a specific prefix or suffix (if found) from a string.
Loyc.Collections:
- The
SmartSelectManymethods ofFWList,VList,WListnow 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) andLNodeis the main user ofVList. - The
AddRangeandInsertRangemethods inFWList,VList, andWListnow acceptIReadOnlyList<>instead ofIList<>, as a necessary side effect of the change toSmartSelectMany.
Loyc.Syntax:
- Added new
SelectManyandRecursiveReplacemethods inLNode. There are now confusingly similar methodsRecursiveReplaceand 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.InsertRangeandLNodeList.AddRangenow 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, andILNodeto use new interfacesIHasFileName,ISourceRange,ILineAndColumn, andILineColumnFile- This allowed
SourceRangeto 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 toMutableListExtensionMethodsnamespace
Loyc.Syntax:
- Introduced
LNodeListto replaceVList<LNode>(#100) with automatic implicit conversions between the old and new collection types to minimize breakage.LNodeListis currently a wrapper aroundVList<LNode>, but the implementation could (of course) change later. - Rename
CodeSymbols.PtrArrowtoRightArrow(old name marked Obsolete) - Rename
CodeSymbols._RightArrowtoRightArrow(old name marked Obsolete) - Rename
LineAndCol,SourcePos,SourcePosAndIndex- Introduce derived class
LineAndColumnas new name forLineAndCol - Introduce derived class
LineColumnFileas new name forSourcePos - Introduce derived class
LineColumnFileAndIndexas new name forSourcePosAndIndex
- Introduce derived class
ISourceRange.StartandISourceRange.Endbecame 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.NullinsteadIParsingServicenow acceptsIParsingOptionsinstead ofParsingMode mode = null, bool preserveComments = truearguments. 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-literalshave been removed since@@now means “backreference”.@@inf.dis now_d"inf",@@nan.fis 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!Tcan parse (#108) - Rearrange lexer to allow
true,falseandnullas type markers, which makes it slightly simpler - Bug fix: for proper round-tripping,
%appendStatementattribute should not cause a statement to be appended if the printer was given thePrintTriviaExplicitlyflag - Move
Les3PrinterOptionsandTokenTreeto separate files. - Tweak grammar of
MLCommentso 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
ISerializedLiteralto represent a serialized text form of a literal value (TextValueandTypeMarkerproperties) - Add
ILiteralValuewhich adds anobject Valueproperty toISerializedLiteral ILNode(andLNode) now includesILiteralValue(TextValueandTypeMarkerproperties)IEither<L,R>: added twoMaybe.Orextension methods and twoMaybe.Thenextension methodsEither<L,R>: addedOr(T defaultValue)method- Add
UString.IsNullproperty - Rename
LCExtinLoyc.InterfacestoCollectionSourceto avoid causing ambiguity errors when referring toLCExt, which also exists inLoyc.Essentials - Optimize conversion from
UStringtoSymbol - Add
EmptySourceFile.Syntheticand markEmptySourceFile.Defaultas Obsolete.
Loyc.Essentials:
DictionaryExt: addedGetOrAddandAddOrUpdateextension methods forIDictionary<,>that behave like the synonymous methods inConcurrentDictionaryLinqToLists: AddConcatNow()methodsStringExt.FormatCore: a recent change toLocalizebroke this method in the case that it is used as theLocalize.Formatterand you call something like"Hello {name}".Localize("name", "Joe"). The problem is that for the sake of its own simplicity,Localizerounds up the number of arguments to 3 so thatFormatCorealways receives at least 3 arguments.FormatCorewas 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.AddIfNotPresentsince it actually provides more functionality than theGetOrAddextension method (i.e. its boolean result) Bijection<,>: implementIDictionaryImplinstead ofIDictionaryAndReadOnly, thus includingIDictionarySink- Cancel obsolescence of
BDictionary.AddIfNotPresentsince it actually provides more functionality than theGetOrAddextension method (i.e. its boolean result) - In
BDictionaryandDictionaryExt(IDictionaryextension method): renamedSetAndGettoGetAndSetto 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
TryGetthat are no longer needed (or weren’t really needed in the first place)
Loyc.Syntax:
- Various APIs now generally refer to
LNodeListinstead ofVList<LNode>andmatchCodemacro now emits references toLNodeListinstead ofVList<LNode>. SourceRange.ToStringnow 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
ILiteralValueProviderand public implementationsLiteralValueandParsedValue. 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:
CustomLiteralwill be deprecated soon.LNodeitself now includesTypeMarkerandTextValueproperties which eliminate the need for it. Use the new overloads ofLNode.Literal()that acceptILiteralValueProviderorLiteralValueto 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>.GetEnumeratorfor likely higher efficiency - Tweaked type of
EmptyEnumerator<T>.Emptyto 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. TheLeftandRightproperties return aMaybe<L>andMaybe<R>respectively, and there’s aValueproperty that returns eitherLeft.ValueorRight.Valueas 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, andISourceRangewhich will be used in breaking changes in v2.8.0. Specifically, theIIndexToLine,IIndexPositionMapper,ISourceFileandILNodeinterfaces will returns these interfaces instead of the concrete typesLineAndCol,SourcePos, andSourceRange. - Renamed
AbstractTriviaInjector.AttachTriviaTotoGetAttachedTrivia. 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
IAddRangeandIListRangeMethodsas<in T>. - Added
ICollectionSource<T>and added it as a base ofISetImm - Added
ICollectionAndReadOnly<T>,IListAndReadOnly<T>,IDictionaryAndReadOnly<T> - Added
ICollectionAndSource<T> - Added
IDictionaryExinterface - Added
IOptimizeas common subinterface ofIAutoSizeArray<T>andINegAutoSizeArray<T> IListAndListSource<T>now includesICollectionSource<T>(which hasCopyToandContainsmethods.)
Loyc.Essentials
Changes that are most likely to be breaking:
- Rename
BaseDictionarytoDictionaryBasefor consistency. - Eliminated
StringSlice(UStringnow implements its interface,IRange<char>) - A new namespace
Loyc.Collections.MutableListExtensionMethodshas 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>.RemoveAllwhich 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
IDictionaryandIDictionaryEx:GetAndRemove,AddRangewithDictEditModeparameter - Added
SetExtextension methods forISet<K> - Added
IDictionarySinkandIDictionaryAndReadOnly. - Added extension method
AddIfNotPresentforIList<T> - Added extension method
AsReadOnlyDictionarywithSelectDictionaryFromKeysadapter - Added extension methods for
IDictionary<K,V>:TryGetValue(K key),AddRange,SetRange,RemoveRange - Added more
LinqToLists.Selectextension methods forICollection/IReadOnlyCollection, with corresponding adaptersSelectCollectionandSelectReadOnlyCollection. - Edit
BDictionaryandMMapto supportIDictionaryEx. - Edit
InvertibleSetto support newCopyTomethod. - Added
ByteArrayInStringclass, 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
TryPopFirstandTryPopLastinUStringandRangeExt.
Loyc.Collections:
BMultiMapnow acceptsnullvalues 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
#usingCastto'using(CodeSymbols.UsingCast) - Rename
#namedArgto'::=(alternate name:<:) (the nameCodeSymbols.NamedArgis unchanged) - Rename
#ofto'of(CodeSymbols.Of) (issue #96) - Rename
#tupleto'tuple(CodeSymbols.Tuple) (issue #96) - Rename
#is/#as/#castto'is/'as/'cast(CodeSymbols.Is/As/Cast) (issue #96) - Rename
#defaultto'default(CodeSymbols.Default) even for the label form,default:(issue #96) - Rename
#sizeof/#typeofto'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
#newinto'newoperator and#newattribute (CodeSymbols.NewandCodeSymbols.NewAttribute) - Split
#switchinto'switchoperator and#switchstatement.CodeSymbols.Switchwas split intoCodeSymbols.SwitchStmtandCodeSymbols.SwitchExpr. Note: EC# parser does not yet support the switch expression. - Increase block size in
BaseLexer, mainly to reduce branch mispredictions - Deleted
IToLNode.ILNode.ToLNodeis 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.CountSizeInBytesmethods implemented forList<T>, Dictionary<K,V>, SortedDictionary<K,V>, andLinkedList<T>) - Added convenience method
SparseAList<T>.AddSpace(count) AListandSparseAList: 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
InternalDListtoInternalList(InternalDListmay 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
ChildrenandLeaves - Hide unimportant properties in debugger
- Added
- Optimize enumerators of InternalList, InternalDList and AList
- InternalList:
yield returnmeasured to be slow. Avoided it. - DList/AList: Factor out “rare” parts to encourage inlining.
- InternalList:
Loyc.Utilities:
- Add
AListSumTrackerandAListStatisticTrackerclasses 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 - 1means(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.Targetto have a more appropriate return type. - Added convenience method for printing
ILNodeinLes2LanguageServiceandLes3LanguageService
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.SpaceswithTokenKind.Otherso that lexers oblivious toTokenKindwill typically have integer values in theTokenKind.Otherregion. Token.ToSourceRangeandToken.Rangewere 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,NextLowerItemwhenindexis 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:
.dotKeywordswill be stored as#hashKeywords - v3:
#is officially an ID character (but was already treated as such) - v3:
.keyw0rdscan now contain digits - v3: Hexadecimal and binary floating-point numbers no longer require a
p0suffix - 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*.2will now be parsed asx * .2rather thanx *. 2, but0..2will 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
- -aanda. -binstead of-’-(a)anda.(@@ -b). - Changed symbols
#[],#[,],#into'[],'[,],'infor consistency with other operators.
v2.5.1: January 19, 2017
Loyc.Syntax
- Bug fix:
ParsingService.ParseFilecould causeIOExceptionthat says “Cannot access a closed file” BaseLexer/BaseParser: Renamed theErrormethod that is called byMatch/MatchExcepttoMatchErrorand added an anti-infinite-loop mechanism.
v2.5.0: January 13, 2017
Loyc.Essentials
- Renamed
ISinkCollection=>ICollectionSink,ISinkArray=>IArraySink,ISinkList=>IListSinkfor consistency withIMessageSinkandIListSource
Localization
- Added
Localize.UseResourceManager() - Methods of
Localizethat accept a symbol representing the string to translate were renamed fromLocalizedtoSymbol. - Introduced “auto-fallback” behavior in
ThreadLocalVariable.Localize.LocalizerandFormatteruse it to mitigate .NET’s lack of thread-local propagation.
Message sinks (logging)
MessageSink: Added extension methodsError,Warn,Debug, etc. Added customizableContextToStringdelegate to replaceLocationString. AddedWithContext.- Removed setter of
MessageSink.Default(useSetDefaultinstead) - Wrappers
SeverityMessageFilterandMessageSplitternow have an optionalTContexttype parameter. ConsoleMessageSink,TraceMessageSinkandNullMessageSinkhave singletonValueproperties now.- Added
MessageSinkWithContext<TContext>wrapper forIMessageSink. - Changed argument order of
TraceMessageSinkfor consistency with other classes - Removed
Severity.Detail, replacing it with a separateDetailversion of each member ofSeverity. - Added
includeDetailsparameter to constructor ofSeverityMessageFilterin the hope of drawing attention to the possibility of accidentally excluding details, while making some older code behave correctly at the same time. - Renamed
MessageSplittertoMessageMulticaster. Renamed some method parameters.
v2.4.2: January 8, 2017
- Rename
LinqToCollectionstoLinqToLists. - Rename some rarely used members of
Severityto 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!cis 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
IReferenceComparabletoIReferenceEquatable - Moved
Reverse()extension method toLinqToCollections.
v2.3.2: December 12, 2016
- Changed return type of
MessageSink.SetDefaultas 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:
Rangewas split. The classRangewent to Loyc.Math and contains methods that returnNumRange. TheIsInRangeandPutInRangemethods went classGinLoyc.EssentialsMathExwas split. Most methods remained inMathExwhich went to Loyc.Math. The methodsSwapandSortPairwent to classG. WhileCountOnes,Log2Floor,ShiftLeftandShiftRightare still inMathEx, certain overloads are implemented inGor duplicated inGbecause they are needed by Loyc.Collections and Loyc.Syntax.
Other changes:
- The rarely-used
CPTrietypes andKeylessHashtablewere moved from Loyc.Collections to Loyc.Utilities - Some geometry stuff was moved from Loyc.Utilities to Loyc.Math.
- The
ParseHelpersclass was split between Loyc.Essentials and Loyc.Syntax, with the conversion-to-string stuff going toPrintHelpersin Loyc.Essentials and the conversion-from-string stuff going toParseHelpersin 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.CurrenttoMessageSink.Default - Introduced
IHasMutableValue<T> - Renamed
PushedTLV<T>toSavedValue<T>, now operates onIHasMutableValue<T> - Removed
G.PushTLV()
- Renamed
v2.1.0: December 3, 2016
- Eliminated
LNodePrinterdelegate, replacing it withILNodePrinter.LNodePrinternow holds standard extension methods ofILNodePrinter. IParsingServiceno longer includes a printing capability; language services implementILNodePrinterseparately.- Renamed
LesNodePrintertoLes2Printer,LesParsertoLes2Parser, and so on forLesLexerand LESv2 unit tests. LinqToCollections: AddedTakeWhile()andSkipWhile()extension methods for IList,IListSource,INegListSource`.- Added extension method
INegListSource<T>.TryGet(index) - Added one-param constructor to
MacroProcessorand switched order of params to other constructor for harmony.
v2.0.0: November 23, 2016
IParsingService.Printhas 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
ILNodePrinterOptionsinterface andLNodePrinterOptionsclass. 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
SourcePosfor the context ofIMessageSink.Write();SourceRangeis now used instead. IParsingService.Parsenow preserves comments by default, if possible.LNode.Equalsnow has aCompareModeparameter 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:
IndexPositionMapperunit tests were not set up to run, and it was broken - Eliminated
NodeStyle.Alternate2; addedNodeStyle.InjectedTriviawhich is applied to trivia attributes byAbstractTriviaInjector. LesNodePrinternow 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
LNodecreation methods. LinqToCollections: AddedSelect(this IList<T>, ...)andFirstOrDefault(this IList<T>, T).- Bug fix in
LNodeFactorythat 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
ILNodeinterface for objects that want to pretend to be Loyc trees. AddedLNode.Equals(ILNode, ILNode). - LES printers can now print
ILNodeobjects directly, but most other functionality still requiresLNodeand this is not planned to change. - Changed the way trivia works (new
#trivia_trailingattribute) 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; addedUnicodeNonCharactersandUnicodePrivateUseoptions. Single quotes are no longer escaped by default but non-characters and private characters are.- Eliminated
SelectNegListsandSelectNegListSources, which most likely no one was using. RenamedNegViewtoAsNegListfor consistency withAsListetc. Added methods toLinqToCollectionsforINegListSource. - Renamed
FronttoFirstandBacktoLastin theRangeinterfaces. - 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: addedCanPreserveCommentsproperty 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
BigIntegerliterals to LESv2 and LESv3 (Issue #42) viazsuffix - Tweaked LESv2 and LESv3 precedence rules. Most code will be unaffected; as LES has few users, it seems better not to fork
LesPrecedenceandLesPrecedenceMapfor v3. LNode: changed definition ofHasSpecialNamedue to LESv3 idea to use ‘.’ to mark keyword-expressions.LNode:addedPlusAttrBefore(),PlusAttrsBefore()NodeStyle.DataTypeis 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 -> Symbolconversion. Fixed bugs inStringExt.EliminateNamedArgs. Eliminated bitwise-not-on-error behavior whenUStringdecodes a code point, because the behavior wasn’t wanted in LES parser. - Add
ParseHelpers.IntegerToStringandParseNumberFlag.SkipSingleQuotes - Tweaked
NodeStyleto 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,
sufin operator names changed from being a prefix to a suffix - Renamed
CodeSymbols.*SettoCodeSymbols.*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.Assertin 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 dedicatedWhereSelectwith one based onTransform; deletedSelect<Out>; renamedWheretoSmartWhere. Replaced a fewPredicate<T>withFunc<T, bool>for consistency with LINQ-to-Objects
v1.7.4: April 18, 2016
IParsingService: changedinputTypeparameters to useParsingMode, a new extensible enumeration. Added additional modes.- Helper methods for parsing and printing tokens and hex digits have been moved from
Loyc.GtoLoyc.Syntax.ParseHelpers - Renamed
USlice(this string...)toSlice - Removed
G.Pairwhich 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 newReplaceRecursiveoverload that can delete items.LNodeperf: 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..hiandlo...hioperators; addedFloorandCeilingto Maths types as needed byNumRange.
v1.5.0: Mar 2, 2016
- Renamed
RVListtoVList, and renamedRWListtoWList. LNodeFactory: RenamedF._MissingtoF.Missing(and the less-oft-usedLNodeFactory.Missingto Missing_ to avoid a name collision).LNode: Added overloads: ofLNode.Calls(string),LNode.IsIdNamed(string),LNode.List(IEnumerable<LNode>).LNodeExt: AddedWithoutNodeNamedextension method.- Renamed
LineAndPostoLineAndCol
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.MessagetoLogMessage(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.OtherLitinto 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,StdSimpleCallNodeWithAttrsto 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
TokensToTreefrom 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
BaseParserForListas its base class. Added propertyBaseParser.ErrorSinkto 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
IIndexToLineas part ofILexer<Token>because certain lexers don’t have aSourceFile, andBaseLexerimplementsIndexToLineanyway - Implemented and tested
IndentTokenGenerator - Changed
IDequeinterface to useMaybe<T>and eliminated most of the extension methods list.TryGet(i)extension methods for lists now returnMaybe<T>.NoValueinstead ofdefault(T)on fail- Defined
IHasValue<T> - Moved the benchmarks to their own project, LoycCore.Benchmarks.
- Bug fix:
NullReferenceExceptioninAListIndexer.VerifyCorrectness
v1.3.1: Jun 14, 2015
ILocationString.LocationStringchanged toIHasLocation.Location; now returnsobjectfor 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 thatTokenis not required to be a struct.- Added
BaseILexer<CharSrc,Token>, and installed it as the new base class ofLesLexer - Added
BaseLexer.ErrorSinkproperty; default behavior is still to throwFormatException LesLexerno longer producesSpacestokens.LesNodePrinterbug 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.