Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 1x 1x 36x 36x 36x 36x 41x 41x 5x 151x 109x 21x 52x 3x 36x 36x 49x 49x 36x 36x 36x 36x 36x 1x | const { buildIdentifier, buildVariableDeclaration, buildVariableDeclarator, } = require('./ast-build'); const { difference } = require('./utils.js'); /** * Represents a scope in a program. */ class Scope { constructor(parent) { this.parent = parent; this.initialized = new Set(); this.used = new Set(); this.VarDeclarators = []; } /** * Adds a variable to the scope. * @param {string} name - The name of the variable. */ add(name) { this.initialized.add(name); this.VarDeclarators.push(buildVariableDeclarator(buildIdentifier(name))); } /** * Sets a variable as initialized in the scope. * @param {string} name - The name of the variable. */ setAsInitialized(name) { this.initialized.add(name); } /** * Sets a variable as used in the scope. * @param {string} name - The name of the variable. */ setAsUsed(name) { this.used.add(name); } /** * Checks if a variable is declared in the scope. * @param {string} name - The name of the variable. * @returns {boolean} - True if the variable is declared, false otherwise. */ has(name) { return this.initialized.has(name); } /** * Builds the variable declaration for the scope. * @returns {VariableDeclaration} - The built variable declaration. */ buildDeclaration() { return buildVariableDeclaration(this.VarDeclarators); } /** * Looks up a variable in the scope and its parent scopes. * @param {string} name - The name of the variable. * @returns {Scope|null} - The scope where the variable is declared, or null if not found. */ lookup(name) { if (this.has(name)) return this; Eif (this.parent) return this.parent.lookup(name); return null; } /** * Finds variables that are used but not declared in the scope. * @returns {Set<string>} - The set of not declared variables. */ notDeclared() { let notDeclared = difference(this.used, this.initialized); for(let v of this.used) { let s = this.lookup(v); Eif (s) notDeclared.delete(v); } return notDeclared; } /** * Generates a message for not declared variables in the scope. * @returns {string|null} - The message for not declared variables, or null if all variables are declared. */ notDeclaredMessage() { let d = this.notDeclared(); Iif (d.size > 0) { return Array.from(d) .map(x => x.replace(/^[$]/, '')) .map(x => `Not declared variable '${x}'`).join(','); } return null; } /** * Gets the number of variable declarators in the scope. * @returns {number} - The number of variable declarators. */ get length() { return this.VarDeclarators.length; } } module.exports = Scope; |