Skip to content

Commit

Permalink
Merge pull request #21 from gobstones/20-no-api-in-internals
Browse files Browse the repository at this point in the history
All internal uses of `this.atEndOfInput()` and `this.atEndOfDocument()` has been optimized (and justified), closing #20
  • Loading branch information
alanrodas authored Dec 7, 2023
2 parents e2782ca + 7a5f6f7 commit 98df228
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 31 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@
* [PARTIAL] Docs completed for the change. ([1e0864c](https://github.com/gobstones/gobstones-core/commit/1e0864c))
* [PARTIAL] Docs regenerated ([132eb3c](https://github.com/gobstones/gobstones-core/commit/132eb3c))
* [PARTIAL] Input name changed, tests updated ([947a16c](https://github.com/gobstones/gobstones-core/commit/947a16c))
* [PARTIAL] One operation optimized, more to go ([f2a4262](https://github.com/gobstones/gobstones-core/commit/f2a4262))
* All optimizations done, and justified with explicit reasonings ([89dcbd9](https://github.com/gobstones/gobstones-core/commit/89dcbd9))
* Changed all names from "string" to "document". Documentation improved a little ([5cdeda9](https://github.com/gobstones/gobstones-core/commit/5cdeda9))
* Fixed, although the casting is now on the constructor... ([fd8eece](https://github.com/gobstones/gobstones-core/commit/fd8eece))



## <small>0.4.7 (2023-12-07)</small>

- [PARTIAL] Docs completed for the change. ([1e0864c](https://github.com/gobstones/gobstones-core/commit/1e0864c))
- [PARTIAL] Docs regenerated ([132eb3c](https://github.com/gobstones/gobstones-core/commit/132eb3c))
- [PARTIAL] Input name changed, tests updated ([947a16c](https://github.com/gobstones/gobstones-core/commit/947a16c))
- Changed all names from "string" to "document". Documentation improved a little ([5cdeda9](https://github.com/gobstones/gobstones-core/commit/5cdeda9))
- Fixed, although the casting is now on the constructor... ([fd8eece](https://github.com/gobstones/gobstones-core/commit/fd8eece))

## <small>0.4.7 (2023-12-07)</small>

- [PARTIAL] Docs completed for the change. ([1e0864c](https://github.com/gobstones/gobstones-core/commit/1e0864c))
Expand Down
2 changes: 1 addition & 1 deletion docs/assets/search.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions docs/classes/SourceReader.SourceReader.html

Large diffs are not rendered by default.

134 changes: 110 additions & 24 deletions src/SourceReader/SourceReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1630,15 +1630,17 @@ export class SourceReader {
* @group API: Access
*/
public atEndOfInput(): boolean {
return !this._hasCurrentDocument();
return !this._hasMoreDocuments();
}

/**
* Answers if there are no more characters to read from the current document.
* @group API: Access
*/
public atEndOfDocument(): boolean {
return this._hasCurrentDocument() && !this._hasCurrentCharAtCurrentDocument();
// Precondition of second condition is guaranteed when the first is true
// so, by shortcircuit, condition is total
return this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument();
}

/**
Expand All @@ -1653,18 +1655,20 @@ export class SourceReader {
* @group API: Access
*/
public peek(): string {
expect(this.atEndOfInput())
// Optimized by manually inlining:
// expect(this.atEndOfInput())
// === (inlining)
expect(!this._hasMoreDocuments())
.toBe(false)
.orThrow(new ErrorAtEndOfInputBy('peek', 'SourceReader'));
// if (this.atEndOfInput()) {
// throw new ErrorAtEndOfInputBy('peek', 'SourceReader');
// }
expect(this.atEndOfDocument())
// Optimized by manually inlining and simplifying:
// expect(this.atEndOfDocument())
// === (inlining)
// expect(this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument())
// === (because this._hasMoreDocuments() is true, by previous expect)
expect(!this._hasMoreCharsAtCurrentDocument())
.toBe(false)
.orThrow(new ErrorAtEndOfDocumentBy('peek', 'SourceReader'));
// if (this.atEndOfDocument()) {
// document new ErrorAtEndOfDocumentBy('peekdocument 'SourceReader');
// }
return this._fullDocumentContentsAt(this._documentIndex)[this._charIndex];
}

Expand All @@ -1682,7 +1686,10 @@ export class SourceReader {
return true;
}
// Needed as there is no current input if it is true
if (this.atEndOfInput()) {
// Optimized by manually inlining:
// if (this.atEndOfInput()) {
// === (inlining)
if (!this._hasMoreDocuments()) {
return false;
}
// Grab all the contents of the current string
Expand All @@ -1702,7 +1709,10 @@ export class SourceReader {
* @group API: Access
*/
public getPosition(): KnownSourcePosition {
if (this.atEndOfInput()) {
// Optimized by manually inlining:
// if (this.atEndOfInput()) {
// === (inlining)
if (!this._hasMoreDocuments()) {
return new EndOfInputSourcePosition(
this,
this._line,
Expand All @@ -1722,10 +1732,18 @@ export class SourceReader {
* @group API: Access
*/
public getDocumentPosition(): DocumentSourcePosition {
expect(this.atEndOfInput())
// Optimized by manually inlining:
// expect(this.atEndOfInput())
// === (inlining)
expect(!this._hasMoreDocuments())
.toBe(false)
.orThrow(new ErrorAtEndOfInputBy('getDocumentPosition', 'SourceReader'));
if (this.atEndOfDocument()) {
// Optimized by manually inlining:
// if (this.atEndOfDocument()) {
// === (inlining)
// expect(this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument())
// === (because this._hasMoreDocuments() is true by previous expect)
if (!this._hasMoreCharsAtCurrentDocument()) {
return new EndOfDocumentSourcePosition(
this,
this._line,
Expand Down Expand Up @@ -1789,7 +1807,12 @@ export class SourceReader {
} else {
cant = howMuch ?? 1;
}
for (let i = 0; i < cant && !this.atEndOfInput(); i++) {
// Optimized by manually inlining:
// for (let i = 0; i < cant && !this.atEndOfInput(); i++) {
// === (inlining)
// for (let i = 0; i < cant && !(!this._hasMoreDocuments()); i++) {
// === (double negation)
for (let i = 0; i < cant && this._hasMoreDocuments(); i++) {
this._skipOne(silently);
}
}
Expand All @@ -1811,12 +1834,34 @@ export class SourceReader {
*/
public takeWhile(contCondition: (ch: string) => boolean, silently: boolean = false): string {
let strRead = '';
if (!this.atEndOfInput() && !this.atEndOfDocument()) {
// Optimized by manually inlining:
// if (!this.atEndOfInput() && !this.atEndOfDocument()) {
// === (inlining)
// if (!(!this._hasMoreDocuments()) && !this.atEndOfDocument()) {
// === (double negation)
// if (this._hasMoreDocuments() && !this.atEndOfDocument()) {
// === (inlining)
// if (this._hasMoreDocuments() &&
// !(this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument())) {
// === (de Morgan)
// if (this._hasMoreDocuments() &&
// (!this._hasMoreDocuments() || !(!this._hasMoreCharsAtCurrentDocument()))) {
// === (double negation)
// if (this._hasMoreDocuments() &&
// (!this._hasMoreDocuments() || this._hasMoreCharsAtCurrentDocument())) {
// === (first condition of || is false, so second is needed to be true)
if (this._hasMoreDocuments() && this._hasMoreCharsAtCurrentDocument()) {
let ch = this.peek();
while (contCondition(ch)) {
this._skipOne(silently);
strRead += ch;
if (this.atEndOfDocument()) {
// Optimized by manually inlining:
// if (this.atEndOfDocument()) {
// === (inlining)
// if (this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument()) {
// === (as !this.atEndOfDocument() before skipping 1,
// there are still documents, and first condition is true)
if (!this._hasMoreCharsAtCurrentDocument()) {
// This check is NOT redundant with the one at the beginning (because of skips),
// and guarantees the precondition of the following peek.
// Not necessary to check the EndOfInput, because skipping inside a document
Expand All @@ -1835,7 +1880,23 @@ export class SourceReader {
* @group API: Modification
*/
public beginRegion(regionId: string): void {
if (!this.atEndOfInput() && !this.atEndOfDocument()) {
// Optimized by manually inlining:
// if (!this.atEndOfInput() && !this.atEndOfDocument()) {
// === (inlining)
// if (!(!this._hasMoreDocuments()) && !this.atEndOfDocument()) {
// === (double negation)
// if (this._hasMoreDocuments() && !this.atEndOfDocument()) {
// === (inlining)
// if (this._hasMoreDocuments() &&
// !(this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument())) {
// === (de Morgan)
// if (this._hasMoreDocuments() &&
// (!this._hasMoreDocuments() || !(!this._hasMoreCharsAtCurrentDocument()))) {
// === (double negation)
// if (this._hasMoreDocuments() &&
// (!this._hasMoreDocuments() || this._hasMoreCharsAtCurrentDocument())) {
// === (first condition of || is false, so second is needed to be true)
if (this._hasMoreDocuments() && this._hasMoreCharsAtCurrentDocument()) {
this._regions.push(regionId);
}
}
Expand Down Expand Up @@ -1955,7 +2016,12 @@ export class SourceReader {
* @private
*/
private _skipOne(silently: boolean): void {
if (this.atEndOfDocument()) {
// Optimized by manually inlining:
// if (this.atEndOfDocument()) {
// === (inlining)
// expect(this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument())
// === (because this._hasMoreDocuments() is implied by the precondition)
if (!this._hasMoreCharsAtCurrentDocument()) {
// document a new line and column
this._line = 1;
this._column = 1;
Expand Down Expand Up @@ -2051,25 +2117,45 @@ export class SourceReader {
}

/**
* Answers if there are still input documents to be read.
* Answers if there are more input documents to be read.
* @group Implementation: Auxiliaries
* @private
*/
private _hasCurrentDocument(): boolean {
private _hasMoreDocuments(): boolean {
return this._documentIndex < this._documentsNames.length;
}

/**
* Answers if there are still chars in the current document.
* Answers if there are more chars in the current document.
*
* **PRECONDITION:** `this._hasCurrentDocument()`
* **PRECONDITION:** `this._hasMoreDocuments()`
* @group Implementation: Auxiliaries
* @private
*/
private _hasCurrentCharAtCurrentDocument(): boolean {
private _hasMoreCharsAtCurrentDocument(): boolean {
return this._charIndex < this._fullDocumentContentsAt(this._documentIndex).length;
}

// /**
// * Answers if there are still input documents to be read.
// * @group Implementation: Auxiliaries
// * @private
// */
// private _hasCurrentDocument(): boolean {
// return this._documentIndex < this._documentsNames.length;
// }

// /**
// * Answers if there are still chars in the current document.
// *
// * **PRECONDITION:** `this._hasCurrentDocument()`
// * @group Implementation: Auxiliaries
// * @private
// */
// private _hasCurrentCharAtCurrentDocument(): boolean {
// return this._charIndex < this._fullDocumentContentsAt(this._documentIndex).length;
// }

/**
* Answers if the given char is recognized as an end of line indicator, according
* to the configuration of the reader.
Expand Down

0 comments on commit 98df228

Please sign in to comment.