# Introduction to Scoping

# Descripción de la Tarea

Queremos extender nuestra calculadora para que soporte operaciones de coma, identificadores, asignación y print de manera que podamos escribir una entrada como esta:

➜  calc2js-solution git:(develop) ✗ cat test/data/input/test-id.calc 
a = 4+i, 
b = 2-2i, 
print(a*b)
1
2
3
4

Cuando se llame a nuestro transpiler con esta entrada, se debe generar un programa JS que al ejecutarse en NodeJS muestre por pantalla el resultado de la operación:

➜  calc2js-solution git:(develop) ✗ bin/calc2js.mjs  test/data/input/test-id.calc    
#!/usr/bin/env node
const Complex = require("/Users/casianorodriguezleon/campus-virtual/2223/pl2223/practicas/drafts/calc2js-solution/src/complex.js");  
const print = x => { console.log(x); return x; };
let $a, $b;
($a = Complex("4").add(Complex("i")), $b = Complex("2").sub(Complex("2i"))), print($a.mul($b));
1
2
3
4
5
6

# Análisis de las dependencias de funciones de soporte

El programa JS generado incluye el código de soporte para números complejos y sólo se añade la función print y no otras del catálogo de funciones de soporte como factorial, max o min que no son necesarias

const print = x => { console.log(x); return x; };
1

Nótese como se genera la importación del módulo complex.js con la ruta en la que haya quedado la instalación del módulo

const Complex = require("/Users/casianorodriguezleon/campus-virtual/2223/pl2223/practicas/drafts/calc2js-solution/src/complex.js");
1

# Análisis de las variables inicializadas

Las variables que se inicializan en el fuente como a y b se declaran como variables globales siguiendo al código de soporte y precediendo al programa JS generado:

// ... Código de soporte
let $a, $b;
($a = Complex("4").add(Complex("i")), 
 $b = Complex("2").sub(Complex("2i"))
), 
print($a.mul($b));
1
2
3
4
5
6

# Evitación de conflictos con palabras reservadas y nombres de soporte

Nótese también como las variables del programa de entrada se declaran con un prefijo $ para evitar conflictos con las variables de soporte, palabras reservadas JS, etc. en el programa JS generado. Por ejemplo, si el programa de entrada es while = 4 el potencial conflicto con el while de JS es resuelto mediante la traducción $while = 4.

# Código generado

El código generado deberá poder ejecutarse correctamente con NodeJS:

➜  calc2js-solution git:(develop) ✗ bin/calc2js.mjs  test/data/input/test-id.calc | node -
{ re: 10, im: -6 }
1
2

# Declaración de Variables

Asumiremos que en nuestra calculadora, similar a como ocurre en Ruby, tan pronto una variable es inicializada se declara (en este caso en el único ámbito global).

Un programa que contenga el uso de una variable no inicializada/declarada debe dar un error de ejecución. Por ejemplo:

➜  scope-intro-solution git:(scope-analysis) cat test/data/input/test-scope1.calc 
a = 4+d+i, 
b = 2-2i, 
print(c)
1
2
3
4

producirá una salida como:

➜  scope-intro-solution git:(scope-analysis) bin/calc2js.mjs  test/data/input/test-scope1.calc
Not declared variable 'd'
Not declared variable 'c'
1
2
3

# Fases del Compilador de la Calculadora

El compilador de la calculadora se puede dividir en las siguientes fases:

module.exports = async function transpile(inputFile, outputFile) {
  let input = await fs.readFile(inputFile, 'utf-8') // 1. leer la entrada
  let ast;
  try {
    ast = p.parse(input);               // 2. parsear la entrada
  } catch (e) {
    let m = e.message                   // 3. si hay error, mostrarlo
    console.error(m);
    return m;
  }

  ast = dependencies(ast);             // 4. calcular que funciones de soporte se necesitan
  ast = initializedVariables(ast);     // 5. calcular que variables se inicializan paa su declaración
  ast = usedVariables(ast);            // 6. calcular que variables son utilizadas
  let d = difference(ast.used, ast.symbolTable)
  if (d.size > 0) {                    // 7. si hay variables usadas y no inicializadas, mostrar error
    let m = notDeclared(d).join('');
    console.error(m);
    return m;
  }

  let output = codeGen(ast);           // 8. generar el código JS
  
  await writeCode(output, outputFile); // 9. escribir el código JS en el fichero de salida
  return output;
}
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

Para las fases 4,5 y 6 deberá recorrer el AST usando visit del módulo ast-types para completar el código de las funciones dependencies, initializedVariables y usedVariables respectivamente. Utilice el módulo recast para la escritura de codeGen.

# Pruebas, Covering e Integración Continua

Escriba las pruebas, haga un estudio de cubrimiento usando c8 (opens new window) y añada integración continua usando GitHub Actions.

Lea las secciones Testing with Mocha y Jest.

# Documentación

Documente el módulo incorporando un README.md y la documentación de la función exportada usando JsDoc. Lea la sección Documenting the JavaScript Sources

# References

Grading Rubric#

Comments#

Last Updated: 3 months ago