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

source-academy / js-slang / 17011975380

16 Aug 2025 07:14PM UTC coverage: 78.56%. Remained the same
17011975380

Pull #1799

github

web-flow
Merge ab7273df7 into 20b0a35b6
Pull Request #1799: Migrate to TypeScript 5.9

2979 of 4115 branches covered (72.39%)

Branch coverage included in aggregate %.

33 of 38 new or added lines in 15 files covered. (86.84%)

1 existing line in 1 file now uncovered.

8981 of 11109 relevant lines covered (80.84%)

155600.21 hits per line

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

44.2
/src/stdlib/pylib.ts
1
import { Value } from '../types'
2

3
export function is_float(v: Value) {
72✔
4
  return typeof v === 'number'
23✔
5
}
6

7
export function is_int(v: Value) {
72✔
8
  return typeof v === 'bigint'
41✔
9
}
10

11
function __is_numeric(v: Value) {
12
  return is_int(v) || is_float(v)
41✔
13
}
14

15
function __is_string(v: Value) {
16
  // Retrieved from https://stackoverflow.com/questions/4059147/check-if-a-variable-is-a-string-in-javascript
17
  return typeof v === 'string' || v instanceof String
2✔
18
}
19

20
export function __py_adder(x: Value, y: Value) {
72✔
21
  if (typeof x === typeof y) {
4✔
22
    return x + y
2✔
23
  }
24
  if (typeof x === 'bigint') {
2!
25
    return Number(x) + y
×
26
  }
27
  if (typeof y === 'bigint') {
2✔
28
    return x + Number(y)
2✔
29
  }
30
  if (__is_numeric(x) && __is_numeric(y)) {
×
31
    // TODO: Shouldn't this be `Number(x) + Number(y)`?
NEW
32
    return (x as any) + (y as any)
×
33
  }
34
  throw new Error(`Invalid types for addition operation: ${typeof x}, ${typeof y}`)
×
35
}
36

37
export function __py_minuser(x: Value, y: Value) {
72✔
38
  if (!__is_numeric(x)) {
3!
39
    throw new Error('Expected number on left hand side of operation, got ' + typeof x + '.')
×
40
  }
41
  if (!__is_numeric(y)) {
3!
42
    throw new Error('Expected number on right hand side of operation, got ' + typeof y + '.')
×
43
  }
44
  if (typeof x === 'bigint' && typeof y === 'bigint') {
3✔
45
    return x - y
1✔
46
  }
47
  if (typeof x === 'number' && typeof y === 'number') {
2✔
48
    return x - y
1✔
49
  }
50
  if (typeof x === 'bigint' && typeof y === 'number') {
1!
51
    return Number(x) - y
×
52
  }
53
  if (typeof x === 'number' && typeof y === 'bigint') {
1✔
54
    return x - Number(y)
1✔
55
  }
56
  throw new Error(`Invalid types for subtraction operation: ${typeof x}, ${typeof y}`)
×
57
}
58

59
export function __py_multiplier(x: Value, y: Value) {
72✔
60
  if (
4✔
61
    !(
62
      (__is_numeric(x) && __is_numeric(y)) ||
9!
63
      (__is_string(x) && __is_numeric(y)) ||
64
      (__is_string(y) && __is_numeric(x))
65
    )
66
  ) {
67
    throw new Error(`Invalid types for multiply operation: ${typeof x}, ${typeof y}`)
1✔
68
  }
69

70
  if (typeof x === 'bigint' && typeof y === 'bigint') {
3✔
71
    return x * y
1✔
72
  }
73
  if (typeof x === 'number' && typeof y === 'number') {
2✔
74
    return x * y
1✔
75
  }
76
  if (typeof x === 'bigint' && typeof y === 'number') {
1!
77
    return Number(x) * y
×
78
  }
79
  if (typeof x === 'number' && typeof y === 'bigint') {
1✔
80
    return x * Number(y)
1✔
81
  }
82
  if (typeof x == 'number' && __is_string(y)) {
×
83
    return y.repeat(x)
×
84
  }
85
  if (typeof y == 'number' && __is_string(x)) {
×
86
    return x.repeat(y)
×
87
  }
88
  throw new Error(`Invalid types for multiply operation: ${typeof x}, ${typeof y}`)
×
89
}
90

91
export function __py_divider(x: Value, y: Value) {
72✔
92
  if (!__is_numeric(x)) {
8✔
93
    throw new Error('Expected number on left hand side of operation, got ' + typeof x + '.')
2✔
94
  }
95
  if (!__is_numeric(y)) {
6!
96
    throw new Error('Expected number on right hand side of operation, got ' + typeof y + '.')
×
97
  }
98
  if (typeof x === 'bigint' && typeof y === 'bigint') {
6✔
99
    return Number(x) / Number(y)
2✔
100
  }
101
  if (typeof x === 'number' && typeof y === 'number') {
4✔
102
    return x / y
2✔
103
  }
104
  if (typeof x === 'bigint' && typeof y === 'number') {
2✔
105
    return Number(x) / y
2✔
106
  }
107
  if (typeof x === 'number' && typeof y === 'bigint') {
×
108
    return x / Number(y)
×
109
  }
110
  throw new Error(`Invalid types for divide operation: ${typeof x}, ${typeof y}`)
×
111
}
112

113
export function __py_modder(x: Value, y: Value) {
72✔
114
  if (!__is_numeric(x)) {
4✔
115
    throw new Error('Expected number on left hand side of operation, got ' + typeof x + '.')
1✔
116
  }
117
  if (!__is_numeric(y)) {
3!
118
    throw new Error('Expected number on right hand side of operation, got ' + typeof y + '.')
×
119
  }
120
  if (typeof x === 'bigint' && typeof y === 'bigint') {
3✔
121
    return x % y
1✔
122
  }
123
  if (typeof x === 'number' && typeof y === 'number') {
2✔
124
    return x % y
1✔
125
  }
126
  if (typeof x === 'bigint' && typeof y === 'number') {
1✔
127
    return Number(x) % y
1✔
128
  }
129
  if (typeof x === 'number' && typeof y === 'bigint') {
×
130
    return x % Number(y)
×
131
  }
132
  throw new Error(`Invalid types for modulo operation: ${typeof x}, ${typeof y}`)
×
133
}
134

135
export function __py_powerer(x: Value, y: Value) {
72✔
136
  if (!__is_numeric(x)) {
4✔
137
    throw new Error('Expected number on left hand side of operation, got ' + typeof x + '.')
1✔
138
  }
139
  if (!__is_numeric(y)) {
3!
140
    throw new Error('Expected number on right hand side of operation, got ' + typeof y + '.')
×
141
  }
142
  if (typeof x === 'bigint' && typeof y === 'bigint') {
3✔
143
    let res = BigInt(1)
1✔
144
    for (let i = 0; i < y; i++) {
1✔
145
      res = res * x
1✔
146
    }
147
    return res
1✔
148
  }
149
  if (typeof x === 'number' && typeof y === 'number') {
2✔
150
    return Math.pow(x, y)
1✔
151
  }
152
  if (typeof x === 'bigint' && typeof y === 'number') {
1✔
153
    return Math.pow(Number(x), y)
1✔
154
  }
155
  if (typeof x === 'number' && typeof y === 'bigint') {
×
156
    return Math.pow(x, Number(y))
×
157
  }
158
  throw new Error(`Invalid types for power operation: ${typeof x}, ${typeof y}`)
×
159
}
160

161
export function __py_floorer(x: Value, y: Value) {
72✔
162
  return BigInt(Math.floor(__py_divider(x, y)))
4✔
163
}
164

165
export function __py_unary_plus(x: Value) {
72✔
166
  if (__is_numeric(x)) {
×
167
    return +Number(x)
×
168
  }
169
  throw new Error(`Invalid type for unary plus operation: ${typeof x}`)
×
170
}
171

172
export function math_abs(x: Value) {
72✔
173
  if (!__is_numeric(x)) {
×
174
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
175
  }
176
  return Math.abs(Number(x))
×
177
}
178

179
export function math_acos(x: Value) {
72✔
180
  if (!__is_numeric(x)) {
×
181
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
182
  }
183
  return Math.acos(Number(x))
×
184
}
185

186
export function math_acosh(x: Value) {
72✔
187
  if (!__is_numeric(x)) {
×
188
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
189
  }
190
  return Math.acosh(Number(x))
×
191
}
192

193
export function math_asin(x: Value) {
72✔
194
  if (!__is_numeric(x)) {
×
195
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
196
  }
197
  return Math.asin(Number(x))
×
198
}
199

200
export function math_asinh(x: Value) {
72✔
201
  if (!__is_numeric(x)) {
×
202
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
203
  }
204
  return Math.asinh(Number(x))
×
205
}
206

207
export function math_atan(x: Value) {
72✔
208
  if (!__is_numeric(x)) {
×
209
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
210
  }
211
  return Math.atan(Number(x))
×
212
}
213

214
export function math_atan2(y: Value, x: Value) {
72✔
215
  if (!__is_numeric(x)) {
×
216
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
217
  }
218
  return Math.atan2(Number(y), Number(x))
×
219
}
220

221
export function math_atanh(x: Value) {
72✔
222
  if (!__is_numeric(x)) {
×
223
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
224
  }
225
  return Math.atanh(Number(x))
×
226
}
227

228
export function math_cbrt(x: Value) {
72✔
229
  if (!__is_numeric(x)) {
×
230
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
231
  }
232
  return Math.cbrt(Number(x))
×
233
}
234

235
export function math_ceil(x: Value) {
72✔
236
  if (!__is_numeric(x)) {
×
237
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
238
  }
239
  return Math.ceil(Number(x))
×
240
}
241

242
export function math_clz32(x: Value) {
72✔
243
  if (!__is_numeric(x)) {
×
244
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
245
  }
246
  return Math.clz32(Number(x))
×
247
}
248

249
export function math_cos(x: Value) {
72✔
250
  if (!__is_numeric(x)) {
×
251
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
252
  }
253
  return Math.cos(Number(x))
×
254
}
255

256
export function math_cosh(x: Value) {
72✔
257
  if (!__is_numeric(x)) {
×
258
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
259
  }
260
  return Math.cosh(Number(x))
×
261
}
262

263
export function math_exp(x: Value) {
72✔
264
  if (!__is_numeric(x)) {
×
265
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
266
  }
267
  return Math.exp(Number(x))
×
268
}
269

270
export function math_expm1(x: Value) {
72✔
271
  if (!__is_numeric(x)) {
×
272
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
273
  }
274
  return Math.expm1(Number(x))
×
275
}
276

277
export function math_floor(x: Value) {
72✔
278
  if (!__is_numeric(x)) {
×
279
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
280
  }
281
  return Math.floor(Number(x))
×
282
}
283

284
export function math_fround(x: Value) {
72✔
285
  if (!__is_numeric(x)) {
×
286
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
287
  }
288
  return Math.fround(Number(x))
×
289
}
290

291
export function math_hypot(...elements: Value[]) {
72✔
292
  const coercedElements: number[] = elements.map(el => {
×
293
    if (!__is_numeric(el)) {
×
294
      throw new Error(`Invalid type for operation: ${typeof el}`)
×
295
    }
296
    return Number(el)
×
297
  })
298
  return Math.hypot(...coercedElements)
×
299
}
300

301
export function math_imul(x: Value, y: Value) {
72✔
302
  if (!__is_numeric(x) || !__is_numeric(y)) {
×
303
    throw new Error(`Invalid types for power operation: ${typeof x}, ${typeof y}`)
×
304
  }
305
  return Math.imul(Number(x), Number(y))
×
306
}
307

308
export function math_log(x: Value) {
72✔
309
  if (!__is_numeric(x)) {
×
310
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
311
  }
312
  return Math.log(Number(x))
×
313
}
314

315
export function math_log1p(x: Value) {
72✔
316
  if (!__is_numeric(x)) {
×
317
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
318
  }
319
  return Math.log1p(Number(x))
×
320
}
321

322
export function math_log2(x: Value) {
72✔
323
  if (!__is_numeric(x)) {
×
324
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
325
  }
326
  return Math.log2(Number(x))
×
327
}
328

329
export function math_log10(x: Value) {
72✔
330
  if (!__is_numeric(x)) {
×
331
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
332
  }
333
  return Math.log10(Number(x))
×
334
}
335

336
export function math_max(...elements: Value[]) {
72✔
337
  // TODO: Python max also supports strings!
338
  const coercedElements: number[] = elements.map(el => {
×
339
    if (!__is_numeric(el)) {
×
340
      throw new Error(`Invalid type for operation: ${typeof el}`)
×
341
    }
342
    return Number(el)
×
343
  })
344
  return Math.max(...coercedElements)
×
345
}
346

347
export function math_min(...elements: Value[]) {
72✔
348
  // TODO: Python min also supports strings!
349
  const coercedElements: number[] = elements.map(el => {
×
350
    if (!__is_numeric(el)) {
×
351
      throw new Error(`Invalid type for operation: ${typeof el}`)
×
352
    }
353
    return Number(el)
×
354
  })
355
  return Math.min(...coercedElements)
×
356
}
357

358
export function math_pow(x: Value, y: Value) {
72✔
359
  if (!__is_numeric(x) || !__is_numeric(y)) {
×
360
    throw new Error(`Invalid types for power operation: ${typeof x}, ${typeof y}`)
×
361
  }
362
  return Math.pow(Number(x), Number(y))
×
363
}
364

365
export function math_random() {
72✔
366
  return Math.random()
×
367
}
368

369
export function math_round(x: Value) {
72✔
370
  if (!__is_numeric(x)) {
×
371
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
372
  }
373
  return Math.round(Number(x))
×
374
}
375

376
export function math_sign(x: Value) {
72✔
377
  if (!__is_numeric(x)) {
×
378
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
379
  }
380
  return Math.sign(Number(x))
×
381
}
382

383
export function math_sin(x: Value) {
72✔
384
  if (!__is_numeric(x)) {
×
385
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
386
  }
387
  return Math.sin(Number(x))
×
388
}
389

390
export function math_sinh(x: Value) {
72✔
391
  if (!__is_numeric(x)) {
×
392
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
393
  }
394
  return Math.sinh(Number(x))
×
395
}
396

397
export function math_sqrt(x: Value) {
72✔
398
  if (!__is_numeric(x)) {
×
399
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
400
  }
401
  return Math.sqrt(Number(x))
×
402
}
403

404
export function math_tan(x: Value) {
72✔
405
  if (!__is_numeric(x)) {
×
406
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
407
  }
408
  return Math.tan(Number(x))
×
409
}
410

411
export function math_tanh(x: Value) {
72✔
412
  if (!__is_numeric(x)) {
×
413
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
414
  }
415
  return Math.tanh(Number(x))
×
416
}
417

418
export function math_trunc(x: Value) {
72✔
419
  if (!__is_numeric(x)) {
×
420
    throw new Error(`Invalid type for operation: ${typeof x}`)
×
421
  }
422
  return Math.trunc(Number(x))
×
423
}
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