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

source-academy / js-slang / 14527354118

pending completion
14527354118

Pull #1745

github

web-flow
Merge b45dab2e1 into fea2b4cad
Pull Request #1745: Remove Interpreter and Testing Refactor

3090 of 4358 branches covered (70.9%)

Branch coverage included in aggregate %.

9068 of 11483 relevant lines covered (78.97%)

153062.41 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) {
71✔
4
  return typeof v === 'number'
23✔
5
}
6

7
export function is_int(v: Value) {
71✔
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) {
71✔
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
    return x + y
×
32
  }
33
  throw new Error(`Invalid types for addition operation: ${typeof x}, ${typeof y}`)
×
34
}
35

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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