• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / js-slang / 24834367427

23 Apr 2026 12:09PM UTC coverage: 78.541% (+0.2%) from 78.391%
24834367427

Pull #1893

github

web-flow
Merge ab101147d into 715603479
Pull Request #1893: Error Handling and Stringify Changes

3126 of 4197 branches covered (74.48%)

Branch coverage included in aggregate %.

801 of 975 new or added lines in 76 files covered. (82.15%)

20 existing lines in 11 files now uncovered.

7056 of 8767 relevant lines covered (80.48%)

173930.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.79
/src/stepper/nodes/Expression/LogicalExpression.ts
1
import type { Comment, LogicalExpression, LogicalOperator, SourceLocation } from 'estree';
2
import type { StepperExpression, StepperPattern } from '..';
3
import type { RedexInfo } from '../..';
4
import { convert } from '../../generator';
5
import { StepperBaseNode } from '../../interface';
6
import assert from '../../../utils/assert';
7
import { checkIfStatement } from '../../../utils/rttc';
8
import { InternalRuntimeError } from '../../../errors/base';
9
import { StepperLiteral } from './Literal';
10

11
export class StepperLogicalExpression
12
  extends StepperBaseNode<LogicalExpression>
13
  implements LogicalExpression
14
{
15
  constructor(
16
    public readonly operator: LogicalOperator,
1,625✔
17
    public readonly left: StepperExpression,
1,625✔
18
    public readonly right: StepperExpression,
1,625✔
19
    leadingComments?: Comment[],
20
    trailingComments?: Comment[],
21
    loc?: SourceLocation | null,
22
    range?: [number, number],
23
  ) {
24
    super('LogicalExpression', leadingComments, trailingComments, loc, range);
1,625✔
25
  }
26

27
  static create(node: LogicalExpression) {
28
    return new StepperLogicalExpression(
405✔
29
      node.operator,
30
      convert(node.left),
31
      convert(node.right),
32
      node.leadingComments,
33
      node.trailingComments,
34
      node.loc,
35
      node.range,
36
    );
37
  }
38

39
  public override isContractible(redex: RedexInfo): boolean {
40
    if (this.left.type === 'Literal') {
1,522✔
41
      checkIfStatement(this, this.left.value);
231✔
42
      redex.preRedex = [this];
231✔
43
      return true;
231✔
44
    }
45

46
    return false;
1,291✔
47
  }
48

49
  public override isOneStepPossible(redex: RedexInfo): boolean {
50
    return (
1,066✔
51
      this.isContractible(redex) ||
1,962✔
52
      this.left.isOneStepPossible(redex) ||
53
      this.right.isOneStepPossible(redex)
54
    );
55
  }
56

57
  public override contract(redex: RedexInfo): StepperExpression {
58
    redex.preRedex = [this];
59✔
59

60
    assert(this.left.type === 'Literal', 'Left operand must be a literal to contract');
59✔
61
    const leftValue = this.left.value;
59✔
62

63
    if (this.operator === '&&' && !leftValue) {
59✔
64
      let ret = new StepperLiteral(
1✔
65
        false,
66
        undefined,
67
        this.leadingComments,
68
        this.trailingComments,
69
        this.loc,
70
        this.range,
71
      );
72
      redex.postRedex = [ret];
1✔
73
      return ret;
1✔
74
    } else if (this.operator === '||' && leftValue) {
58✔
75
      let ret = new StepperLiteral(
1✔
76
        true,
77
        undefined,
78
        this.leadingComments,
79
        this.trailingComments,
80
        this.loc,
81
        this.range,
82
      );
83
      redex.postRedex = [ret];
1✔
84
      return ret;
1✔
85
    } else {
86
      return this.right;
57✔
87
    }
88
  }
89

90
  public override oneStep(redex: RedexInfo): StepperExpression {
91
    if (this.isContractible(redex)) {
455✔
92
      return this.contract(redex);
59✔
93
    } else if (this.left.isOneStepPossible(redex)) {
396!
94
      return new StepperLogicalExpression(
396✔
95
        this.operator,
96
        this.left.oneStep(redex),
97
        this.right,
98
        this.leadingComments,
99
        this.trailingComments,
100
        this.loc,
101
        this.range,
102
      );
NEW
103
    } else if (this.right.isOneStepPossible(redex)) {
×
104
      return new StepperLogicalExpression(
×
105
        this.operator,
106
        this.left,
107
        this.right.oneStep(redex),
108
        this.leadingComments,
109
        this.trailingComments,
110
        this.loc,
111
        this.range,
112
      );
113
    }
114

NEW
115
    throw new InternalRuntimeError('Cannot oneStep ineligible LogicalExpression', this);
×
116
  }
117

118
  public override substitute(
119
    id: StepperPattern,
120
    value: StepperExpression,
121
    redex: RedexInfo,
122
  ): StepperExpression {
123
    return new StepperLogicalExpression(
824✔
124
      this.operator,
125
      this.left.substitute(id, value, redex),
126
      this.right.substitute(id, value, redex),
127
      this.leadingComments,
128
      this.trailingComments,
129
      this.loc,
130
      this.range,
131
    );
132
  }
133

134
  public override freeNames(): string[] {
135
    return Array.from(new Set([this.left.freeNames(), this.right.freeNames()].flat()));
3✔
136
  }
137

138
  public override allNames(): string[] {
139
    return Array.from(new Set([this.left.allNames(), this.right.allNames()].flat()));
12✔
140
  }
141

142
  public override rename(before: string, after: string): StepperExpression {
143
    return new StepperLogicalExpression(
×
144
      this.operator,
145
      this.left.rename(before, after),
146
      this.right.rename(before, after),
147
      this.leadingComments,
148
      this.trailingComments,
149
      this.loc,
150
      this.range,
151
    );
152
  }
153
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc