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

source-academy / js-slang / 11296882442

11 Oct 2024 05:41PM UTC coverage: 81.253% (-0.4%) from 81.61%
11296882442

Pull #1725

github

web-flow
Merge cabdfe168 into 883ffe766
Pull Request #1725: Remove Non-Det Interpreter

3379 of 4524 branches covered (74.69%)

Branch coverage included in aggregate %.

22 of 32 new or added lines in 7 files covered. (68.75%)

7 existing lines in 4 files now uncovered.

10664 of 12759 relevant lines covered (83.58%)

142972.81 hits per line

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

96.69
/src/utils/rttc.ts
1
import * as es from 'estree'
2

3
import { RuntimeSourceError } from '../errors/runtimeSourceError'
75✔
4
import { Chapter, ErrorSeverity, ErrorType, Node, Value } from '../types'
75✔
5

6
const LHS = ' on left hand side of operation'
75✔
7
const RHS = ' on right hand side of operation'
75✔
8

9
export class TypeError extends RuntimeSourceError {
75✔
10
  public type = ErrorType.RUNTIME
877✔
11
  public severity = ErrorSeverity.ERROR
877✔
12
  public location: es.SourceLocation
13

14
  constructor(
15
    node: Node,
16
    public side: string,
877✔
17
    public expected: string,
877✔
18
    public got: string,
877✔
19
    public chapter: Chapter = Chapter.SOURCE_4
877✔
20
  ) {
21
    super(node)
877✔
22
  }
23

24
  public explain() {
25
    const displayGot =
26
      this.got === 'array' ? (this.chapter <= 2 ? 'pair' : 'compound data') : this.got
1,705!
27
    return `Expected ${this.expected}${this.side}, got ${displayGot}.`
1,705✔
28
  }
29

30
  public elaborate() {
31
    return this.explain()
830✔
32
  }
33
}
34

35
// We need to define our own typeof in order for null/array to display properly in error messages
36
const typeOf = (v: Value) => {
75✔
37
  if (v === null) {
62,890,542✔
38
    return 'null'
281✔
39
  } else if (Array.isArray(v)) {
62,890,261✔
40
    return 'array'
820✔
41
  } else {
42
    return typeof v
62,889,441✔
43
  }
44
}
45

46
const isNumber = (v: Value) => typeOf(v) === 'number'
46,851,206✔
47
// See section 4 of https://2ality.com/2012/12/arrays.html
48
// v >>> 0 === v checks that v is a valid unsigned 32-bit int
49
// tslint:disable-next-line:no-bitwise
50
const isArrayIndex = (v: Value) => isNumber(v) && v >>> 0 === v && v < 2 ** 32 - 1
286✔
51
const isString = (v: Value) => typeOf(v) === 'string'
692✔
52
const isBool = (v: Value) => typeOf(v) === 'boolean'
16,037,007✔
53
const isObject = (v: Value) => typeOf(v) === 'object'
408✔
54
const isArray = (v: Value) => typeOf(v) === 'array'
359✔
55

56
export const checkUnaryExpression = (
75✔
57
  node: Node,
58
  operator: es.UnaryOperator,
59
  value: Value,
60
  chapter: Chapter = Chapter.SOURCE_4
75✔
61
) => {
62
  if ((operator === '+' || operator === '-') && !isNumber(value)) {
168✔
63
    return new TypeError(node, '', 'number', typeOf(value), chapter)
16✔
64
  } else if (operator === '!' && !isBool(value)) {
152✔
65
    return new TypeError(node, '', 'boolean', typeOf(value), chapter)
8✔
66
  } else {
67
    return undefined
144✔
68
  }
69
}
70

71
export const checkBinaryExpression = (
75✔
72
  node: Node,
73
  operator: es.BinaryOperator,
74
  chapter: Chapter,
75
  left: Value,
76
  right: Value
77
) => {
78
  switch (operator) {
23,677,574!
79
    case '-':
80
    case '*':
81
    case '/':
82
    case '%':
83
      if (!isNumber(left)) {
493,488✔
84
        return new TypeError(node, LHS, 'number', typeOf(left), chapter)
292✔
85
      } else if (!isNumber(right)) {
493,196✔
86
        return new TypeError(node, RHS, 'number', typeOf(right), chapter)
36✔
87
      } else {
88
        return
493,160✔
89
      }
90
    case '+':
91
    case '<':
92
    case '<=':
93
    case '>':
94
    case '>=':
95
    case '!==':
96
    case '===':
97
      if (chapter > 2 && (operator === '===' || operator === '!==')) {
23,184,086✔
98
        return
251,804✔
99
      }
100
      if (isNumber(left)) {
22,932,282✔
101
        return isNumber(right)
22,931,803✔
102
          ? undefined
103
          : new TypeError(node, RHS, 'number', typeOf(right), chapter)
104
      } else if (isString(left)) {
479✔
105
        return isString(right)
164✔
106
          ? undefined
107
          : new TypeError(node, RHS, 'string', typeOf(right), chapter)
108
      } else {
109
        return new TypeError(node, LHS, 'string or number', typeOf(left), chapter)
315✔
110
      }
111
    default:
112
      return
×
113
  }
114
}
115

116
export const checkIfStatement = (node: Node, test: Value, chapter: Chapter = Chapter.SOURCE_4) => {
75✔
117
  return isBool(test)
16,036,979✔
118
    ? undefined
119
    : new TypeError(node, ' as condition', 'boolean', typeOf(test), chapter)
120
}
121

122
export const checkMemberAccess = (node: Node, obj: Value, prop: Value) => {
75✔
123
  if (isObject(obj)) {
408✔
124
    return isString(prop) ? undefined : new TypeError(node, ' as prop', 'string', typeOf(prop))
49✔
125
  } else if (isArray(obj)) {
359✔
126
    return isArrayIndex(prop)
286✔
127
      ? undefined
128
      : isNumber(prop)
11✔
129
      ? new TypeError(node, ' as prop', 'array index', 'other number')
130
      : new TypeError(node, ' as prop', 'array index', typeOf(prop))
131
  } else {
132
    return new TypeError(node, '', 'object or array', typeOf(obj))
73✔
133
  }
134
}
135

136
export const isIdentifier = (node: any): node is es.Identifier => {
75✔
UNCOV
137
  return (node as es.Identifier).name !== undefined
×
138
}
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

© 2025 Coveralls, Inc