Skip to content

Commit

Permalink
feat: 🚀 Concat of String and If instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLorenzana272 committed Oct 5, 2024
1 parent 64715d4 commit 7cef1dc
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 48 deletions.
124 changes: 100 additions & 24 deletions JS_Analyzer_parts/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,17 @@ export class CompilerVisitor extends BaseVisitor {
node.izq.accept(this); // izq |
node.der.accept(this); // izq | der

this.code.popObject(r.T0); // der
this.code.popObject(r.T1); // izq
const der = this.code.popObject(r.T0); // der
const izq = this.code.popObject(r.T1); // izq

if (izq.type === 'string' && der.type === 'string') {
this.code.add(r.A0, r.ZERO, r.T1);
this.code.add(r.A1, r.ZERO, r.T0);
this.code.callBuiltin('concatString');
this.code.pushObject({ type: 'string', length: 4 });
return;
}


switch (node.op) {
case '+':
Expand Down Expand Up @@ -133,17 +142,54 @@ export class CompilerVisitor extends BaseVisitor {
this.code.popObject(r.T0); // der
this.code.popObject(r.T1); // izq

switch (node.op) {
case '&&':
this.code.and(r.T0, r.T0, r.T1);
this.code.push(r.T0);
break;
case '||':
this.code.or(r.T0, r.T1, r.T0);
this.code.push(r.T0);
break;
if (node.op === '&&') {
node.izq.accept(this); // izq
this.code.popObject(r.T0); // izq

const labelFalse = this.code.getLabel();
const labelEnd = this.code.getLabel();

this.code.beq(r.T0, r.ZERO, labelFalse); // if (!izq) goto labelFalse
node.der.accept(this); // der
this.code.popObject(r.T0); // der
this.code.beq(r.T0, r.ZERO, labelFalse); // if (!der) goto labelFalse

this.code.li(r.T0, 1);
this.code.push(r.T0);
this.code.j(labelEnd);
this.code.addLabel(labelFalse);
this.code.li(r.T0, 0);
this.code.push(r.T0);

this.code.addLabel(labelEnd);
this.code.pushObject({ type: 'bool', length: 4 });
return
}

if (node.op === '||') {
node.izq.accept(this); // izq
this.code.popObject(r.T0); // izq

const labelTrue = this.code.getLabel();
const labelEnd = this.code.getLabel();

this.code.bne(r.T0, r.ZERO, labelTrue); // if (izq) goto labelTrue
node.der.accept(this); // der
this.code.popObject(r.T0); // der
this.code.bne(r.T0, r.ZERO, labelTrue); // if (der) goto labelTrue

this.code.li(r.T0, 0);
this.code.push(r.T0);

this.code.j(labelEnd);
this.code.addLabel(labelTrue);
this.code.li(r.T0, 1);
this.code.push(r.T0);

this.code.addLabel(labelEnd);
this.code.pushObject({ type: 'bool', length: 4 });
return
}
this.code.pushObject({ type: 'bool', length: 4 });
}

/**
Expand Down Expand Up @@ -310,21 +356,51 @@ visitVariableAssign(node) {
* @type {BaseVisitor['visitIfNode']}
*/
visitIfNode(node) {
// Evaluar la condición
node.cond.accept(this);
this.code.comment('Inicio de If');

this.code.li(r.T0, node.cond.value);

// Hacer pop del valor de la condición
this.code.comment('Condicion');
node.cond.accept(this);
this.code.popObject(r.T0);

// Crear etiquetas
const falseLabel = this.code.newLabel();
const endLabel = this.code.newLabel();
this.code.comment('Fin de condicion');
/*
// no else
if (!cond) goto endIf
...
endIf:
// else
if (!cond) goto else
...
goto endIf
else:
...
endIf:
*/

const hasElse = !!node.stmtFalse

if (hasElse) {
const elseLabel = this.code.getLabel();
const endIfLabel = this.code.getLabel();

this.code.beq(r.T0, r.ZERO, elseLabel);
this.code.comment('Rama verdadera');
node.stmtTrue.accept(this);
this.code.j(endIfLabel);
this.code.addLabel(elseLabel);
this.code.comment('Rama falsa');
node.stmtFalse.accept(this);
this.code.addLabel(endIfLabel);
} else {
const endIfLabel = this.code.getLabel();
this.code.beq(r.T0, r.ZERO, endIfLabel);
this.code.comment('Rama verdadera');
node.stmtTrue.accept(this);
this.code.addLabel(endIfLabel);
}

//Bloque if
this.code.beqz(r.T0, falseLabel);
// No se que más hacer aquí
this.code.comment('Fin del If');

}

Expand Down
46 changes: 46 additions & 0 deletions RISC/builtins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { registers as r } from "./constants.js"
import { Generador } from "./generator.js"

/**
* @param {Generador} code
*/
export const concatString = (code) => {
// A0 -> dirección en heap de la primera cadena
// A1 -> dirección en heap de la segunda cadena
// result -> push en el stack la dirección en heap de la cadena concatenada

code.comment('Guardando en el stack la dirección en heap de la cadena concatenada')
code.push(r.HP);

code.comment('Copiando la 1er cadena en el heap')
const end1 = code.getLabel()
const loop1 = code.addLabel()

code.lb(r.T1, r.A0)
code.beq(r.T1, r.ZERO, end1)
code.sb(r.T1, r.HP)
code.addi(r.HP, r.HP, 1)
code.addi(r.A0, r.A0, 1)
code.j(loop1)
code.addLabel(end1)

code.comment('Copiando la 2da cadena en el heap')
const end2 = code.getLabel()
const loop2 = code.addLabel()

code.lb(r.T1, r.A1)
code.beq(r.T1, r.ZERO, end2)
code.sb(r.T1, r.HP)
code.addi(r.HP, r.HP, 1)
code.addi(r.A1, r.A1, 1)
code.j(loop2)
code.addLabel(end2)

code.comment('Agregando el caracter nulo al final')
code.sb(r.ZERO, r.HP)
code.addi(r.HP, r.HP, 1)
}

export const builtins = {
concatString: concatString
}
72 changes: 49 additions & 23 deletions RISC/generator.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { registers as r } from "./constants.js";
import { stringTo32BitsArray } from "./utils.js";
import { stringTo32BitsArray, stringTo1ByteArray } from "./utils.js";
import { builtins } from "./builtins.js";

class Instruction {

Expand All @@ -26,26 +27,19 @@ export class Generador {
this.instrucciones = []
this.objectStack = []
this.depth = 0
this.labelCount = 0
this.labels = new Set();
this._usedBuiltins = new Set()
this._labelCounter = 0;

}

newLabel() {
let label;
do {
label = `label${this.labelCount++}`;
} while (this.labels.has(label));
this.labels.add(label);
this.instrucciones.push(new Instruction(`${label}:`));
return label;
getLabel() {
return `L${this._labelCounter++}`
}

label(label) {
if (!this.labels.has(label)) {
this.labels.add(label);
this.instrucciones.push(new Instruction(`${label}:`));
}
addLabel(label) {
label = label || this.getLabel()
this.instrucciones.push(new Instruction(`${label}:`))
return label
}

add(rd, rs1, rs2) {
Expand Down Expand Up @@ -216,6 +210,10 @@ export class Generador {
this.instrucciones.push(new Instruction('j', label))
}

ret() {
this.instrucciones.push(new Instruction('ret'))
}

/* ------------------------------------------------------------------- */

/* ------------------------ Instrucción de Break ---------------------- */
Expand All @@ -225,10 +223,18 @@ export class Generador {
this.instrucciones.push(new Instruction('sw', rs1, `${inmediato}(${rs2})`))
}

sb(rs1, rs2, inmediato = 0) {
this.instrucciones.push(new Instruction('sb', rs1, `${inmediato}(${rs2})`))
}

lw(rd, rs1, inmediato = 0) {
this.instrucciones.push(new Instruction('lw', rd, `${inmediato}(${rs1})`))
}

lb(rd, rs1, inmediato = 0) {
this.instrucciones.push(new Instruction('lb', rd, `${inmediato}(${rs1})`))
}

li(rd, inmediato) {
this.instrucciones.push(new Instruction('li', rd, inmediato))
}
Expand Down Expand Up @@ -259,6 +265,14 @@ export class Generador {
this.instrucciones.push(new Instruction('ecall'))
}

callBuiltin(builtinName) {
if (!builtins[builtinName]) {
throw new Error(`Builtin ${builtinName} not found`)
}
this._usedBuiltins.add(builtinName)
this.jal(builtinName)
}

printInt(rd = r.A0) {

if (rd !== r.A0) {
Expand Down Expand Up @@ -338,17 +352,21 @@ export class Generador {
break;

case 'string':
const stringArray = stringTo32BitsArray(object.value);
const stringArray = stringTo1ByteArray(object.value);

this.comment(`Pushing string ${object.value}`);
this.addi(r.T0, r.HP, 4);
this.push(r.T0);
// this.addi(r.T0, r.HP, 4);
// this.push(r.T0);
this.push(r.HP);

stringArray.forEach((block32bits) => {
this.li(r.T0, block32bits);
stringArray.forEach((charCode) => {
this.li(r.T0, charCode);
// this.push(r.T0);
this.addi(r.HP, r.HP, 4);
this.sw(r.T0, r.HP);
// this.addi(r.HP, r.HP, 4);
// this.sw(r.T0, r.HP);

this.sb(r.T0, r.HP);
this.addi(r.HP, r.HP, 1);
});

length = 4;
Expand Down Expand Up @@ -444,7 +462,15 @@ export class Generador {
}

toString() {
this.comment('Fin del programa')
this.endProgram()
this.comment('Builtins')

Array.from(this._usedBuiltins).forEach(builtinName => {
this.addLabel(builtinName)
builtins[builtinName](this)
this.ret()
})
return `
.data
Expand Down
12 changes: 12 additions & 0 deletions RISC/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,17 @@ export const stringTo32BitsArray = (str) => {
resultado.push(0);
}

return resultado;
}

export const stringTo1ByteArray = (str) => {
const resultado = []
let elementIndex = 0

while (elementIndex < str.length) {
resultado.push(str.charCodeAt(elementIndex))
elementIndex++
}
resultado.push(0)
return resultado;
}
22 changes: 21 additions & 1 deletion tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,24 @@ int jose = 5*7;
System.out.println(jose > 45);

System.out.println(!true);
System.out.println(!false);
System.out.println(!false);

int goku = 5;

if(goku > 45){
System.out.println("Jose" + " Daniel");
} else if(goku == 5) {
if(goku < 10){
System.out.println("goku es igual a 5 y menor que 10");
} else {
System.out.println("goku es igual a 5 pero no menor que 10");
}
} else if(goku > 20 && goku <= 45){
System.out.println("goku está entre 20 y 45");
} else {
if(78 > 5 || (false && true)){
System.out.println(true);
} else {
System.out.println(false);
}
}

0 comments on commit 7cef1dc

Please sign in to comment.