.
This commit is contained in:
Executable
+35
@@ -0,0 +1,35 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/And16.hdl
|
||||
|
||||
/**
|
||||
* 16-bit bitwise And:
|
||||
* for i = 0..15: out[i] = (a[i] and b[i])
|
||||
*/
|
||||
|
||||
CHIP And16 {
|
||||
IN a[16], b[16];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
|
||||
And(a=a[0],b=b[0],out=out[0]);
|
||||
And(a=a[1],b=b[1],out=out[1]);
|
||||
And(a=a[2],b=b[2],out=out[2]);
|
||||
And(a=a[3],b=b[3],out=out[3]);
|
||||
And(a=a[4],b=b[4],out=out[4]);
|
||||
And(a=a[5],b=b[5],out=out[5]);
|
||||
And(a=a[6],b=b[6],out=out[6]);
|
||||
And(a=a[7],b=b[7],out=out[7]);
|
||||
And(a=a[8],b=b[8],out=out[8]);
|
||||
And(a=a[9],b=b[9],out=out[9]);
|
||||
And(a=a[10],b=b[10],out=out[10]);
|
||||
And(a=a[11],b=b[11],out=out[11]);
|
||||
And(a=a[12],b=b[12],out=out[12]);
|
||||
And(a=a[13],b=b[13],out=out[13]);
|
||||
And(a=a[14],b=b[14],out=out[14]);
|
||||
And(a=a[15],b=b[15],out=out[15]);
|
||||
|
||||
|
||||
}
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/DMux.hdl
|
||||
|
||||
/**
|
||||
* Demultiplexor:
|
||||
* {a, b} = {in, 0} if sel == 0
|
||||
* {0, in} if sel == 1
|
||||
*/
|
||||
|
||||
CHIP DMux {
|
||||
IN in, sel;
|
||||
OUT a, b;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel,out=notsel);
|
||||
And(a=in,b=notsel,out=a);
|
||||
And(a=in,b=sel,out=b);
|
||||
|
||||
}
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/DMux4Way.hdl
|
||||
|
||||
/**
|
||||
* 4-way demultiplexor:
|
||||
* {a, b, c, d} = {in, 0, 0, 0} if sel == 00
|
||||
* {0, in, 0, 0} if sel == 01
|
||||
* {0, 0, in, 0} if sel == 10
|
||||
* {0, 0, 0, in} if sel == 11
|
||||
*/
|
||||
|
||||
CHIP DMux4Way {
|
||||
IN in, sel[2];
|
||||
OUT a, b, c, d;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel[1],out=notsel1);
|
||||
Not(in=sel[0],out=notsel0);
|
||||
|
||||
And(a=notsel1,b=notsel0,out=out1);
|
||||
And(a=notsel1,b=sel[0],out=out2);
|
||||
And(a=sel[1],b=notsel0,out=out3);
|
||||
And(a=sel[1],b=sel[0],out=out4);
|
||||
|
||||
And(a=in,b=out1,out=a);
|
||||
And(a=in,b=out2,out=b);
|
||||
And(a=in,b=out3,out=c);
|
||||
And(a=in,b=out4,out=d);
|
||||
|
||||
}
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/DMux8Way.hdl
|
||||
|
||||
/**
|
||||
* 8-way demultiplexor:
|
||||
* {a, b, c, d, e, f, g, h} = {in, 0, 0, 0, 0, 0, 0, 0} if sel == 000
|
||||
* {0, in, 0, 0, 0, 0, 0, 0} if sel == 001
|
||||
* etc.
|
||||
* {0, 0, 0, 0, 0, 0, 0, in} if sel == 111
|
||||
*/
|
||||
|
||||
CHIP DMux8Way {
|
||||
IN in, sel[3];
|
||||
OUT a, b, c, d, e, f, g, h;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel[0],out=notsel0);
|
||||
Not(in=sel[1],out=notsel1);
|
||||
Not(in=sel[2],out=notsel2);
|
||||
|
||||
And(a=notsel2,b=notsel1,out=out1);
|
||||
And(a=out1,b=notsel0,out=outA);
|
||||
And(a=out1,b=sel[0],out=outB);
|
||||
|
||||
And(a=notsel2,b=sel[1],out=out2);
|
||||
And(a=out2,b=notsel0,out=outC);
|
||||
And(a=out2,b=sel[0],out=outD);
|
||||
|
||||
And(a=sel[2],b=notsel1,out=out3);
|
||||
And(a=out3,b=notsel0,out=outE);
|
||||
And(a=out3,b=sel[0],out=outF);
|
||||
|
||||
And(a=sel[2],b=sel[1],out=out4);
|
||||
And(a=out4,b=notsel0,out=outG);
|
||||
And(a=out4,b=sel[0],out=outH);
|
||||
|
||||
And(a=in,b=outA,out=a);
|
||||
And(a=in,b=outB,out=b);
|
||||
And(a=in,b=outC,out=c);
|
||||
And(a=in,b=outD,out=d);
|
||||
And(a=in,b=outE,out=e);
|
||||
And(a=in,b=outF,out=f);
|
||||
And(a=in,b=outG,out=g);
|
||||
And(a=in,b=outH,out=h);
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
/**
|
||||
* Multiplexor:
|
||||
* out = a if sel == 0
|
||||
* b otherwise
|
||||
*/
|
||||
|
||||
CHIP Mux {
|
||||
IN a, b, sel;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel,out=notsel);
|
||||
And(a=a,b=notsel,out=out1);
|
||||
And(a=b,b=sel,out=out2);
|
||||
Or(a=out1,b=out2,out=out);
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Mux16.hdl
|
||||
|
||||
/**
|
||||
* 16-bit multiplexor:
|
||||
* for i = 1..15 out[i] = a[i] if sel == 1
|
||||
* b[i] if sel == 1
|
||||
*/
|
||||
|
||||
CHIP Mux16 {
|
||||
IN a[16], b[16], sel;
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Mux(a=a[0],b=b[0],sel=sel,out=out[0]);
|
||||
Mux(a=a[1],b=b[1],sel=sel,out=out[1]);
|
||||
Mux(a=a[2],b=b[2],sel=sel,out=out[2]);
|
||||
Mux(a=a[3],b=b[3],sel=sel,out=out[3]);
|
||||
Mux(a=a[4],b=b[4],sel=sel,out=out[4]);
|
||||
Mux(a=a[5],b=b[5],sel=sel,out=out[5]);
|
||||
Mux(a=a[6],b=b[6],sel=sel,out=out[6]);
|
||||
Mux(a=a[7],b=b[7],sel=sel,out=out[7]);
|
||||
Mux(a=a[8],b=b[8],sel=sel,out=out[8]);
|
||||
Mux(a=a[9],b=b[9],sel=sel,out=out[9]);
|
||||
Mux(a=a[10],b=b[10],sel=sel,out=out[10]);
|
||||
Mux(a=a[11],b=b[11],sel=sel,out=out[11]);
|
||||
Mux(a=a[12],b=b[12],sel=sel,out=out[12]);
|
||||
Mux(a=a[13],b=b[13],sel=sel,out=out[13]);
|
||||
Mux(a=a[14],b=b[14],sel=sel,out=out[14]);
|
||||
Mux(a=a[15],b=b[15],sel=sel,out=out[15]);
|
||||
|
||||
}
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
CHIP Mux4Way {
|
||||
IN a, b, c, d, sel0, sel1;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel0,out=notsel0);
|
||||
Not(in=sel1,out=notsel1);
|
||||
|
||||
And(a=notsel0,b=notsel1,out=outA);
|
||||
And(a=sel0,b=notsel1,out=outB);
|
||||
And(a=notsel0,b=sel1,out=outC);
|
||||
And(a=sel0,b=sel1,out=outD);
|
||||
|
||||
And(a=outA,b=a,out=outA1);
|
||||
And(a=outB,b=b,out=outB1);
|
||||
And(a=outC,b=c,out=outC1);
|
||||
And(a=outD,b=d,out=outD1);
|
||||
Or(a=outA1,b=outB1,out=out1);
|
||||
Or(a=outC1,b=outD1,out=out2);
|
||||
Or(a=out1,b=out2,out=out);
|
||||
}
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/Mux4Way16.hdl
|
||||
|
||||
/**
|
||||
* 4-way 16-bit multiplexor:
|
||||
* out = a if sel == 00
|
||||
* b if sel == 01
|
||||
* c if sel == 10
|
||||
* d if sel == 11
|
||||
*/
|
||||
|
||||
CHIP Mux4Way16 {
|
||||
IN a[16], b[16], c[16], d[16], sel[2];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
|
||||
Mux4Way(a=a[0],b=b[0],c=c[0],d=d[0],sel0=sel[0],sel1=sel[1],out=out[0]);
|
||||
Mux4Way(a=a[1],b=b[1],c=c[1],d=d[1],sel0=sel[0],sel1=sel[1],out=out[1]);
|
||||
Mux4Way(a=a[2],b=b[2],c=c[2],d=d[2],sel0=sel[0],sel1=sel[1],out=out[2]);
|
||||
Mux4Way(a=a[3],b=b[3],c=c[3],d=d[3],sel0=sel[0],sel1=sel[1],out=out[3]);
|
||||
Mux4Way(a=a[4],b=b[4],c=c[4],d=d[4],sel0=sel[0],sel1=sel[1],out=out[4]);
|
||||
Mux4Way(a=a[5],b=b[5],c=c[5],d=d[5],sel0=sel[0],sel1=sel[1],out=out[5]);
|
||||
Mux4Way(a=a[6],b=b[6],c=c[6],d=d[6],sel0=sel[0],sel1=sel[1],out=out[6]);
|
||||
Mux4Way(a=a[7],b=b[7],c=c[7],d=d[7],sel0=sel[0],sel1=sel[1],out=out[7]);
|
||||
Mux4Way(a=a[8],b=b[8],c=c[8],d=d[8],sel0=sel[0],sel1=sel[1],out=out[8]);
|
||||
Mux4Way(a=a[9],b=b[9],c=c[9],d=d[9],sel0=sel[0],sel1=sel[1],out=out[9]);
|
||||
|
||||
Mux4Way(a=a[10],b=b[10],c=c[10],d=d[10],sel0=sel[0],sel1=sel[1],out=out[10]);
|
||||
Mux4Way(a=a[11],b=b[11],c=c[11],d=d[11],sel0=sel[0],sel1=sel[1],out=out[11]);
|
||||
Mux4Way(a=a[12],b=b[12],c=c[12],d=d[12],sel0=sel[0],sel1=sel[1],out=out[12]);
|
||||
Mux4Way(a=a[13],b=b[13],c=c[13],d=d[13],sel0=sel[0],sel1=sel[1],out=out[13]);
|
||||
Mux4Way(a=a[14],b=b[14],c=c[14],d=d[14],sel0=sel[0],sel1=sel[1],out=out[14]);
|
||||
Mux4Way(a=a[15],b=b[15],c=c[15],d=d[15],sel0=sel[0],sel1=sel[1],out=out[15]);
|
||||
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
CHIP Mux8Way {
|
||||
IN a, b, c, d, e, f, g, h, sel0, sel1, sel2;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Not(in=sel0,out=notsel0);
|
||||
Not(in=sel1,out=notsel1);
|
||||
Not(in=sel2,out=notsel2);
|
||||
|
||||
|
||||
And(a=notsel0,b=notsel1,out=outA);
|
||||
And(a=notsel0,b=sel2,out=outC);
|
||||
And(a=sel0,b=notsel1,out=outE);
|
||||
And(a=sel0,b=sel1,out=outG);
|
||||
|
||||
And(a=outA,b=notsel2,out=outA1);
|
||||
And(a=outC,b=notsel2,out=outC1);
|
||||
And(a=outE,b=notsel2,out=outE1);
|
||||
And(a=outG,b=notsel2,out=outG1);
|
||||
And(a=outA,b=sel2,out=outB1);
|
||||
And(a=outG,b=sel2,out=outH1);
|
||||
And(a=outC,b=sel2,out=outD1);
|
||||
And(a=outE,b=sel2,out=outF1);
|
||||
|
||||
And(a=outA1,b=a,out=outA2);
|
||||
And(a=outB1,b=b,out=outB2);
|
||||
And(a=outC1,b=c,out=outC2);
|
||||
And(a=outD1,b=d,out=outD2);
|
||||
And(a=outE1,b=e,out=outE2);
|
||||
And(a=outF1,b=f,out=outF2);
|
||||
And(a=outG1,b=g,out=outG2);
|
||||
And(a=outH1,b=h,out=outH2);
|
||||
|
||||
Or(a=outA2,b=outB2,out=out1);
|
||||
Or(a=outC2,b=outD2,out=out2);
|
||||
Or(a=outE2,b=outF2,out=out4);
|
||||
Or(a=outG2,b=outH2,out=out5);
|
||||
Or(a=out4,b=out5,out=out6);
|
||||
Or(a=out1,b=out2,out=out3);
|
||||
Or(a=out3,b=out6,out=out);
|
||||
}
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/Mux8Way16.hdl
|
||||
|
||||
/**
|
||||
* 8-way 16-bit multiplexor:
|
||||
* out = a if sel == 000
|
||||
* b if sel == 001
|
||||
* etc.
|
||||
* h if sel == 111
|
||||
*/
|
||||
|
||||
CHIP Mux8Way16 {
|
||||
IN a[16], b[16], c[16], d[16],
|
||||
e[16], f[16], g[16], h[16],
|
||||
sel[3];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Mux8Way(a=a[0],b=b[0],c=c[0],d=d[0],e=e[0],f=f[0],g=g[0],h=h[0],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[0]);
|
||||
Mux8Way(a=a[1],b=b[1],c=c[1],d=d[1],e=e[1],f=f[1],g=g[1],h=h[1],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[1]);
|
||||
Mux8Way(a=a[2],b=b[2],c=c[2],d=d[2],e=e[2],f=f[2],g=g[2],h=h[2],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[2]);
|
||||
Mux8Way(a=a[3],b=b[3],c=c[3],d=d[3],e=e[3],f=f[3],g=g[3],h=h[3],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[3]);
|
||||
Mux8Way(a=a[4],b=b[4],c=c[4],d=d[4],e=e[4],f=f[4],g=g[4],h=h[4],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[4]);
|
||||
Mux8Way(a=a[5],b=b[5],c=c[5],d=d[5],e=e[5],f=f[5],g=g[5],h=h[5],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[5]);
|
||||
Mux8Way(a=a[6],b=b[6],c=c[6],d=d[6],e=e[6],f=f[6],g=g[6],h=h[6],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[6]);
|
||||
Mux8Way(a=a[7],b=b[7],c=c[7],d=d[7],e=e[7],f=f[7],g=g[7],h=h[7],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[7]);
|
||||
Mux8Way(a=a[8],b=b[8],c=c[8],d=d[8],e=e[8],f=f[8],g=g[8],h=h[8],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[8]);
|
||||
Mux8Way(a=a[9],b=b[9],c=c[9],d=d[9],e=e[9],f=f[9],g=g[9],h=h[9],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[9]);
|
||||
|
||||
Mux8Way(a=a[11],b=b[11],c=c[11],d=d[11],e=e[11],f=f[11],g=g[11],h=h[11],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[11]);
|
||||
Mux8Way(a=a[12],b=b[12],c=c[12],d=d[12],e=e[12],f=f[12],g=g[12],h=h[12],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[12]);
|
||||
Mux8Way(a=a[14],b=b[14],c=c[14],d=d[14],e=e[14],f=f[14],g=g[14],h=h[14],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[14]);
|
||||
Mux8Way(a=a[13],b=b[13],c=c[13],d=d[13],e=e[13],f=f[13],g=g[13],h=h[13],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[13]);
|
||||
Mux8Way(a=a[15],b=b[15],c=c[15],d=d[15],e=e[15],f=f[15],g=g[15],h=h[15],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[15]);
|
||||
Mux8Way(a=a[10],b=b[10],c=c[10],d=d[10],e=e[10],f=f[10],g=g[10],h=h[10],sel0=sel[0],sel1=sel[1],sel2=sel[2],out=out[10]);
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/Not.hdl
|
||||
|
||||
/**
|
||||
* Not gate:
|
||||
* out = not in
|
||||
*/
|
||||
|
||||
CHIP Not {
|
||||
IN in;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Nand(a=in,b=in,out=out);
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/Not16.hdl
|
||||
|
||||
/**
|
||||
* 16-bit Not:
|
||||
* for i=0..15: out[i] = not in[i]
|
||||
*/
|
||||
|
||||
CHIP Not16 {
|
||||
IN in[16];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Not(in=in[0],out=out[0]);
|
||||
Not(in=in[1],out=out[1]);
|
||||
Not(in=in[2],out=out[2]);
|
||||
Not(in=in[3],out=out[3]);
|
||||
Not(in=in[4],out=out[4]);
|
||||
Not(in=in[5],out=out[5]);
|
||||
Not(in=in[6],out=out[6]);
|
||||
Not(in=in[7],out=out[7]);
|
||||
Not(in=in[8],out=out[8]);
|
||||
Not(in=in[9],out=out[9]);
|
||||
Not(in=in[10],out=out[10]);
|
||||
Not(in=in[11],out=out[11]);
|
||||
Not(in=in[12],out=out[12]);
|
||||
Not(in=in[13],out=out[13]);
|
||||
Not(in=in[14],out=out[14]);
|
||||
Not(in=in[15],out=out[15]);
|
||||
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
CHIP Or {
|
||||
IN a, b;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Not(in=a,out=nota);
|
||||
Not(in=b,out=notb);
|
||||
Nand(a=nota,b=notb,out=out);
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Or16.hdl
|
||||
|
||||
/**
|
||||
* 16-bit bitwise Or:
|
||||
* for i = 1..15 out[i] = (a[i] or b[i])
|
||||
*/
|
||||
|
||||
CHIP Or16 {
|
||||
IN a[16], b[16];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Or(a=a[0],b=b[0],out=out[0]);
|
||||
Or(a=a[1],b=b[1],out=out[1]);
|
||||
Or(a=a[2],b=b[2],out=out[2]);
|
||||
Or(a=a[3],b=b[3],out=out[3]);
|
||||
Or(a=a[4],b=b[4],out=out[4]);
|
||||
Or(a=a[5],b=b[5],out=out[5]);
|
||||
Or(a=a[6],b=b[6],out=out[6]);
|
||||
Or(a=a[7],b=b[7],out=out[7]);
|
||||
Or(a=a[8],b=b[8],out=out[8]);
|
||||
Or(a=a[9],b=b[9],out=out[9]);
|
||||
Or(a=a[10],b=b[10],out=out[10]);
|
||||
Or(a=a[11],b=b[11],out=out[11]);
|
||||
Or(a=a[12],b=b[12],out=out[12]);
|
||||
Or(a=a[13],b=b[13],out=out[13]);
|
||||
Or(a=a[14],b=b[14],out=out[14]);
|
||||
Or(a=a[15],b=b[15],out=out[15]);
|
||||
|
||||
}
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/01/Or8Way.hdl
|
||||
|
||||
/**
|
||||
* 8-way Or:
|
||||
* out = (in[0] or in[1] or ... or in[7])
|
||||
*/
|
||||
|
||||
CHIP Or8Way {
|
||||
IN in[8];
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Or(a=in[0],b=in[1],out=out1);
|
||||
Or(a=out1,b=in[2],out=out2);
|
||||
Or(a=out2,b=in[3],out=out3);
|
||||
Or(a=out3,b=in[4],out=out4);
|
||||
Or(a=out4,b=in[5],out=out5);
|
||||
Or(a=out5,b=in[6],out=out6);
|
||||
Or(a=out6,b=in[7],out=out);
|
||||
|
||||
|
||||
}
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/02/ALU.hdl
|
||||
|
||||
/**
|
||||
* The ALU (Arithmetic Logic Unit).
|
||||
* Computes one of the following functions:
|
||||
* x+y, x-y, y-x, 0, 1, -1, x, y, -x, -y, !x, !y,
|
||||
* x+1, y+1, x-1, y-1, x&y, x|y on two 16-bit inputs,
|
||||
* according to 6 input bits denoted zx,nx,zy,ny,f,no.
|
||||
* In addition, the ALU computes two 1-bit outputs:
|
||||
* if the ALU output == 0, zr is set to 1; otherwise zr is set to 0;
|
||||
* if the ALU output < 0, ng is set to 1; otherwise ng is set to 0.
|
||||
*/
|
||||
|
||||
// Implementation: the ALU logic manipulates the x and y inputs
|
||||
// and operates on the resulting values, as follows:
|
||||
// if (zx == 1) set x = 0 // 16-bit constant
|
||||
// if (nx == 1) set x = !x // bitwise not
|
||||
// if (zy == 1) set y = 0 // 16-bit constant
|
||||
// if (ny == 1) set y = !y // bitwise not
|
||||
// if (f == 1) set out = x + y // integer 2's complement addition
|
||||
// if (f == 0) set out = x & y // bitwise and
|
||||
// if (no == 1) set out = !out // bitwise not
|
||||
// if (out == 0) set zr = 1
|
||||
// if (out < 0) set ng = 1
|
||||
|
||||
CHIP ALU {
|
||||
IN
|
||||
x[16], y[16], // 16-bit inputs
|
||||
zx, // zero the x input?
|
||||
nx, // negate the x input?
|
||||
zy, // zero the y input?
|
||||
ny, // negate the y input?
|
||||
f, // compute out = x + y (if 1) or x & y (if 0)
|
||||
no; // negate the out output?
|
||||
|
||||
OUT
|
||||
out[16], // 16-bit output
|
||||
zr, // 1 if (out == 0), 0 otherwise
|
||||
ng; // 1 if (out < 0), 0 otherwise
|
||||
|
||||
PARTS:
|
||||
Mux16(a=x,b[0..15]=false,sel=zx,out=outZx);//zx +
|
||||
Mux16(a=y,b[0..15]=false,sel=zy,out=outZy);//zy +
|
||||
|
||||
Not16(in=outZx,out=outNx1);//nx1
|
||||
Not16(in=outZy,out=outNy1);//ny1
|
||||
Mux16(a=outZx,b=outNx1,sel=nx,out=outNx);//nx +
|
||||
Mux16(a=outZy,b=outNy1,sel=ny,out=outNy);//ny +
|
||||
|
||||
Add16(a=outNx,b=outNy,out=outF1);//f1 +
|
||||
And16(a=outNy,b=outNx,out=outF0);//f0 +
|
||||
Mux16(a=outF0,b=outF1,sel=f,out=outF);//f
|
||||
|
||||
Not16(in=outF,out=outNo1);//no +
|
||||
Mux16(a=outF, b=outNo1, sel=no, out=out, out[15]=ng, out[0..7]=zr1, out[8..15]=zr2); +
|
||||
|
||||
Or8Way(in=zr1,out=out2);
|
||||
Or8Way(in=zr2,out=out3);
|
||||
Not(in=out2,out=out4);
|
||||
Not(in=out3,out=out5);
|
||||
And(a=out4,b=out5,out=zr);
|
||||
|
||||
}
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/02/Adder16.hdl
|
||||
|
||||
/**
|
||||
* Adds two 16-bit values.
|
||||
* The most significant carry bit is ignored.
|
||||
*/
|
||||
|
||||
CHIP Add16 {
|
||||
IN a[16], b[16];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
HalfAdder(a=a[0], b=b[0], sum=out[0], carry=carry1);
|
||||
FullAdder(a=a[1], b=b[1], c=carry1, sum=out[1], carry=carry2);
|
||||
FullAdder(a=a[2], b=b[2], c=carry2, sum=out[2], carry=carry3);
|
||||
FullAdder(a=a[3], b=b[3], c=carry3, sum=out[3], carry=carry4);
|
||||
FullAdder(a=a[4], b=b[4], c=carry4, sum=out[4], carry=carry5);
|
||||
FullAdder(a=a[5], b=b[5], c=carry5, sum=out[5], carry=carry6);
|
||||
FullAdder(a=a[6], b=b[6], c=carry6, sum=out[6], carry=carry7);
|
||||
FullAdder(a=a[7], b=b[7], c=carry7, sum=out[7], carry=carry8);
|
||||
FullAdder(a=a[8], b=b[8], c=carry8, sum=out[8], carry=carry9);
|
||||
FullAdder(a=a[9], b=b[9], c=carry9, sum=out[9], carry=carry10);
|
||||
|
||||
FullAdder(a=a[10],b=b[10],c=carry10,sum=out[10],carry=carry11);
|
||||
FullAdder(a=a[11],b=b[11],c=carry11,sum=out[11],carry=carry12);
|
||||
FullAdder(a=a[12],b=b[12],c=carry12,sum=out[12],carry=carry13);
|
||||
FullAdder(a=a[13],b=b[13],c=carry13,sum=out[13],carry=carry14);
|
||||
FullAdder(a=a[14],b=b[14],c=carry14,sum=out[14],carry=carry15);
|
||||
FullAdder(a=a[15],b=b[15],c=carry15,sum=out[15],carry=carry16);
|
||||
|
||||
|
||||
}
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/02/FullAdder.hdl
|
||||
|
||||
/**
|
||||
* Computes the sum of three bits.
|
||||
*/
|
||||
|
||||
CHIP FullAdder {
|
||||
IN a, b, c; // 1-bit inputs
|
||||
OUT sum, // Right bit of a + b + c
|
||||
carry; // Left bit of a + b + c
|
||||
|
||||
PARTS:
|
||||
HalfAdder(a=b,b=c,sum=sum1,carry=carry1);
|
||||
HalfAdder(a=a,b=sum1,sum=sum,carry=carry2);
|
||||
Or(a=carry1,b=carry2,out=carry);
|
||||
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/02/HalfAdder.hdl
|
||||
|
||||
/**
|
||||
* Computes the sum of two bits.
|
||||
*/
|
||||
|
||||
CHIP HalfAdder {
|
||||
IN a, b; // 1-bit inputs
|
||||
OUT sum, // Right bit of a + b
|
||||
carry; // Left bit of a + b
|
||||
|
||||
PARTS:
|
||||
Xor(a=a,b=b,out=sum);
|
||||
And(a=a,b=b,out=carry);
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/02/Inc16.hdl
|
||||
|
||||
/**
|
||||
* 16-bit incrementer:
|
||||
* out = in + 1 (arithmetic addition)
|
||||
*/
|
||||
|
||||
CHIP Inc16 {
|
||||
IN in[16];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Add16(a=in, b[1..15]=false, b[0]=true , out=out);
|
||||
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/a/Bit.hdl
|
||||
|
||||
/**
|
||||
* 1-bit register:
|
||||
* If load[t] == 1 then out[t+1] = in[t]
|
||||
* else out does not change (out[t+1] = out[t])
|
||||
*/
|
||||
|
||||
CHIP Bit {
|
||||
IN in, load;
|
||||
OUT out;
|
||||
|
||||
PARTS:
|
||||
Mux(a=out2,b=in,sel=load,out=out1);
|
||||
DFF(in=out1,out=out2,out=out);
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
CHIP DMux8Way16 {
|
||||
IN in[16], sel[3];
|
||||
OUT a[16], b[16], c[16], d[16], e[16], f[16], g[16], h[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(a=a[0],b=b[0],c=c[0],d=d[0],e=e[0],f=f[0],g=g[0],h=h[0],sel=sel,in=in[0]);
|
||||
DMux8Way(a=a[1],b=b[1],c=c[1],d=d[1],e=e[1],f=f[1],g=g[1],h=h[1],sel=sel,in=in[1]);
|
||||
DMux8Way(a=a[2],b=b[2],c=c[2],d=d[2],e=e[2],f=f[2],g=g[2],h=h[2],sel=sel,in=in[2]);
|
||||
DMux8Way(a=a[3],b=b[3],c=c[3],d=d[3],e=e[3],f=f[3],g=g[3],h=h[3],sel=sel,in=in[3]);
|
||||
DMux8Way(a=a[4],b=b[4],c=c[4],d=d[4],e=e[4],f=f[4],g=g[4],h=h[4],sel=sel,in=in[4]);
|
||||
DMux8Way(a=a[5],b=b[5],c=c[5],d=d[5],e=e[5],f=f[5],g=g[5],h=h[5],sel=sel,in=in[5]);
|
||||
DMux8Way(a=a[6],b=b[6],c=c[6],d=d[6],e=e[6],f=f[6],g=g[6],h=h[6],sel=sel,in=in[6]);
|
||||
DMux8Way(a=a[7],b=b[7],c=c[7],d=d[7],e=e[7],f=f[7],g=g[7],h=h[7],sel=sel,in=in[7]);
|
||||
DMux8Way(a=a[8],b=b[8],c=c[8],d=d[8],e=e[8],f=f[8],g=g[8],h=h[8],sel=sel,in=in[8]);
|
||||
DMux8Way(a=a[9],b=b[9],c=c[9],d=d[9],e=e[9],f=f[9],g=g[9],h=h[9],sel=sel,in=in[9]);
|
||||
DMux8Way(a=a[10],b=b[10],c=c[10],d=d[10],e=e[10],f=f[10],g=g[10],h=h[10],sel=sel,in=in[10]);
|
||||
DMux8Way(a=a[11],b=b[11],c=c[11],d=d[11],e=e[11],f=f[11],g=g[11],h=h[11],sel=sel,in=in[11]);
|
||||
DMux8Way(a=a[12],b=b[12],c=c[12],d=d[12],e=e[12],f=f[12],g=g[12],h=h[12],sel=sel,in=in[12]);
|
||||
DMux8Way(a=a[13],b=b[13],c=c[13],d=d[13],e=e[13],f=f[13],g=g[13],h=h[13],sel=sel,in=in[13]);
|
||||
DMux8Way(a=a[14],b=b[14],c=c[14],d=d[14],e=e[14],f=f[14],g=g[14],h=h[14],sel=sel,in=in[14]);
|
||||
DMux8Way(a=a[15],b=b[15],c=c[15],d=d[15],e=e[15],f=f[15],g=g[15],h=h[15],sel=sel,in=in[15]);
|
||||
}
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/a/PC.hdl
|
||||
|
||||
/**
|
||||
* A 16-bit counter with load and reset control bits.
|
||||
* if (reset[t] == 1) out[t+1] = 0
|
||||
* else if (load[t] == 1) out[t+1] = in[t]
|
||||
* else if (inc[t] == 1) out[t+1] = out[t] + 1 (integer addition)
|
||||
* else out[t+1] = out[t]
|
||||
*/
|
||||
|
||||
CHIP PC {
|
||||
IN in[16],load,inc,reset;
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(in=true,sel[0]=reset,sel[1]=load,sel[2]=inc,a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h);
|
||||
|
||||
DFF(in=inc,out=inct);
|
||||
And(a=inc,b=inct,out=out1);
|
||||
Mux16(a=in,b=out4,sel=out1,out=out2);
|
||||
Inc16(in=out2,out=out3);
|
||||
Register(in=out3,load=load,out=out4,out=out);
|
||||
|
||||
Not(in=a,out=notа);
|
||||
Register(in=in,load=notа,out=outA);
|
||||
|
||||
And16(a[0..15]=false,b[0..15]=false,out=outB);
|
||||
|
||||
Register(in=in,load=c,out=outC);
|
||||
|
||||
And16(a[0..15]=false,b[0..15]=false,out=outD);
|
||||
|
||||
|
||||
And16(a[0..15]=false,b[0..15]=false,out=outF);
|
||||
|
||||
Register(in=in,load=g,out=outG);
|
||||
|
||||
And16(a[0..15]=false,b[0..15]=false,out=outH);
|
||||
And16(a[0..15]=false,b[0..15]=false,out=outE);
|
||||
Mux8Way16(a=outA,b=outB,c=outC,d=outD,e=outE,f=outF,g=outG,h=outH,sel[0]=reset,sel[1]=load,sel[2]=inc,out=out67);
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/b/RAM16K.hdl
|
||||
|
||||
/**
|
||||
* Memory of 16K registers, each 16 bit-wide. Out holds the value
|
||||
* stored at the memory location specified by address. If load==1, then
|
||||
* the in value is loaded into the memory location specified by address
|
||||
* (the loaded value will be emitted to out from the next time step onward).
|
||||
*/
|
||||
|
||||
CHIP RAM16K {
|
||||
IN in[16], load, address[14];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux4Way(in=load,sel=address[0..1],a=a,b=b,c=c,d=d);
|
||||
RAM4K(in=in,load=a,address=address[2..13],out=outa);
|
||||
RAM4K(in=in,load=b,address=address[2..13],out=outb);
|
||||
RAM4K(in=in,load=c,address=address[2..13],out=outc);
|
||||
RAM4K(in=in,load=d,address=address[2..13],out=outd);
|
||||
Mux4Way16(a=outa,b=outb,c=outc,d=outd,sel=address[0..1],out=out);
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/b/RAM4K.hdl
|
||||
|
||||
/**
|
||||
* Memory of 4K registers, each 16 bit-wide. Out holds the value
|
||||
* stored at the memory location specified by address. If load==1, then
|
||||
* the in value is loaded into the memory location specified by address
|
||||
* (the loaded value will be emitted to out from the next time step onward).
|
||||
*/
|
||||
|
||||
CHIP RAM4K {
|
||||
IN in[16], load, address[12];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(in=load,sel=address[0..2],a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h);
|
||||
RAM512(in=in,load=a,address=address[3..11],out=outa);
|
||||
RAM512(in=in,load=b,address=address[3..11],out=outb);
|
||||
RAM512(in=in,load=c,address=address[3..11],out=outc);
|
||||
RAM512(in=in,load=d,address=address[3..11],out=outd);
|
||||
RAM512(in=in,load=e,address=address[3..11],out=oute);
|
||||
RAM512(in=in,load=f,address=address[3..11],out=outf);
|
||||
RAM512(in=in,load=g,address=address[3..11],out=outg);
|
||||
RAM512(in=in,load=h,address=address[3..11],out=outh);
|
||||
Mux8Way16(a=outa,b=outb,c=outc,d=outd,e=oute,f=outf,g=outg,h=outh,sel=address[0..2],out=out);
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
// This file is part of the materials accompanying the book
|
||||
// "The Elements of Computing Systems" by Nisan and Schocken,
|
||||
// MIT Press. Book site: www.idc.ac.il/tecs
|
||||
// File name: projects/03/b/RAM512.hdl
|
||||
|
||||
/**
|
||||
* Memory of 512 registers, each 16 bit-wide. Out holds the value
|
||||
* stored at the memory location specified by address. If load==1, then
|
||||
* the in value is loaded into the memory location specified by address
|
||||
* (the loaded value will be emitted to out from the next time step onward).
|
||||
*/
|
||||
|
||||
CHIP RAM512 {
|
||||
IN in[16], load, address[9];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(in=load,sel=address[0..2],a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h);
|
||||
RAM64(in=in,load=a,address=address[3..8],out=outa);
|
||||
RAM64(in=in,load=b,address=address[3..8],out=outb);
|
||||
RAM64(in=in,load=c,address=address[3..8],out=outc);
|
||||
RAM64(in=in,load=d,address=address[3..8],out=outd);
|
||||
RAM64(in=in,load=e,address=address[3..8],out=oute);
|
||||
RAM64(in=in,load=f,address=address[3..8],out=outf);
|
||||
RAM64(in=in,load=g,address=address[3..8],out=outg);
|
||||
RAM64(in=in,load=h,address=address[3..8],out=outh);
|
||||
Mux8Way16(a=outa,b=outb,c=outc,d=outd,e=oute,f=outf,g=outg,h=outh,sel=address[0..2],out=out);
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/a/RAM64.hdl
|
||||
|
||||
/**
|
||||
* Memory of 64 registers, each 16 bit-wide. Out holds the value
|
||||
* stored at the memory location specified by address. If load==1, then
|
||||
* the in value is loaded into the memory location specified by address
|
||||
* (the loaded value will be emitted to out from the next time step onward).
|
||||
*/
|
||||
|
||||
CHIP RAM64 {
|
||||
IN in[16], load, address[6];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(in=load,sel=address[0..2],a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h);
|
||||
RAM8(in=in,load=a,address=address[3..5],out=outa);
|
||||
RAM8(in=in,load=b,address=address[3..5],out=outb);
|
||||
RAM8(in=in,load=c,address=address[3..5],out=outc);
|
||||
RAM8(in=in,load=d,address=address[3..5],out=outd);
|
||||
RAM8(in=in,load=e,address=address[3..5],out=oute);
|
||||
RAM8(in=in,load=f,address=address[3..5],out=outf);
|
||||
RAM8(in=in,load=g,address=address[3..5],out=outg);
|
||||
RAM8(in=in,load=h,address=address[3..5],out=outh);
|
||||
Mux8Way16(a=outa,b=outb,c=outc,d=outd,e=oute,f=outf,g=outg,h=outh,sel=address[0..2],out=out);
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/a/RAM8.hdl
|
||||
|
||||
/**
|
||||
* Memory of 8 registers, each 16 bit-wide. Out holds the value
|
||||
* stored at the memory location specified by address. If load==1, then
|
||||
* the in value is loaded into the memory location specified by address
|
||||
* (the loaded value will be emitted to out from the next time step onward).
|
||||
*/
|
||||
|
||||
CHIP RAM8 {
|
||||
IN in[16], load, address[3];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux8Way(in=load,sel=address,a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h);
|
||||
|
||||
Register(in=in,load=a,out=outa);
|
||||
Register(in=in,load=b,out=outb);
|
||||
Register(in=in,load=c,out=outc);
|
||||
Register(in=in,load=d,out=outd);
|
||||
Register(in=in,load=e,out=oute);
|
||||
Register(in=in,load=f,out=outf);
|
||||
Register(in=in,load=g,out=outg);
|
||||
Register(in=in,load=h,out=outh);
|
||||
Mux8Way16(a=outa,b=outb,c=outc,d=outd,e=oute,f=outf,g=outg,h=outh,sel=address,out=out);
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/03/a/Register.hdl
|
||||
|
||||
/**
|
||||
* 16-bit register:
|
||||
* If load[t] == 1 then out[t+1] = in[t]
|
||||
* else out does not change
|
||||
*/
|
||||
|
||||
CHIP Register {
|
||||
IN in[16], load;
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
Bit(in=in[0],load=load,out=out[0]);
|
||||
Bit(in=in[1],load=load,out=out[1]);
|
||||
Bit(in=in[2],load=load,out=out[2]);
|
||||
Bit(in=in[3],load=load,out=out[3]);
|
||||
Bit(in=in[4],load=load,out=out[4]);
|
||||
Bit(in=in[5],load=load,out=out[5]);
|
||||
Bit(in=in[6],load=load,out=out[6]);
|
||||
Bit(in=in[7],load=load,out=out[7]);
|
||||
Bit(in=in[8],load=load,out=out[8]);
|
||||
Bit(in=in[9],load=load,out=out[9]);
|
||||
Bit(in=in[10],load=load,out=out[10]);
|
||||
Bit(in=in[11],load=load,out=out[11]);
|
||||
Bit(in=in[12],load=load,out=out[12]);
|
||||
Bit(in=in[13],load=load,out=out[13]);
|
||||
Bit(in=in[14],load=load,out=out[14]);
|
||||
Bit(in=in[15],load=load,out=out[15]);
|
||||
|
||||
}
|
||||
Executable
+97
@@ -0,0 +1,97 @@
|
||||
@END //check if button is pressed
|
||||
0;JMP
|
||||
|
||||
(BLACK)
|
||||
//start= 16384 the start of the screen memory
|
||||
@SCREEN
|
||||
D=A
|
||||
@start
|
||||
M=D
|
||||
|
||||
//n=8,192 this is the memory for the display =addreass of the keyboard - address of the screen
|
||||
@8192
|
||||
D=A
|
||||
@n
|
||||
M=D
|
||||
|
||||
//i=0 this is the index for each group of pixels
|
||||
@i
|
||||
M=0
|
||||
|
||||
(LOOP1)
|
||||
//if i==n goto end
|
||||
@i
|
||||
D=M
|
||||
@n
|
||||
D=D-M
|
||||
@END
|
||||
D;JEQ
|
||||
|
||||
//start+1=-1 set each group of pixels to -1 which is = 111111111111
|
||||
@start
|
||||
D=M
|
||||
@i
|
||||
A=D+M
|
||||
M=-1
|
||||
|
||||
// increment i by 1
|
||||
@i
|
||||
M=M+1
|
||||
|
||||
// go back to the start of the loop
|
||||
@LOOP1
|
||||
0;JMP
|
||||
|
||||
(WHITE)
|
||||
//start= 16384 the start of the screen memory
|
||||
@SCREEN
|
||||
D=A
|
||||
@start
|
||||
M=D
|
||||
|
||||
//n=8,192 this is the memory for the display =addreass of the keyboard - address of the screen
|
||||
@8192
|
||||
D=A
|
||||
@n
|
||||
M=D
|
||||
|
||||
//i=0 this is the index for each group of pixels
|
||||
@i
|
||||
M=0
|
||||
|
||||
(LOOP2)
|
||||
//if i==n goto end
|
||||
@i
|
||||
D=M
|
||||
@n
|
||||
D=D-M
|
||||
@END
|
||||
D;JEQ
|
||||
|
||||
//start+1=-1 set each group of pixels to 0 which is = 00000000
|
||||
@start
|
||||
D=M
|
||||
@i
|
||||
A=D+M
|
||||
M=0
|
||||
|
||||
// increment i by 1
|
||||
@i
|
||||
M=M+1
|
||||
|
||||
// go back to the start of the loop
|
||||
@LOOP2
|
||||
0;JMP
|
||||
|
||||
//check if button is pressed
|
||||
(END)
|
||||
@KBD
|
||||
D=M
|
||||
@WHITE
|
||||
D;JEQ
|
||||
@KBD
|
||||
D=M
|
||||
@BLACK
|
||||
D;JNE
|
||||
@END
|
||||
0;JMP
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
@R2
|
||||
M=0
|
||||
@sum
|
||||
M=0
|
||||
(LOOP)
|
||||
@1
|
||||
D=M
|
||||
@END
|
||||
D;JEQ // if R1==0 goto end
|
||||
@R0
|
||||
D=M // D=R0
|
||||
@sum
|
||||
M=M+D // sum=sum+R0
|
||||
@R1
|
||||
M=M-1 //R1=R1-1
|
||||
@sum
|
||||
D=M
|
||||
@R2
|
||||
M=D
|
||||
@LOOP
|
||||
0;JMP
|
||||
(END)
|
||||
@END
|
||||
0;JMP
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/05/CPU.hdl
|
||||
|
||||
/**
|
||||
* The Hack CPU (Central Processing unit), consisting of an ALU,
|
||||
* two registers named A and D, and a program counter named PC.
|
||||
* The CPU is designed to fetch and execute instructions written in
|
||||
* the Hack machine language. In particular, functions as follows:
|
||||
* Executes the inputted instruction according to the Hack machine
|
||||
* language specification. The D and A in the language specification
|
||||
* refer to CPU-resident registers, while M refers to the external
|
||||
* memory location addressed by A, i.e. to Memory[A]. The inM input
|
||||
* holds the value of this location. If the current instruction needs
|
||||
* to write a value to M, the value is placed in outM, the address
|
||||
* of the target location is placed in the addressM output, and the
|
||||
* writeM control bit is asserted. (When writeM==0, any value may
|
||||
* appear in outM). The outM and writeM outputs are combinational:
|
||||
* they are affected instantaneously by the execution of the current
|
||||
* instruction. The addressM and pc outputs are clocked: although they
|
||||
* are affected by the execution of the current instruction, they commit
|
||||
* to their new values only in the next time step. If reset==1 then the
|
||||
* CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather
|
||||
* than to the address resulting from executing the current instruction.
|
||||
*/
|
||||
|
||||
CHIP CPU {
|
||||
|
||||
IN inM[16], // M value input (M = contents of RAM[A])
|
||||
instruction[16], // Instruction for execution
|
||||
reset; // Signals whether to re-start the current
|
||||
// program (reset==1) or continue executing
|
||||
// the current program (reset==0).
|
||||
|
||||
OUT outM[16], // M value output
|
||||
writeM, // Write to M?
|
||||
addressM[15], // Address in data memory (of M)
|
||||
pc[15]; // address of next instruction
|
||||
|
||||
PARTS:
|
||||
Mux16(a=instruction ,b=ALUout ,sel=instruction[15] ,out=outToAreg );
|
||||
ARegister(in=outToAreg ,load=loadAreg ,out=outAreg,out[0..14]=addressM );
|
||||
DRegister(in=ALUout ,load=loadDreg ,out=outDreg );
|
||||
Mux16(a=outAreg ,b=inM ,sel=instruction[12] ,out=outToALU );
|
||||
ALU(x=outDreg ,y=outToALU ,zx=instruction[11] ,nx=instruction[10] ,zy=instruction[9] ,ny=instruction[8] ,f=instruction[7] ,no=instruction[6] ,out=ALUout,out=outM ,zr=zr ,ng=ng );
|
||||
And(a=instruction[3],b=instruction[15],out=writeM);
|
||||
|
||||
//when to load A reg
|
||||
Not(in=instruction[5],out=notd5);
|
||||
Nand(a=instruction[15],b=notd5,out=loadAreg);
|
||||
Not(in=ng,out=notNg);
|
||||
Not(in=zr,out=notZr);
|
||||
|
||||
//when to load D reg
|
||||
And(a=instruction[4],b=instruction[15],out=loadDreg);
|
||||
|
||||
//checking if instruction is a or c before jump decision is made
|
||||
And(a=instruction[2],b=instruction[15],out=J1);
|
||||
And(a=instruction[1],b=instruction[15],out=J2);
|
||||
And(a=instruction[0],b=instruction[15],out=J3);
|
||||
|
||||
//NULL
|
||||
Nand(a=J1,b=J2,out=NandJ1J2);
|
||||
Nand(a=NandJ1J2,b=J3,out=NoJump);
|
||||
//JGT
|
||||
And(a=J3,b=J3,out=AndJ3J3);
|
||||
Or(a=zr,b=ng,out=orZrNg);
|
||||
Not(in=orZrNg,out=NorZrNg);
|
||||
And(a=AndJ3J3,b=NorZrNg,out=JGT);
|
||||
|
||||
//JEQ
|
||||
And(a=J2,b=J2,out=AndJ2J2);
|
||||
And(a=zr,b=zr,out=AndZrZr);
|
||||
And(a=AndZrZr,b=AndJ2J2,out=JEQ);
|
||||
|
||||
//JGE
|
||||
And(a=J3,b=J2,out=AndJ3J2);
|
||||
Or(a=zr,b=notNg,out=AndZrNotNg);
|
||||
And(a=AndZrNotNg,b=AndJ3J2,out=JGE);
|
||||
|
||||
//JLT
|
||||
And(a=J1,b=J1,out=AndJ1J1);
|
||||
And(a=ng,b=ng,out=AndNgNg);
|
||||
And(a=AndJ1J1,b=AndNgNg,out=JLT);
|
||||
|
||||
//JNE
|
||||
And(a=J3,b=J1,out=AndJ3J1);
|
||||
And(a=notZr,b=notZr,out=AndNotZrNotZr);
|
||||
And(a=AndNotZrNotZr,b=AndJ3J1,out=JNE);
|
||||
|
||||
//JLE
|
||||
And(a=J2,b=J1,out=AndJ2J1);
|
||||
And(a=AndJ2J1,b=orZrNg,out=JLE);
|
||||
|
||||
//JMP
|
||||
And(a=AndJ3J1,b=J2,out=JMP);
|
||||
|
||||
Not(in=outToLoad,out=outToLoad1); // once needted to know when to increes but also needed to not it so it dosent load the reg when J1J2J3=000
|
||||
|
||||
//4wayMux one
|
||||
Mux(a=JMP,b=JGT,sel=instruction[0] ,out=out1);
|
||||
Mux(a=JEQ,b=JGE,sel=instruction[0] ,out=out2);
|
||||
Mux(a=out1,b=out2, sel=instruction[1] ,out=out5);
|
||||
|
||||
//4wayMux two
|
||||
Mux(a=JLT,b=JNE,sel=instruction[0] ,out=out3);
|
||||
Mux(a=JLE,b=JMP,sel=instruction[0] ,out=out4);
|
||||
Mux(a=out3,b=out4,sel=instruction[1] ,out=out6);
|
||||
|
||||
//2wayMux
|
||||
Mux(a=out5,b=out6,sel= instruction[2],out=outToLoad);
|
||||
|
||||
PC(in=outAreg ,load=outToLoad ,inc=outToLoad1 ,reset=reset ,out[0..14]=pc);
|
||||
}
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/05/Computer.hdl
|
||||
|
||||
/**
|
||||
* The HACK computer, including CPU, ROM and RAM.
|
||||
* When reset is 0, the program stored in the computer's ROM executes.
|
||||
* When reset is 1, the execution of the program restarts.
|
||||
* Thus, to start a program's execution, reset must be pushed "up" (1)
|
||||
* and "down" (0). From this point onward the user is at the mercy of
|
||||
* the software. In particular, depending on the program's code, the
|
||||
* screen may show some output and the user may be able to interact
|
||||
* with the computer via the keyboard.
|
||||
*/
|
||||
|
||||
CHIP Computer {
|
||||
|
||||
IN reset;
|
||||
|
||||
PARTS:
|
||||
CPU(inM=inM ,instruction=inst ,reset=reset ,outM=outM ,writeM=writeM ,addressM=addressM ,pc=pc );
|
||||
Memory(in=outM ,load=writeM ,address= addressM,out=inM );
|
||||
ROM32K(address=pc ,out=inst );
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/05/Memory.hdl
|
||||
|
||||
/**
|
||||
* The complete address space of the Hack computer's memory,
|
||||
* including RAM and memory-mapped I/O.
|
||||
* The chip facilitates read and write operations, as follows:
|
||||
* Read: out(t) = Memory[address(t)](t)
|
||||
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
|
||||
* In words: the chip always outputs the value stored at the memory
|
||||
* location specified by address. If load==1, the in value is loaded
|
||||
* into the memory location specified by address. This value becomes
|
||||
* available through the out output from the next time step onward.
|
||||
* Address space rules:
|
||||
* Only the upper 16K+8K+1 words of the Memory chip are used.
|
||||
* Access to address>0x6000 is invalid. Access to any address in
|
||||
* the range 0x4000-0x5FFF results in accessing the screen memory
|
||||
* map. Access to address 0x6000 results in accessing the keyboard
|
||||
* memory map. The behavior in these addresses is described in the
|
||||
* Screen and Keyboard chip specifications given in the book.
|
||||
*/
|
||||
|
||||
CHIP Memory {
|
||||
IN in[16], load, address[15];
|
||||
OUT out[16];
|
||||
|
||||
PARTS:
|
||||
DMux4Way(in=load,sel[0]=address[13],sel[1]=address[14] ,a=ram16k ,b=ram16k2,c=ramScreen);
|
||||
Or(a=ram16k ,b=ram16k2 ,out=ram16end);
|
||||
RAM16K(in=in ,load=ram16end ,address=address[0..13] ,out=out1);
|
||||
Screen(in=in ,load=ramScreen ,address=address[0..12] ,out=out2);
|
||||
Keyboard(out=outKey);
|
||||
Mux4Way16(a=out1 ,b=out1 ,c=out2 ,d=outKey ,sel[0]=address[13],sel[1]=address[14] ,out=out);
|
||||
}
|
||||
Executable
+230
@@ -0,0 +1,230 @@
|
||||
def a_instruct(string): # covert the A instruction to bits
|
||||
string = string.strip('@\n')
|
||||
x = "{0:b}".format(int(string)) # convert the number to binary, problem if the number is too big
|
||||
while len(x) < 16: # need to be 16 bits and 1 for \n
|
||||
x = "0" + x
|
||||
return x # return th 16 bit value
|
||||
|
||||
|
||||
def c_instruct(string): # priema edna liniq koeto e edna instrukciq i q prevryshta v bit kod
|
||||
string = string + "\n"
|
||||
flag1, flag2, p = 0, 0, 0
|
||||
dest_s = ''
|
||||
comp_s = ''
|
||||
jump_s = ''
|
||||
for c in range(len(string)):
|
||||
if string[c] == '=': # ako ima ravno znachi predi nego ima destination
|
||||
i = 0
|
||||
flag1 = 1 # diga flag za destination
|
||||
while i < c:
|
||||
p = c
|
||||
dest_s += string[i]
|
||||
i += 1
|
||||
dest_s = destDic.get(dest_s) # convert t to Destination
|
||||
if string[c] == ';': # ako ima ; znachi predi nego ima computation
|
||||
flag2 = 1 # diga flag za Jump
|
||||
if flag1 == 0: # ako flaga za destination ne e dignat zapochvame ot nachaloto na liniqta
|
||||
p = 0
|
||||
else: # ako e zapochvame ot kydeto e ravnoto koeto se pazi vyv var i
|
||||
p = i
|
||||
while p < c:
|
||||
comp_s += string[p]
|
||||
p += 1
|
||||
comp_s = compDic.get(comp_s) # convert t1 to Computation
|
||||
|
||||
if string[c] == '\n':
|
||||
if flag2 == 1: # ako ima flag za jump to vzimame stoinosta na jumpa
|
||||
j = p + 1
|
||||
while j < c:
|
||||
jump_s += string[j]
|
||||
j += 1
|
||||
jump_s = jumpDic.get(jump_s)
|
||||
else: # ako nqma togava vzima stoinosta na computationa
|
||||
j = i + 1
|
||||
while j < c:
|
||||
comp_s += string[j]
|
||||
j += 1
|
||||
comp_s = compDic.get(comp_s)
|
||||
final_result = '111' + comp_s # dobavqme 111 koeto e standart za C instrukt i computation bez koeto nqma instrukciq
|
||||
if dest_s != '': # ako e imalo dest go dobavqme
|
||||
final_result = final_result + dest_s
|
||||
else: # inache dobavqme 3 nuli
|
||||
final_result = final_result + '000'
|
||||
if jump_s != '': # ako e imalo jump go dobavqme
|
||||
final_result = final_result + jump_s
|
||||
else: # inache dobavqme 3 nuli
|
||||
final_result = final_result + '000'
|
||||
return final_result
|
||||
|
||||
|
||||
def check_a_or_c(temp_string):
|
||||
line = ''
|
||||
temp_string1 = ''
|
||||
for j in temp_string: # zapisva liniqta v string koito posle se obrabotva
|
||||
if j != '\n':
|
||||
line += j
|
||||
else:
|
||||
for index in range(len(line)): # proverqva vseki simvol ot liniqta
|
||||
if line[index] == "@": # ako liniqta zapochva s @ znachi e a instrukciq
|
||||
temp_string1 += a_instruct(line) + '\n'
|
||||
line = ''
|
||||
break
|
||||
else: # ako ne zapochva s @ znachi e C instrukciq
|
||||
temp_string1 += c_instruct(line) + '\n'
|
||||
line = ''
|
||||
break
|
||||
return temp_string1
|
||||
|
||||
|
||||
def clear_file(temp_string_cf): # clears the empty lines, comments and spaces and writes them in a string
|
||||
for line in asmfile:
|
||||
f = 0
|
||||
if line == '\n': # removes empty lines
|
||||
continue
|
||||
for index in range(len(line)):
|
||||
if line[index] == "/" and line[index + 1] == '/': # checks if it is comment
|
||||
if f == 1: # maybe a problem if the last element of a line is / since it will stay
|
||||
temp_string_cf += '\n'
|
||||
break
|
||||
if line[index] != ' ': # removes all of the whitespaces except newlines
|
||||
temp_string_cf += line[index]
|
||||
f = 1
|
||||
return temp_string_cf
|
||||
|
||||
|
||||
def label(temp_string): # removes the labels and adds them to the dictionary writes all in a string
|
||||
line = ''
|
||||
temp_string_l = ''
|
||||
global rowasm
|
||||
for j in temp_string: # zapisva liniqta v string koito posle se obrabotva
|
||||
if j != '\n':
|
||||
line += j
|
||||
else:
|
||||
f = 0
|
||||
for index in range(len(line)): # loops through the lines char by char
|
||||
if line[index] == "(":
|
||||
# checks if it is a label, will be a problem if there is only "(" and no closing bracket alse need to check label syntax
|
||||
if bool(labelDic.get(line.strip('()'))) == False: # check if label is already in the Dictionary
|
||||
labelDic[line.strip("()")] = str(rowasm) # adds the label to the dictionary
|
||||
rowasm -= 1 # need to pay attention to the counting cause im not sure
|
||||
f = 1
|
||||
break # brake so i don't write this line in the string since it needs to be removed
|
||||
if f != 1:
|
||||
temp_string_l += line
|
||||
temp_string_l += '\n'
|
||||
rowasm += 1
|
||||
line = ''
|
||||
return temp_string_l
|
||||
|
||||
|
||||
def variable(temp_string): # replaces the variables with the correct address
|
||||
global variableCount
|
||||
line = ''
|
||||
temp_string_v = ''
|
||||
for j in temp_string: # zapisva liniqta v string koito posle se obrabotva
|
||||
if j != '\n':
|
||||
line += j
|
||||
else:
|
||||
for index in range(len(line)):
|
||||
if line[index] == '@' and numbers.find(line[index + 1]) < 0: # checks if the line holds a variable
|
||||
if bool(labelDic.get(line.strip('@'))): # check if variable is already in the Dictionary
|
||||
line = '@' + labelDic[line.strip('@')] # replaces the variable with address i hope
|
||||
else:
|
||||
labelDic[line.strip('@')] = str(variableCount) # if isn't it adds it
|
||||
line = '@' + str(variableCount) # replaces the variable with address i hope
|
||||
variableCount += 1 # increases the variable counter so i don't write them all in address 16
|
||||
break
|
||||
temp_string_v += line + '\n' # appends the line to the string
|
||||
line = ''
|
||||
return temp_string_v
|
||||
|
||||
|
||||
destDic = {'None': '000',
|
||||
'M': '001',
|
||||
'D': '010',
|
||||
'MD': '011',
|
||||
'A': '100',
|
||||
'AM': '101',
|
||||
'AD': '110',
|
||||
'AMD': '111', } # contains all destinations and their bit equivalent
|
||||
jumpDic = {'None': '000',
|
||||
'JGT': '001',
|
||||
'JQE': '010',
|
||||
'JGE': '011',
|
||||
'JLT': '100',
|
||||
'JNE': '101',
|
||||
'JLE': '110',
|
||||
'JMP': '111', } # contains all jumps and their bit equivalent
|
||||
compDic = {'0': '0101010',
|
||||
'1': '0111111',
|
||||
'-1': '0111010',
|
||||
'D': '0001100',
|
||||
'A': '0110000',
|
||||
'!D': '0001101',
|
||||
'!A': '0110001',
|
||||
'-D': '0001111',
|
||||
'-A': '0110011',
|
||||
'D+1': '0011111',
|
||||
'A+1': '0110111',
|
||||
'D-1': '0001110',
|
||||
'A-1': '0110010',
|
||||
'D+A': '0000010',
|
||||
'D-A': '0010011',
|
||||
'A-D': '0000111',
|
||||
'D&A': '0000000',
|
||||
'D|A': '0010101',
|
||||
'M': '1110000',
|
||||
'!M': '1110001',
|
||||
'-M': '1110011',
|
||||
'M+1': '1110111',
|
||||
'M-1': '1110010',
|
||||
'D+M': '1000010',
|
||||
'D-M': '1010011',
|
||||
'M-D': '1000111',
|
||||
'D&M': '1000000',
|
||||
'D|M': '1010101',
|
||||
} # contains all computations and their bit equivalent
|
||||
tempString = '' # create empty string
|
||||
rowasm = 0
|
||||
numbers = '0123456789' # used to check if given instruction calls to variable
|
||||
variableCount = 16 # keeps count of the variable address
|
||||
|
||||
labelDic = {'SP': '0',
|
||||
'LCL': '1',
|
||||
'ARG': '2',
|
||||
'THIS': '3',
|
||||
'THAT': '4',
|
||||
'SCREEN': '16384',
|
||||
'KBD': '24576',
|
||||
'R0': '0',
|
||||
'R1': '1',
|
||||
'R2': '2',
|
||||
'R3': '3',
|
||||
'R4': '4',
|
||||
'R5': '5',
|
||||
'R6': '6',
|
||||
'R7': '7',
|
||||
'R8': '8',
|
||||
'R9': '9',
|
||||
'R10': '10',
|
||||
'R11': '11',
|
||||
'R12': '12',
|
||||
'R13': '13',
|
||||
'R14': '14',
|
||||
'R15': '15',
|
||||
} # dictionary containing Labels and Variables in format: AddressNumber : LabelName/ VariableName
|
||||
with open("C:/Users/AGrudev/Desktop/n2t/nand2tetris/projects/06/pong/Pong.asm", "r+") as asmfile:
|
||||
tempString = clear_file(tempString)
|
||||
print(tempString + '----------')
|
||||
|
||||
tempString = label(tempString)
|
||||
print(tempString + '----------')
|
||||
|
||||
tempString = variable(tempString)
|
||||
print(tempString + '----------')
|
||||
|
||||
tempString = check_a_or_c(tempString)
|
||||
print(tempString + '----------')
|
||||
|
||||
with open("C:/Users/AGrudev/Desktop/n2t/nand2tetris/projects/06/pong/Pong.hack", "w+") as destfile:
|
||||
destfile.write(tempString)
|
||||
Executable
+160
@@ -0,0 +1,160 @@
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
trueCounter = 0
|
||||
falseCounter = 0
|
||||
staticCounter = 16
|
||||
|
||||
|
||||
def clear_file(temp_string_cf, asmfile): # clears the empty lines, comments and spaces and writes them in a string
|
||||
for line in asmfile:
|
||||
f = 0
|
||||
if line == '\n': # removes empty lines
|
||||
continue
|
||||
for index in range(len(line)):
|
||||
if line[index] == "/" and line[index + 1] == '/': # checks if it is comment
|
||||
if f == 1: # maybe a problem if the last element of a line is / since it will stay
|
||||
temp_string_cf += '\n'
|
||||
break
|
||||
if line[index] != ' ': # removes all of the whitespaces except newlines
|
||||
temp_string_cf += line[index]
|
||||
f = 1
|
||||
return temp_string_cf
|
||||
|
||||
|
||||
def push(line):
|
||||
global tempString1
|
||||
if line[4:8] == 'this':
|
||||
number = int(line[8:])
|
||||
line = '@' + str(number) + '\nD=A\n@THIS\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:8] == 'that':
|
||||
number = int(line[8:])
|
||||
line = '@' + str(number) + '\nD=A\n@THAT\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:8] == 'temp':
|
||||
number = int(line[8:])
|
||||
number += 5
|
||||
line = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:9] == 'local':
|
||||
number = int(line[9:])
|
||||
line = '@' + str(number) + '\nD=A\n@LCL\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:10] == 'static':
|
||||
number = int(line[10:])
|
||||
line = '@' + name1 + '.' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:11] == 'pointer':
|
||||
number = int(line[11:])
|
||||
number += 3
|
||||
line = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:12] == 'argument':
|
||||
number = int(line[12:])
|
||||
line = '@' + str(number) + '\nD=A\n@ARG\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
elif line[4:12] == 'constant':
|
||||
number = line[12:]
|
||||
line = '@' + str(number) + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
tempString1 += line
|
||||
|
||||
|
||||
def pop(line):
|
||||
global SP
|
||||
global tempString1
|
||||
if line[3:7] == 'this':
|
||||
number = int(line[7:])
|
||||
line = '@' + str(number) + '\nD=A\n@THIS\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THIS\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@THIS\nM=M-D\n'
|
||||
elif line[3:7] == 'that':
|
||||
number = int(line[7:])
|
||||
line = '@' + str(number) + '\nD=A\n@THAT\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THAT\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@THAT\nM=M-D\n'
|
||||
elif line[3:7] == 'temp':
|
||||
number = int(line[7:])
|
||||
number = number + 5
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n'
|
||||
elif line[3:8] == 'local':
|
||||
number = int(line[8:])
|
||||
line = '@' + str(number) + '\nD=A\n@LCL\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@LCL\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@LCL\nM=M-D\n'
|
||||
elif line[3:9] == 'static':
|
||||
number = int(line[9:])
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\n@' + name1 + '.' + str(number) + '\nM=D\n'
|
||||
elif line[3:10] == 'pointer':
|
||||
number = int(line[10:])
|
||||
number = number + 3
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n'
|
||||
elif line[3:11] == 'argument':
|
||||
number = int(line[11:])
|
||||
line = '@' + str(number) + '\nD=A\n@ARG\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@ARG\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@ARG\nM=M-D\n'
|
||||
tempString1 += line
|
||||
|
||||
|
||||
def aritmetic(line):
|
||||
global trueCounter
|
||||
global falseCounter
|
||||
global tempString1
|
||||
if line == 'add':
|
||||
line = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M+D\n"
|
||||
elif line == 'sub':
|
||||
line = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M-D\n"
|
||||
elif line == 'neg':
|
||||
line = "@SP\nA=M\nA=A-1\nM=-M\n"
|
||||
elif line == 'eq':
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JEQ\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif line == 'gt':
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JGT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif line == 'lt':
|
||||
line = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JLT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif line == 'and':
|
||||
line = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M&D\n"
|
||||
elif line == 'or':
|
||||
line = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M|D\n"
|
||||
elif line == 'not':
|
||||
line = "@SP\nA=M\nA=A-1\nM=!M\n"
|
||||
tempString1 += line
|
||||
|
||||
|
||||
name1 = None
|
||||
line, tempString = '', ''
|
||||
tempString1 = ''
|
||||
aritmeticList3 = ['add', 'sub', 'neg', 'and', 'not']
|
||||
aritmeticList2 = ['or', 'gt', 'lt', 'eq']
|
||||
yourpath = os.getcwd()
|
||||
for root, dirs, files in os.walk(yourpath, topdown=False):
|
||||
nam1 = ''
|
||||
for name in files:
|
||||
if name[-3:] == '.vm':
|
||||
name1 = name
|
||||
tempString1 = ''
|
||||
tempString = ''
|
||||
with open(Path(root, name), "r+") as vmfile:
|
||||
tempString = clear_file(tempString, vmfile)
|
||||
for j in tempString: # zapisva liniqta v string koito posle se obrabotva
|
||||
if j != '\n':
|
||||
line += j
|
||||
else:
|
||||
if line[:4] == 'push':
|
||||
push(line)
|
||||
line = ''
|
||||
elif line[:3] == 'pop':
|
||||
pop(line)
|
||||
line = ''
|
||||
elif line[:2] in aritmeticList2 or line[:3] in aritmeticList3:
|
||||
aritmetic(line)
|
||||
line = ''
|
||||
if name1 == name:
|
||||
with open(Path(root, f'{name1[:-3]}.asm'), 'w+') as newfile:
|
||||
newfile.write(tempString1)
|
||||
Executable
+246
@@ -0,0 +1,246 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def clear_file(clearfile):
|
||||
temp_string_cf = '' # clears the empty lines, comments and spaces and writes them in a string
|
||||
for vmline in clearfile:
|
||||
flag = 0
|
||||
if vmline == '\n':
|
||||
continue
|
||||
for index in range(len(vmline)):
|
||||
if vmline[index:index + 2] == '//':
|
||||
if flag == 1:
|
||||
temp_string_cf += '\n'
|
||||
break
|
||||
if flag == 1 and vmline[index:index + 2] == ' ':
|
||||
temp_string_cf += '\n'
|
||||
break
|
||||
temp_string_cf += vmline[index]
|
||||
flag = 1
|
||||
return temp_string_cf
|
||||
|
||||
|
||||
def push(pushline, funcname):
|
||||
if 'this' in pushline:
|
||||
number = int(pushline[10:])
|
||||
pushline = '@' + str(number) + '\nD=A\n@THIS\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THIS\n'
|
||||
elif 'that' in pushline:
|
||||
number = int(pushline[10:])
|
||||
pushline = '@' + str(number) + '\nD=A\n@THAT\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push THAT\n'
|
||||
elif 'temp' in pushline:
|
||||
number = int(pushline[10:])
|
||||
number += 5
|
||||
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push TMP\n'
|
||||
elif 'local' in pushline:
|
||||
number = int(pushline[11:])
|
||||
pushline = '@' + str(number) + '\nD=A\n@LCL\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push LOCAL\n'
|
||||
elif 'static' in pushline:
|
||||
number = int(pushline[12:])
|
||||
pushline = '@' + funcname + '.' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push STATIC\n'
|
||||
elif 'pointer' in pushline:
|
||||
number = int(pushline[13:])
|
||||
number += 3
|
||||
pushline = '@' + str(number) + '\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push POINTER\n'
|
||||
elif 'argument' in pushline:
|
||||
number = int(pushline[14:])
|
||||
pushline = '@' + str(number) + '\nD=A\n@ARG\nA=M+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push ARGUMENT\n'
|
||||
elif 'constant' in pushline:
|
||||
number = pushline[14:]
|
||||
pushline = '@' + str(number) + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//push CONSTANT\n'
|
||||
return pushline
|
||||
|
||||
|
||||
def pop(popline, funcname):
|
||||
if 'this' in popline:
|
||||
number = int(popline[9:])
|
||||
popline = '@' + str(number) + '\nD=A\n@THIS\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THIS\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@THIS\nM=M-D\n//pop THIS\n'
|
||||
elif 'that' in popline:
|
||||
number = int(popline[9:])
|
||||
popline = '@' + str(number) + '\nD=A\n@THAT\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@THAT\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@THAT\nM=M-D\n//pop THAT\n'
|
||||
elif 'temp' in popline:
|
||||
number = int(popline[9:])
|
||||
number = number + 5
|
||||
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop TMP\n'
|
||||
elif 'local' in popline:
|
||||
number = int(popline[10:])
|
||||
popline = '@' + str(number) + '\nD=A\n@LCL\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@LCL\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@LCL\nM=M-D\n//pop LOCAL\n'
|
||||
elif 'static' in popline:
|
||||
number = int(popline[11:])
|
||||
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + funcname + '.' + str(number) + '\nM=D\n//pop STATIC\n'
|
||||
elif 'pointer' in popline:
|
||||
number = int(popline[12:])
|
||||
number = number + 3
|
||||
popline = '@SP\nM=M-1\nA=M\nD=M\n@' + str(number) + '\nM=D\n//pop POINTER\n'
|
||||
elif 'argument' in popline:
|
||||
number = int(popline[13:])
|
||||
popline = '@' + str(number) + '\nD=A\n@ARG\nM=M+D\n@SP\nM=M-1\nA=M\nD=M\n@ARG\nA=M\nM=D\n' + '@' + str(
|
||||
number) + '\nD=A\n@ARG\nM=M-D\n//pop ARG\n'
|
||||
return popline
|
||||
|
||||
|
||||
def aritmetic(armline):
|
||||
global trueCounter
|
||||
global falseCounter
|
||||
if armline == 'add':
|
||||
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M+D\n//ADD\n"
|
||||
elif armline == 'sub':
|
||||
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M-D\n//SUB\n"
|
||||
elif armline == 'neg':
|
||||
armline = "@SP\nA=M\nA=A-1\nM=-M\n//NEG\n"
|
||||
elif armline == 'eq':
|
||||
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JEQ\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n//EQ\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif armline == 'gt':
|
||||
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JGT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n//GT\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif armline == 'lt':
|
||||
armline = '@SP\nM=M-1\nA=M\nD=M\nA=A-1\nD=M-D\n@TRUE' + str(
|
||||
trueCounter) + '\nD;JLT\n@SP\nA=M\nA=A-1\nM=0\n@FALSE' + str(
|
||||
falseCounter) + '\n0;JMP\n(TRUE' + str(trueCounter) + ')\n@SP\nA=M\nA=A-1\nM=-1\n(FALSE' + str(
|
||||
falseCounter) + ')\n//LT\n'
|
||||
trueCounter += 1
|
||||
falseCounter += 1
|
||||
elif armline == 'and':
|
||||
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M&D\n//AND\n"
|
||||
elif armline == 'or':
|
||||
armline = "@SP\nM=M-1\nA=M\nD=M\nA=A-1\nM=M|D\n//OR\n"
|
||||
elif armline == 'not':
|
||||
armline = "@SP\nA=M\nA=A-1\nM=!M\n//NOT\n"
|
||||
return armline
|
||||
|
||||
|
||||
def label(labelline):
|
||||
labelline = '(' + func_label_name + '$' + labelline[6:] + ')\n//LABEL\n'
|
||||
return labelline
|
||||
|
||||
|
||||
def goto(gotoline):
|
||||
gotoline = '@' + func_label_name + '$' + gotoline[5:] + '\n0;JMP\n//GOTO\n'
|
||||
return gotoline
|
||||
|
||||
|
||||
def if_goto(ifline):
|
||||
ifline = '@SP\nM=M-1\nA=M\nD=M\n@' + func_label_name + '$' + ifline[8:] + '\nD;JNE\n//IFGOTO\n'
|
||||
return ifline
|
||||
|
||||
|
||||
def define_func(funcline):
|
||||
global func_label_name
|
||||
def_func_list = funcline.rsplit(' ')
|
||||
func_label_name = def_func_list[1]
|
||||
funcline = '(' + def_func_list[1] + ')\n'
|
||||
for ind in range(int(def_func_list[2])):
|
||||
funcline += '@0\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n//DEFINEFUNC\n'
|
||||
return funcline
|
||||
|
||||
|
||||
def call_func(callline):
|
||||
global f
|
||||
call_func_list = callline.rsplit(' ')
|
||||
callline = '@' + call_func_list[1] + str(f) + 'RA\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
callline += '@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
callline += '@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
callline += '@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
callline += '@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'
|
||||
callline += '@SP\nD=M\n@' + call_func_list[2] + '\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n'
|
||||
callline += '@SP\nD=M\n@LCL\nM=D\n'
|
||||
callline += '@' + call_func_list[1] + '\n0;JMP\n'
|
||||
callline += '(' + call_func_list[1] + str(f) + 'RA)\n//CALLFUNC\n'
|
||||
f += 1
|
||||
return callline
|
||||
|
||||
|
||||
def return_func(returnline):
|
||||
returnline = '@LCL\nD=M\n@R13\nM=D\n'
|
||||
returnline += '@5\nD=A\n@R13\nD=M-D\nA=D\nD=M\n@R14\nM=D\n'
|
||||
returnline += '@SP\nA=M-1\nD=M\n@ARG\nA=M\nM=D\n'
|
||||
returnline += '@ARG\nD=M+1\n@SP\nM=D\n'
|
||||
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THAT\nM=D\n'
|
||||
returnline += '@R13\nM=M-1\nA=M\nD=M\n@THIS\nM=D\n'
|
||||
returnline += '@R13\nM=M-1\nA=M\nD=M\n@ARG\nM=D\n'
|
||||
returnline += '@R13\nM=M-1\nA=M\nD=M\n@LCL\nM=D\n'
|
||||
returnline += '@R14\nA=M\n0;JMP\n//RETURN\n'
|
||||
return returnline
|
||||
|
||||
|
||||
def iterate(name_iterate, yourpath_iterate):
|
||||
line = ''
|
||||
new_string = ''
|
||||
with open(Path(yourpath_iterate, name_iterate + '.vm'), "r+") as vmfile:
|
||||
string_iterate = clear_file(vmfile)
|
||||
for j in string_iterate: # zapisva liniqta v string koito posle se obrabotva
|
||||
if j != '\n':
|
||||
line += j
|
||||
else:
|
||||
if line[:4] == 'push':
|
||||
new_string += push(line, name_iterate)
|
||||
line = ''
|
||||
elif line[:3] == 'pop':
|
||||
new_string += pop(line, name_iterate)
|
||||
line = ''
|
||||
elif line[:2] in aritmeticList2 or line[:3] in aritmeticList3:
|
||||
new_string += aritmetic(line)
|
||||
line = ''
|
||||
elif line[:5] == 'label':
|
||||
new_string += label(line)
|
||||
line = ''
|
||||
elif line[:4] == 'goto':
|
||||
new_string += goto(line)
|
||||
line = ''
|
||||
elif line[:7] == 'if-goto':
|
||||
new_string += if_goto(line)
|
||||
line = ''
|
||||
elif line[:8] == 'function':
|
||||
new_string += define_func(line)
|
||||
line = ''
|
||||
elif line[:4] == 'call':
|
||||
new_string += call_func(line)
|
||||
line = ''
|
||||
elif line[:6] == 'return':
|
||||
new_string += return_func(line)
|
||||
line = ''
|
||||
return new_string
|
||||
|
||||
|
||||
trueCounter = falseCounter = f = 0
|
||||
staticCounter = 16
|
||||
func_label_name = ''
|
||||
aritmeticList3 = ['add', 'sub', 'neg', 'and', 'not']
|
||||
aritmeticList2 = ['or', 'gt', 'lt', 'eq']
|
||||
yourpath = os.getcwd()
|
||||
|
||||
bootstrap = '''@256\nD=A\n@SP\nM=D\n@MainLoopXYZRA\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@LCL\nD=M\n@SP\nA=M\nM=D\n@SP
|
||||
M=M+1\n@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@THAT\nD=M\n@SP\nA=M\nM=D\n@SP
|
||||
M=M+1\n@SP\nD=M\n@0\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n@SP\nD=M\n@LCL\nM=D\n@Sys.init\n0;JMP\n(MainLoopXYZRARA)
|
||||
//CALLFUNC\n'''
|
||||
|
||||
for root, dirs, files in os.walk(yourpath, topdown=False):
|
||||
nameslist = []
|
||||
sysstring, functstring = '', ''
|
||||
for name in files:
|
||||
tempString = ''
|
||||
if name[-3:] == '.vm':
|
||||
nameslist += [name[:-3]]
|
||||
for i in nameslist:
|
||||
if i == 'Sys':
|
||||
sysstring = bootstrap
|
||||
sysstring += iterate(i, root)
|
||||
|
||||
else:
|
||||
functstring += iterate(i, root)
|
||||
if nameslist:
|
||||
with open(Path(root, f'{os.path.split(root)[1]}.asm'), 'w+') as newfile:
|
||||
newfile.write(sysstring + functstring)
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
class Main {
|
||||
function void main (){
|
||||
var int s;
|
||||
let s = -1;
|
||||
do Output.moveCursor(0,20);
|
||||
do Output.printString("Welcome to Tetris");
|
||||
do Sys.wait(2000);
|
||||
do Output.println();
|
||||
do Output.println();
|
||||
do Output.println();
|
||||
while ((s < 0) | (s > 100)){ // gets a number used for seed for the random function
|
||||
let s = Keyboard.readInt("Enter a number between 0 and 100:");
|
||||
do Screen.clearScreen();
|
||||
}
|
||||
do Sys.wait(2000);
|
||||
do Tetris.tetris(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+473
@@ -0,0 +1,473 @@
|
||||
class Piece {
|
||||
static int lBorder, rBorder, uBorder, dBorder, st;
|
||||
field int x1, y1, x2, y2, x3, y3, x4, y4, piece, direction;
|
||||
field bool move;
|
||||
static Array st;
|
||||
|
||||
constructor Piece new(int Ax1, int Ay1, int Ax2, int Ay2, int Ax3, int Ay3, int Ax4, int Ay4, int p) {
|
||||
let x1 = Ax1;
|
||||
let y1 = Ay1;
|
||||
let x2 = Ax2;
|
||||
let y2 = Ay2;
|
||||
let x3 = Ax3;
|
||||
let y3 = Ay3;
|
||||
let x4 = Ax4;
|
||||
let y4 = Ay4;
|
||||
let piece = p;
|
||||
let direction = 0;
|
||||
let move = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
function void init(){
|
||||
var int a;
|
||||
let lBorder = 0;
|
||||
let rBorder = 511;
|
||||
let uBorder = 0;
|
||||
let dBorder = 255;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** draws 2 rectangles also checks if there is a piece at the spawn which will indicate end of the game. */
|
||||
method bool draw() {
|
||||
var bool finish;
|
||||
let finish = true;
|
||||
let finish = Piece.sample(x1,y1) & finish;
|
||||
let finish = Piece.sample(x2,y2) & finish;
|
||||
let finish = Piece.sample(x3,y3) & finish;
|
||||
let finish = Piece.sample(x4,y4) & finish;
|
||||
if (finish){
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x1, y1, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Erases the square from the screen. */
|
||||
method void erase() {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x1, y2, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
return;
|
||||
}
|
||||
/** checks if those coodinates hold any value > 0. */
|
||||
function bool sample(int x, int y){
|
||||
var int value, address, bit, memBlock;
|
||||
let memBlock = x / 16;
|
||||
let address = (32 * y) + memBlock + 16384;
|
||||
if (address > 24576){
|
||||
return false;
|
||||
}
|
||||
let value = Memory.peek(address);
|
||||
if (value = 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
method bool getMove(){
|
||||
return move;
|
||||
}
|
||||
|
||||
/** Checks if the piece can move in the given direction(dir). */
|
||||
method bool fullSample(int dir){
|
||||
var int size1, size2, i, j;
|
||||
var bool result, flagUpon;
|
||||
if (dir = 1){ //down
|
||||
let size1 = x2 - x1;
|
||||
let size2 = x4 - x3;
|
||||
let result = true;
|
||||
while (i < size1){ // for each block of the first rectangle
|
||||
let j = 0;
|
||||
let flagUpon = false;
|
||||
while (j < size2){ // for each block of the second rectangle
|
||||
if ((x1 + i) = (x3 + j)){ // if this block of the first rectangle sits upon a block of the second rectangle
|
||||
let flagUpon = true;
|
||||
}
|
||||
let result = result & Piece.sample(x3 + j, y4 + 1); // if there is a block under the second rectangle
|
||||
let j = j + 16; // sets the coords for the next block of the second rectangle
|
||||
}
|
||||
if (~(flagUpon)){
|
||||
let result = result & Piece.sample(x1 + i, y2 + 1); // if there is a block under the first rectangle
|
||||
}
|
||||
let i = i + 16; // sets the coords for the next block of the firs rectangle
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else{
|
||||
if (dir = 2){ //right
|
||||
let size1 = y2 - y1;
|
||||
let size2 = y4 - y3;
|
||||
let result = true;
|
||||
while (i < size1){
|
||||
let j = 0;
|
||||
let flagUpon = false;
|
||||
while (j < size2){
|
||||
if ((y1 + i) = (y3 + j)){
|
||||
let flagUpon = true;
|
||||
}
|
||||
let result = result & Piece.sample(x4 + 1, (y3 + j));
|
||||
let j = j + 16;
|
||||
}
|
||||
if (~(flagUpon)){
|
||||
let result = result & Piece.sample(x2 + 1, (y1 + i));
|
||||
}
|
||||
let i = i +16;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else{ // left
|
||||
let size1 = y2 - y1;
|
||||
let size2 = y4 - y3;
|
||||
let result = true;
|
||||
while (i < size2){
|
||||
let j = 0;
|
||||
let flagUpon = false;
|
||||
while (j < size1){
|
||||
if ((y3 + i) = (y1 + j)){
|
||||
let flagUpon = true;
|
||||
}
|
||||
let result = result & Piece.sample(x1 - 1, (y1 + j));
|
||||
let j = j + 16;
|
||||
}
|
||||
if (~(flagUpon)){
|
||||
let result = result & Piece.sample(x3 - 1, (y3 + i));
|
||||
}
|
||||
let i = i + 16;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Moves the game piece 16 pixels down. */
|
||||
method void moveDown() {
|
||||
var int i;
|
||||
if ((y2 < dBorder) & (y4 < dBorder) & (move) & fullSample(1)) {
|
||||
while (i < 16){
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x1, y1, x2, y1);
|
||||
do Screen.drawRectangle(x3, y3, x4, y3);
|
||||
let y1 = y1 + 1;
|
||||
let y2 = y2 + 1;
|
||||
let y3 = y3 + 1;
|
||||
let y4 = y4 + 1;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x1, y2, x2, y2);
|
||||
do Screen.drawRectangle(x3, y4, x4, y4);
|
||||
let i = i + 1;
|
||||
do Sys.wait(10);
|
||||
}
|
||||
}
|
||||
else{
|
||||
let move = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the game piece 16 pixels to the left. */
|
||||
method void moveLeft() {
|
||||
var int i;
|
||||
if ((x1 + 15 > lBorder) & (move) & (x3 + 15 > lBorder)& fullSample(0)){
|
||||
while (i < 16){
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x2, y1, x2, y2);
|
||||
do Screen.drawRectangle(x4, y3, x4, y4);
|
||||
let x1 = x1 - 1;
|
||||
let x2 = x2 - 1;
|
||||
let x3 = x3 - 1;
|
||||
let x4 = x4 - 1;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x1, y1, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
let i = i + 1;
|
||||
do Sys.wait(10);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the game piece 16 pixels to the right. */
|
||||
method void moveRight() {
|
||||
var int i;
|
||||
if ((x4 < rBorder) & (move) & (x2 < rBorder) & fullSample(2)){
|
||||
while (i < 16){
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x1, y1, x1, y2);
|
||||
do Screen.drawRectangle(x3, y3, x3, y4);
|
||||
let x1 = x1 + 1;
|
||||
let x2 = x2 + 1;
|
||||
let x3 = x3 + 1;
|
||||
let x4 = x4 + 1;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x1, y1, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
let i = i + 1;
|
||||
do Sys.wait(10);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Deletes the piece and draws it at the new coodinates. */
|
||||
method void reDraw(int Ax1, int Ay1, int Ax2, int Ay2, int Ax3, int Ay3, int Ax4, int Ay4){
|
||||
var int absTmp;
|
||||
if((Ax1 < 175) | (Ax3 < 175) | (Ax2 > 336) | (Ax4 > 336)){
|
||||
return;
|
||||
}
|
||||
if((Ay2 > 255) | (Ay4 > 255) | (Ay1 < 0) | (Ay3 < 0)){
|
||||
return;
|
||||
}
|
||||
if((Ax1 > Ax2) | (Ax3 > Ax4) | (Ay1 > Ay2) | (Ay3 > Ay4)){
|
||||
return;
|
||||
}
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x1, y1, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
do Screen.setColor(true);
|
||||
let x1 = Ax1;
|
||||
let y1 = Ay1;
|
||||
let x2 = Ax2;
|
||||
let y2 = Ay2;
|
||||
let x3 = Ax3;
|
||||
let y3 = Ay3;
|
||||
let x4 = Ax4;
|
||||
let y4 = Ay4;
|
||||
do Screen.drawRectangle(x1, y1, x2, y2);
|
||||
do Screen.drawRectangle(x3, y3, x4, y4);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Rotates the piece clockwise. */
|
||||
method void rotate(){
|
||||
var bool samp;
|
||||
let samp = true;
|
||||
if (direction = 0){ // starting position
|
||||
if (piece = 0){ // arrow
|
||||
let samp = Piece.sample(x4, y1) & samp; // checks if the place at which the new piece will be drawn are free
|
||||
let samp = Piece.sample(x4, y1 - 1) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x2, y2, x4 - 15, y4 - 47, x4, y4); // redraws it at the new location
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
if (piece = 1){
|
||||
let samp = Piece.sample(x1 + 16, y1) & samp;
|
||||
let samp = Piece.sample(x1 + 16, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x4, y1 - 16) & samp;
|
||||
if(samp){
|
||||
do reDraw(x1 + 16, y1 - 16, x4 - 16, y4, x4 - 15, y1 - 16, x4, y1 - 1);
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
if (piece = 2){
|
||||
let samp = Piece.sample(x1 - 16, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x1 - 16, y1) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1 - 16, x2 - 16, y2 + 16, x3 + 32, y3, x4, y4);
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
if (piece = 3){
|
||||
let samp = Piece.sample(x3 + 16, y3 - 32) & samp;
|
||||
let samp = Piece.sample(x4, y4 - 16) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 + 16, y1, x2, y2 + 16, x3 + 16, y3 - 32, x4, y4 - 16);
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
if (piece = 4){
|
||||
let samp = Piece.sample(x3 + 32, y3 - 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x2 - 16, y2 + 16, x3 + 32, y3 - 32, x4 + 16, y4 - 16);
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
if (piece = 5){
|
||||
let samp = Piece.sample(x1 + 32, y1 - 32) & samp;
|
||||
let samp = Piece.sample(x2 + 16, y2 - 16) & samp;
|
||||
let samp = Piece.sample(x4 - 16, y4 + 16) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 + 32, y1 - 32, x2 + 16, y2 - 16, x3, y3, x4 - 16, y4 + 16);
|
||||
let direction = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (direction = 1){
|
||||
if (piece = 0){
|
||||
let samp = Piece.sample(x1, y3) & samp;
|
||||
let samp = Piece.sample(x1 - 1, y3) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y3, x4, y3 + 15, x1, y1, x2, y2);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
if (piece = 1){
|
||||
let samp = Piece.sample(x1 - 16, y1 + 16) & samp;
|
||||
let samp = Piece.sample(x3, y3 + 16) & samp;
|
||||
let samp = Piece.sample(x3, y3 + 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1 + 16, x4, y4 + 16, x3, y3 + 32, x4, y2);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
if (piece = 2){
|
||||
let samp = Piece.sample(x1 - 16, y1 + 16) & samp;
|
||||
let samp = Piece.sample(x2 + 16, y2 - 16) & samp;
|
||||
let samp = Piece.sample(x3 - 32, y3) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1 + 16, x2 + 16, y2 - 16, x3 - 32, y3, x4 - 32, y4);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
if (piece = 3){
|
||||
let samp = Piece.sample(x1 - 16, y1) & samp;
|
||||
let samp = Piece.sample(x4, y4 + 16) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1, x2, y2 - 16, x3 - 16, y3 +32, x4, y4 + 16);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
if (piece = 4){
|
||||
let samp = Piece.sample(x3 - 32, y3 + 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x2 + 16, y2 - 16, x3 - 32, y3 + 32, x4 - 16, y4 + 16);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
if (piece = 5){
|
||||
let samp = Piece.sample(x1 - 16, y1 + 16) & samp;
|
||||
let samp = Piece.sample(x3 + 16, y3 - 16) & samp;
|
||||
let samp = Piece.sample(x4 + 32, y4 - 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 32, y1 + 16, x2 - 16, y2, x3, y3 - 16, x4 + 16, y4 - 32);
|
||||
let direction = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (direction = 2){
|
||||
if (piece = 0){
|
||||
let samp = Piece.sample(x1, y1+16) & samp;
|
||||
let samp = Piece.sample(x1, y1+32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x1 + 15, y1 + 47, x3, y3, x4, y4);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
if (piece = 1){
|
||||
let samp = Piece.sample(x1 - 16, y1 + 16) & samp;
|
||||
let samp = Piece.sample(x3, y3 + 16) & samp;
|
||||
let samp = Piece.sample(x3, y3 + 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1 + 16, x1 + 15, y1 + 31, x1 + 16, y1 - 16, x4 - 16, y4);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
if (piece = 2){
|
||||
let samp = Piece.sample(x1, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x2 + 32, y2 + 16) & samp;
|
||||
let samp = Piece.sample(x4 + 16, y4) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1 - 16, x2 - 32, y2 - 16, x3 + 16, y3 - 32, x4 + 16, y4);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
if (piece = 3){
|
||||
let samp = Piece.sample(x2 - 16, y2 + 16) & samp;
|
||||
let samp = Piece.sample(x3, y3 - 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x2 - 16, y2 + 16, x3, y3 - 32, x4 - 16, y4 - 16);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
if (piece = 4){
|
||||
let samp = Piece.sample(x1 - 16, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x2 - 32, y2) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1 - 16, x2 - 32, y2, x3 + 16, y3 - 16, x4, y4);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
if (piece = 5){
|
||||
let samp = Piece.sample(x1 + 16, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x3 - 16, y3 - 16) & samp;
|
||||
let samp = Piece.sample(x4 - 32, y4 + 32) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 + 16, y1 - 16, x2, y2, x3 - 16, y3 + 16, x4 - 32, y4 + 32);
|
||||
let direction = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (piece = 0){
|
||||
let samp = Piece.sample(x4 + 16, y4) & samp;
|
||||
let samp = Piece.sample(x4 + 32, y4) & samp;
|
||||
if (samp){
|
||||
do reDraw(x3, y3, x4, y4, x1, y1 + 32, x1 + 47, y1 + 47);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
if (piece = 1){
|
||||
let samp = Piece.sample(x1, y1 - 16) & samp;
|
||||
let samp = Piece.sample(x4 + 16, y4) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1 - 16, x2, y2 -16, x1, y1, x4 + 16, y4);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
if (piece = 2){
|
||||
let samp = Piece.sample(x1 + 32, y1 + 16) & samp;
|
||||
let samp = Piece.sample(x3 - 16, y3 + 32) & samp;
|
||||
let samp = Piece.sample(x4 + 16, y4) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 + 32, y1 + 16, x2 + 32, y2 + 16, x3 - 16, y3 + 32, x4 + 16, y4);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
if (piece = 3){
|
||||
let samp = Piece.sample(x3, y3 + 32) & samp;
|
||||
let samp = Piece.sample(x4 + 16, y4 + 16) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1, y1, x2 + 16, y2 - 16, x3, y3 + 32, x4 + 16, y4 + 16);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
if (piece = 4){
|
||||
let samp = Piece.sample(x3 - 16, y3 + 16) & samp;
|
||||
let samp = Piece.sample(x2 + 32, y2) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 + 16, y1 + 16, x2 + 32, y2, x3 - 16, y3 + 16, x4, y4);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
if (piece = 5){
|
||||
let samp = Piece.sample(x1 - 16, y1 + 32) & samp;
|
||||
let samp = Piece.sample(x3 + 16, y3) & samp;
|
||||
let samp = Piece.sample(x4 + 32, y4 - 16) & samp;
|
||||
if (samp){
|
||||
do reDraw(x1 - 16, y1 + 32, x2, y2 + 16, x3 + 16, y3, x4 + 32, y4 - 16);
|
||||
let direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+203
@@ -0,0 +1,203 @@
|
||||
class Tetris {
|
||||
static int points, seed, next_seed;
|
||||
|
||||
function void tetris(int z){
|
||||
var Piece p, nextPiece;
|
||||
var int i, x1, y1, x2, y2, x3, y3, x4, y4, key, j, randTmp, piece_number, moves;
|
||||
var Array left_g, right_g, box, stick, left_z, right_z,dick, all_piece, tmp;
|
||||
do Piece.init();
|
||||
do Tetris.border();
|
||||
let points = 0;
|
||||
let all_piece = Array.new(25);
|
||||
let all_piece[0] = Tetris.newPiece(16,0,31,15, 0,16,47,31, 0); // arrow
|
||||
let all_piece[1] = Tetris.newPiece(0,0,15,15, 0,16,47,31, 1); // right_L
|
||||
let all_piece[2] = Tetris.newPiece(32,16,47,31, 0,32,47,47, 2); // left_L
|
||||
let all_piece[3] = Tetris.newPiece(0,0,31,15, 16,16,47,31, 3); // left_z
|
||||
let all_piece[4] = Tetris.newPiece(16,0,47,15, 0,16,31,31, 4); // right_z
|
||||
let all_piece[5] = Tetris.newPiece(0,0,31,15, 32,0,63,15, 5); //stick
|
||||
let all_piece[6] = Tetris.newPiece(0,0,15,31, 16,0,31,31, 6); //box
|
||||
|
||||
|
||||
let seed = z * 3; // multiply by 3, because it gets in a loop on some even numbers
|
||||
let next_seed = Tetris.randomNumber();
|
||||
do Output.moveCursor(0,0);
|
||||
do Output.printString("Point: ");
|
||||
do Output.printInt(points);
|
||||
do Output.println();
|
||||
do Output.printString("Next Piece: ");
|
||||
while (true){ // The main game loop
|
||||
let j = next_seed;
|
||||
let next_seed = Tetris.randomNumber();
|
||||
let tmp = all_piece[j]; // initializes the coords of the game piece
|
||||
let x1 = tmp[0];
|
||||
let y1 = tmp[1];
|
||||
let x2 = tmp[2];
|
||||
let y2 = tmp[3];
|
||||
let x3 = tmp[4];
|
||||
let y3 = tmp[5];
|
||||
let x4 = tmp[6];
|
||||
let y4 = tmp[7];
|
||||
let piece_number = tmp[8];
|
||||
let p = Piece.new(x1 + 240, y1, x2 + 240, y2, x3 + 240, y3, x4 + 240, y4, piece_number);
|
||||
if (~(p.draw())){ // if a piece tries to spawn above a limit the game ends
|
||||
if (~(Tetris.finish())){
|
||||
return;
|
||||
}
|
||||
}
|
||||
let tmp = all_piece[next_seed];
|
||||
let x1 = tmp[0]; // initializes the coords of the next game piece that is being displayed
|
||||
let y1 = tmp[1];
|
||||
let x2 = tmp[2];
|
||||
let y2 = tmp[3];
|
||||
let x3 = tmp[4];
|
||||
let y3 = tmp[5];
|
||||
let x4 = tmp[6];
|
||||
let y4 = tmp[7];
|
||||
let piece_number = tmp[8];
|
||||
let nextPiece = Piece.new(x1 + 16, y1 + 32, x2+16, y2 + 32, x3+16, y3 + 32, x4 + 16, y4 + 32, piece_number);
|
||||
do nextPiece.draw();
|
||||
while (p.getMove()){
|
||||
let moves = 0;
|
||||
while (moves < 3){ // one can move its piece 3 times before it moves down automatically
|
||||
let key = Keyboard.keyPressed();
|
||||
if (key = 130){
|
||||
do p.moveLeft();
|
||||
do Sys.wait(80);
|
||||
}
|
||||
if (key = 132){
|
||||
do p.moveRight();
|
||||
do Sys.wait(80);
|
||||
}
|
||||
if (key = 131){
|
||||
do p.rotate();
|
||||
}
|
||||
if (key = 133){
|
||||
do p.moveDown();
|
||||
do p.moveDown();
|
||||
}
|
||||
let moves = moves +1;
|
||||
}
|
||||
do p.moveDown();
|
||||
let i = i + 1;
|
||||
do Sys.wait(80);
|
||||
}
|
||||
let i = 0;
|
||||
do p.dispose();
|
||||
do Tetris.completeRow();
|
||||
do Output.moveCursor(0,7);
|
||||
do Output.printInt(points);
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(16,32,80,96);
|
||||
do Screen.setColor(true);
|
||||
do nextPiece.dispose();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function void completeRow(){ // checks if a row has been completed
|
||||
var int adddress, row, colloum;
|
||||
var bool complete;
|
||||
let adddress = 16384 + 11;
|
||||
let row = 15;
|
||||
while (row > 0){ // for each row
|
||||
let complete = true;
|
||||
let colloum = 0;
|
||||
while ((colloum < 10) & (complete)){ // for each collum
|
||||
let complete = Memory.peek(adddress + colloum + (row * 512)) & complete;
|
||||
let colloum = colloum + 1;
|
||||
}
|
||||
if (complete){ // removes the row
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(176, row * 16, 335, ((row * 16)+ 15) );
|
||||
let points = points + 1;
|
||||
do Tetris.shift(row);
|
||||
}
|
||||
let row = row - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function void shift(int rowShift){ // shifts all rows above the completed one
|
||||
var int j, val, adddress, tmp, k;
|
||||
let adddress = 16384 + 11;
|
||||
while (rowShift > 1){ // each row
|
||||
let j = 0;
|
||||
while (j < 10){ // collum in the game field
|
||||
let k = 0;
|
||||
while (k < 16){ // each line a in 16 x 16 box
|
||||
let tmp = adddress + j + (((rowShift - 1) * 512) + (k * 32));
|
||||
let val = Memory.peek(tmp);
|
||||
do Memory.poke(adddress + j + ((rowShift * 512) + (k * 32)), val);
|
||||
do Memory.poke(tmp,0);
|
||||
let k = k+ 1;
|
||||
}
|
||||
let j = j + 1;
|
||||
}
|
||||
let rowShift = rowShift - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function void border(){ // draws a border
|
||||
do Screen.drawLine(175,0,175,255);
|
||||
do Screen.drawLine(336,0,336,255);
|
||||
return;
|
||||
}
|
||||
|
||||
function Array newPiece(int Ax1, int Ay1, int Ax2, int Ay2, int Ax3, int Ay3, int Ax4, int Ay4,int p){
|
||||
var Array gamepice;
|
||||
let gamepice = Array.new(9);
|
||||
let gamepice[0] = Ax1;
|
||||
let gamepice[1] = Ay1;
|
||||
let gamepice[2] = Ax2;
|
||||
let gamepice[3] = Ay2;
|
||||
let gamepice[4] = Ax3;
|
||||
let gamepice[5] = Ay3;
|
||||
let gamepice[6] = Ax4;
|
||||
let gamepice[7] = Ay4;
|
||||
let gamepice[8] = p;
|
||||
return gamepice;
|
||||
}
|
||||
|
||||
function int randomNumber(){ // radom number generator
|
||||
var int multiplier,additor,moduler,toBeModulated;
|
||||
let multiplier = 7;
|
||||
let additor = 13;
|
||||
let moduler = 1133;
|
||||
let toBeModulated = (multiplier * seed) + additor;
|
||||
let seed = Tetris.mod(toBeModulated,moduler);
|
||||
return Tetris.mod(seed,7);
|
||||
}
|
||||
|
||||
function bool finish(){ // after finishing the game the player has 2 options to start onether or to end the game
|
||||
var char c;
|
||||
do Screen.clearScreen();
|
||||
do Output.moveCursor(10,24);
|
||||
do Output.printString("Your score: ");
|
||||
do Output.printInt(points);
|
||||
do Sys.wait(10000);
|
||||
do Screen.clearScreen();
|
||||
do Output.moveCursor(10,0);
|
||||
do Output.printString("Would you like to play again, for yes click 'Y' and for no 'N':");
|
||||
let c = Keyboard.readChar();
|
||||
if (c = 89){
|
||||
do Screen.clearScreen();
|
||||
return false;
|
||||
}
|
||||
if (c = 78){
|
||||
do Screen.clearScreen();
|
||||
do Sys.halt();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function int mod(int tbm, int mo){ //simple moduler devision
|
||||
var int val, tmp2;
|
||||
if (tbm < mo){
|
||||
return tbm;
|
||||
}
|
||||
let tmp2 = (tbm / mo) * mo;
|
||||
let val = tbm - tmp2;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
Executable
+410
@@ -0,0 +1,410 @@
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class Tokenizer:
|
||||
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
self.file = ''
|
||||
self.symbols = ('(', ')', '[', ']', '}', '{', '>', '<', '=', '*', '+', '-', '/', '.', ';', ',', '&', '|',
|
||||
'~', '>', '<', '&')
|
||||
self.key_word = (
|
||||
'class', 'method', 'function', 'constructor', 'int', 'boolean', 'char', 'void', 'var', 'static', 'field',
|
||||
'let', 'do', 'if', 'else', 'while', 'return', 'true', 'false', 'null', 'this')
|
||||
self.token = ''
|
||||
|
||||
def token_type(self):
|
||||
if self.token is None or self.token == '':
|
||||
return None
|
||||
if self.token in self.key_word:
|
||||
return 'keyword'
|
||||
elif self.token[0] == '"':
|
||||
return 'stringConstant'
|
||||
elif re.match(r"\d+", self.token):
|
||||
return 'integerConstant'
|
||||
elif self.token in self.symbols:
|
||||
return 'symbol'
|
||||
else:
|
||||
return 'identifier'
|
||||
|
||||
def advance(self):
|
||||
token = ''
|
||||
i = self.i
|
||||
while i < len(self.file):
|
||||
if re.match(r'\s', self.file[i]):
|
||||
i = i + 1
|
||||
continue
|
||||
else:
|
||||
if self.file[i] in self.symbols:
|
||||
if self.file[i] == '>':
|
||||
self.token = '>'
|
||||
elif self.file[i] == '<':
|
||||
self.token = '<'
|
||||
elif self.file[i] == '&':
|
||||
self.token = '&'
|
||||
else:
|
||||
self.token = self.file[i]
|
||||
# self.token = self.file[i]
|
||||
self.i = i + 1
|
||||
return
|
||||
elif self.file[i] == '"':
|
||||
i += 1
|
||||
while self.file[i] != '"':
|
||||
token += self.file[i]
|
||||
i += 1
|
||||
self.i = i + 1
|
||||
self.token = '"' + token + '"'
|
||||
return
|
||||
else:
|
||||
while re.match(r'\w', self.file[i]):
|
||||
token += self.file[i]
|
||||
if i + 1 > len(self.file) - 1:
|
||||
break
|
||||
i += 1
|
||||
self.i = i
|
||||
self.token = token
|
||||
return
|
||||
|
||||
def clear_file(self, directory):
|
||||
with open(directory, "r") as my_file:
|
||||
txt = my_file.read()
|
||||
txt = re.sub(r"//.*", "", txt)
|
||||
txt = re.sub(r"/[*][*].*[*]/", "", txt)
|
||||
txt = re.sub(r"/[*][*][\w*\W*]*[*]/", "", txt)
|
||||
self.file = txt
|
||||
|
||||
|
||||
class CompilationEngine:
|
||||
def __init__(self):
|
||||
self.string = ''
|
||||
self.tab = 0
|
||||
|
||||
def write_token(self, tokenizer):
|
||||
if tokenizer.token_type() == 'stringConstant':
|
||||
self.string += ' ' * self.tab + '<' + tokenizer.token_type() + '> ' + tokenizer.token.strip('"') + ' </' \
|
||||
+ tokenizer.token_type() + '>\n'
|
||||
else:
|
||||
self.string += ' ' * self.tab + '<' + tokenizer.token_type() + '> ' + tokenizer.token + ' </' \
|
||||
+ tokenizer.token_type() + '>\n'
|
||||
|
||||
def compile_class(self, tokenizer):
|
||||
tokenizer.advance()
|
||||
self.string += '<class>\n' + ' ' * self.tab
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token != '}':
|
||||
if tokenizer.token in ['static', 'field']:
|
||||
self.compile_class_var_dec(tokenizer)
|
||||
if tokenizer.token in ['constructor', 'function', 'method']:
|
||||
self.compile_subroutine(tokenizer)
|
||||
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</class>\n'
|
||||
|
||||
def compile_class_var_dec(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<classVarDec>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token == ',':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</classVarDec>\n'
|
||||
|
||||
def compile_subroutine(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<subroutineDec>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_parameter_list(tokenizer)
|
||||
self.string += ' ' * self.tab + '<subroutineBody>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token != '}':
|
||||
if tokenizer.token == 'var':
|
||||
self.compile_var_dec(tokenizer)
|
||||
elif tokenizer.token in ['let', 'if', 'while', 'do', 'return']:
|
||||
self.compile_statements(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</subroutineBody>\n'
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</subroutineDec>\n'
|
||||
|
||||
def compile_parameter_list(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<parameterList>\n'
|
||||
self.tab += 2
|
||||
while tokenizer.token != ')':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token == ',':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</parameterList>\n'
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
|
||||
def compile_var_dec(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<varDec>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token == ',':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</varDec>\n'
|
||||
|
||||
def compile_statements(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<statements>\n'
|
||||
self.tab += 2
|
||||
while True:
|
||||
if tokenizer.token == 'let':
|
||||
self.compile_let(tokenizer)
|
||||
elif tokenizer.token == 'if':
|
||||
self.compile_if(tokenizer)
|
||||
elif tokenizer.token == 'while':
|
||||
self.compile_while(tokenizer)
|
||||
elif tokenizer.token == 'do':
|
||||
self.compile_do(tokenizer)
|
||||
elif tokenizer.token == 'return':
|
||||
self.compile_return(tokenizer)
|
||||
else:
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</statements>\n'
|
||||
break
|
||||
|
||||
def compile_do(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<doStatement>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
if tokenizer.token == '(':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression_list(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
elif tokenizer.token == '.':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression_list(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</doStatement>\n'
|
||||
|
||||
def compile_let(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<letStatement>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
if tokenizer.token == '[':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</letStatement>\n'
|
||||
|
||||
def compile_while(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<whileStatement>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_statements(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</whileStatement>\n'
|
||||
|
||||
def compile_return(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<returnStatement>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
if tokenizer.token != ';':
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</returnStatement>\n'
|
||||
|
||||
def compile_if(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<ifStatement>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_statements(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
while tokenizer.token == 'else':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_statements(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</ifStatement>\n'
|
||||
|
||||
def compile_expression(self, tokenizer):
|
||||
if tokenizer.token in ['(', '~', '-'] or tokenizer.token_type() != 'symbol':
|
||||
self.string += ' ' * self.tab + '<expression>\n'
|
||||
self.tab += 2
|
||||
self.compile_term(tokenizer)
|
||||
while tokenizer.token in ['+', '-', '*', '/', '&', '|', '<', '>', '=']:
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_term(tokenizer)
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</expression>\n'
|
||||
|
||||
def compile_term(self, tokenizer):
|
||||
if tokenizer.token == '(':
|
||||
self.string += ' ' * self.tab + '<term>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
elif tokenizer.token in ['~', '-']:
|
||||
self.string += ' ' * self.tab + '<term>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_term(tokenizer)
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
elif tokenizer.token_type() != 'symbol':
|
||||
self.string += ' ' * self.tab + '<term>\n'
|
||||
self.tab += 2
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
if tokenizer.token == '[':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
elif tokenizer.token == '(':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression_list(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
elif tokenizer.token == '.':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression_list(tokenizer)
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
else:
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</term>\n'
|
||||
|
||||
def compile_expression_list(self, tokenizer):
|
||||
self.string += ' ' * self.tab + '<expressionList>\n'
|
||||
self.tab += 2
|
||||
self.compile_expression(tokenizer)
|
||||
while tokenizer.token == ',':
|
||||
self.write_token(tokenizer)
|
||||
tokenizer.advance()
|
||||
self.compile_expression(tokenizer)
|
||||
self.tab -= 2
|
||||
self.string += ' ' * self.tab + '</expressionList>\n'
|
||||
|
||||
|
||||
path = os.getcwd()
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for name in files:
|
||||
if name[-4:] == 'jack':
|
||||
tok = Tokenizer()
|
||||
tok.clear_file(Path(root, name))
|
||||
ce = CompilationEngine()
|
||||
ce.compile_class(tok)
|
||||
with open(Path(root, name[:-4] + 'xml'), "w+") as my_xml:
|
||||
my_xml.write(ce.string)
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from tokenizer import Tokenizer
|
||||
from vmwriter import VMWriter
|
||||
from symbol_table import SymbolTable
|
||||
|
||||
|
||||
# TODO add names to variables when you call for them, aka current_vm_append(thingtobeappended=blablac)
|
||||
|
||||
class CompilationEngine:
|
||||
def __init__(self, tokenizer, full_path_vm):
|
||||
self.string = self.sub_type = self.class_name = self.function_type = ''
|
||||
self.tab = self.recursion_index = 0
|
||||
self.tokenizer = tokenizer
|
||||
self.sym_table = []
|
||||
self.vmwriter = VMWriter(full_path_vm)
|
||||
self.current_vm = [] # used to reverse some of the commands, eg a+b need to be a b +
|
||||
|
||||
def search_kind_of_sym(self, current_vm):
|
||||
if self.sym_table[-1].kind_of(current_vm) is not None:
|
||||
return self.sym_table[-1].kind_of(current_vm), self.sym_table[-1].index_of(current_vm)
|
||||
for i in range(len(self.sym_table) - 2, -1,
|
||||
-1): # start from the amount of sym_tables -2 so it starts from one below the current,
|
||||
# until it is bigger than -1, walking it backwards
|
||||
if self.sym_table[i].kind_of(current_vm) in ('static', 'this'):
|
||||
return self.sym_table[i].kind_of(current_vm), self.sym_table[i].index_of(current_vm)
|
||||
|
||||
def search_type_of_sym(self, current_vm):
|
||||
for i in range(len(self.sym_table) - 1, -1, -1):
|
||||
if self.sym_table[i].type_of(current_vm) is not None:
|
||||
return self.sym_table[i].type_of(current_vm)
|
||||
|
||||
def write_token(self):
|
||||
if self.tokenizer.token_type() == 'stringConstant':
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token.strip(
|
||||
'"') + ' </' + self.tokenizer.token_type() + '>\n'
|
||||
else:
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token + ' </' \
|
||||
+ self.tokenizer.token_type() + '>\n'
|
||||
|
||||
def compile_class(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.tokenizer.advance() # class ->
|
||||
self.tokenizer.advance() # type ->
|
||||
self.class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token != '}':
|
||||
if self.tokenizer.token in ['static', 'field']:
|
||||
self.compile_class_var_dec()
|
||||
if self.tokenizer.token in ['constructor', 'function', 'method']:
|
||||
self.compile_subroutine()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
self.vmwriter.close_vm_file()
|
||||
|
||||
def compile_class_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_subroutine(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.sub_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine type(function|method|constructor) ->
|
||||
self.function_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine kind(int|void|etc..) ->
|
||||
sub_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
if self.sub_type == 'method':
|
||||
self.sym_table[-1].start_subroutine('this', self.class_name)
|
||||
self.compile_parameter_list()
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token == 'var': # create only symbol teable entries
|
||||
self.compile_var_dec()
|
||||
if self.sub_type == 'constructor':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('constant', self.sym_table[-2].var_count('field'))
|
||||
self.vmwriter.write_call('Memory.alloc', 1)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
elif self.sub_type == 'method':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('argument', 0)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
else:
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
while self.tokenizer.token != '}':
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
|
||||
def compile_parameter_list(self):
|
||||
if self.tokenizer.token != ')':
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # var ype ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # var name ->
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance() # , ->
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # type ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # )->
|
||||
|
||||
def compile_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_statements(self):
|
||||
while True:
|
||||
if self.tokenizer.token == 'let':
|
||||
self.compile_let()
|
||||
elif self.tokenizer.token == 'if':
|
||||
self.compile_if()
|
||||
elif self.tokenizer.token == 'while':
|
||||
self.compile_while()
|
||||
elif self.tokenizer.token == 'do':
|
||||
self.compile_do()
|
||||
elif self.tokenizer.token == 'return':
|
||||
self.compile_return()
|
||||
else:
|
||||
break
|
||||
|
||||
def compile_do(self):
|
||||
self.tokenizer.advance() # do ->
|
||||
class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.tokenizer.token == '(': # method
|
||||
self.vmwriter.write_push('pointer', 0)
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{class_name}', count + 1)
|
||||
elif self.tokenizer.token == '.': # method or function
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = f'{class_name}.{self.tokenizer.token}'
|
||||
sname = f'{self.search_type_of_sym(class_name)}.{self.tokenizer.token}'
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(class_name))
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_call(f'{sname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{fname}', count)
|
||||
self.vmwriter.write_pop('temp', '0')
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_let(self):
|
||||
flag_array = 0
|
||||
self.tokenizer.advance() # let ->
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # var_name ->
|
||||
if self.tokenizer.token == '[':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ] ->
|
||||
flag_array = 1
|
||||
self.tokenizer.advance() # = ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ; ->
|
||||
if flag_array == 0:
|
||||
self.vmwriter.write_pop(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
self.vmwriter.write_pop('temp', 1)
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('temp', 1)
|
||||
self.vmwriter.write_pop('that', 0)
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_while(self):
|
||||
self.tokenizer.advance() # while ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_lable(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_goto(label1)
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_return(self):
|
||||
self.tokenizer.advance() # return ->
|
||||
if self.tokenizer.token != ';':
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_return(self.function_type)
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_if(self):
|
||||
self.tokenizer.advance() # if ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_goto(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.vmwriter.write_lable(label1)
|
||||
if self.tokenizer.token == 'else':
|
||||
self.tokenizer.advance() # else ->
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_expression(self):
|
||||
self.compile_term()
|
||||
while self.tokenizer.token in ['+', '-', '*', '/', '|', '=', '>', '<', '&']:
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # symbol ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_term(self):
|
||||
if self.tokenizer.token == '(': # expression ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
elif self.tokenizer.token in ['~', '-']: # uniry op
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
tmp = 'neg' if self.tokenizer.token == '-' else self.tokenizer.token
|
||||
self.tokenizer.advance() # ~ or - ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(tmp)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type() != 'symbol':
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # integer, string, keyword, varnname, subroutine_name, class_name, var_name ->
|
||||
if self.tokenizer.token == '[': # Array
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('that', 0)
|
||||
self.tokenizer.advance() # ] ->
|
||||
elif self.tokenizer.token == '(': # subroutine_name ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{self.current_vm[-1]}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token == '.': # method
|
||||
if self.search_type_of_sym(self.current_vm[-1]) is not None:
|
||||
flag = 1
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
flag = 0
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if flag == 1:
|
||||
self.vmwriter.write_call(f'{self.search_type_of_sym(self.current_vm[-1])}.{fname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{self.current_vm[-1]}.{fname}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'stringConstant':
|
||||
self.vmwriter.write_push('constant', len(self.current_vm[-1].strip('"')))
|
||||
self.vmwriter.write_call('String.new', 1)
|
||||
for index, item in enumerate(self.current_vm[-1].strip('"')):
|
||||
self.vmwriter.write_push('constant', ord(item))
|
||||
self.vmwriter.write_call('String.appendChar', 2)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'integerConstant':
|
||||
self.vmwriter.write_push('constant', self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'identifier':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'true':
|
||||
self.vmwriter.write_push('constant', '1')
|
||||
self.vmwriter.write_arithmetic('neg')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'false' or self.current_vm[-1] == 'null':
|
||||
self.vmwriter.write_push('constant', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'this':
|
||||
self.vmwriter.write_push('pointer', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'that':
|
||||
self.vmwriter.write_push('pointer', '1')
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_expression_list(self):
|
||||
count_exp = 0
|
||||
if self.tokenizer.token in ['(', '~', '-'] or self.tokenizer.token_type() != 'symbol':
|
||||
count_exp += 1
|
||||
self.compile_expression()
|
||||
while self.tokenizer.token == ',':
|
||||
count_exp += 1
|
||||
self.tokenizer.advance() # ,
|
||||
self.compile_expression()
|
||||
return count_exp
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
path = os.getcwd()
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for name in files:
|
||||
if name[-4:] == 'jack':
|
||||
tokenizer_main = Tokenizer()
|
||||
tokenizer_main.clear_file(Path(root, name))
|
||||
full_path = Path(root, name[:-4] + 'vm')
|
||||
comp_eng_main = CompilationEngine(tokenizer_main, full_path)
|
||||
comp_eng_main.compile_class()
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
class Symbol:
|
||||
def __init__(self):
|
||||
self.s_name = ''
|
||||
self.s_kind = ''
|
||||
self.s_type = ''
|
||||
self.s_index = 0
|
||||
|
||||
|
||||
class SymbolTable:
|
||||
def __init__(self):
|
||||
self.sym = []
|
||||
|
||||
def define(self, s_name, s_type, s_kind):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = s_kind
|
||||
self.sym[-1].s_index = self.var_count(s_kind) - 1
|
||||
|
||||
def start_subroutine(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'argument'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def start_class(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = 'this'
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'field'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def var_count(self, s_kind):
|
||||
count = 0 # it is -1 so the first index is 0
|
||||
for i in self.sym:
|
||||
if i.s_kind == s_kind:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def kind_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
if i.s_kind == 'var':
|
||||
return 'local'
|
||||
elif i.s_kind == 'field':
|
||||
return 'this'
|
||||
else:
|
||||
return i.s_kind
|
||||
return None
|
||||
|
||||
def type_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_type
|
||||
return None
|
||||
|
||||
def index_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_index
|
||||
return None
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
import re
|
||||
|
||||
|
||||
class Tokenizer:
|
||||
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
self.file = ''
|
||||
self.symbols = ('(', ')', '[', ']', '}', '{', '>', '<', '=', '*', '+', '-', '/', '.', ';', ',', '&', '|',
|
||||
'~')
|
||||
self.key_word = (
|
||||
'class', 'method', 'function', 'constructor', 'int', 'boolean', 'char', 'void', 'var', 'static', 'field',
|
||||
'let', 'do', 'if', 'else', 'while', 'return', 'true', 'false', 'null', 'this')
|
||||
self.token = ''
|
||||
|
||||
def token_type(self, token=None):
|
||||
if token is None:
|
||||
token = self.token
|
||||
if token is None or token == '':
|
||||
return None
|
||||
if token in self.key_word:
|
||||
return 'keyword'
|
||||
elif token[0] == '"':
|
||||
return 'stringConstant'
|
||||
elif re.match(r"\d+", token):
|
||||
return 'integerConstant'
|
||||
elif token in self.symbols:
|
||||
return 'symbol'
|
||||
else:
|
||||
return 'identifier'
|
||||
|
||||
def advance(self):
|
||||
token = ''
|
||||
i = self.i
|
||||
while i < len(self.file):
|
||||
if re.match(r'\s', self.file[i]):
|
||||
i = i + 1
|
||||
continue
|
||||
else:
|
||||
if self.file[i] in self.symbols:
|
||||
self.token = self.file[i]
|
||||
self.i = i + 1
|
||||
return
|
||||
elif self.file[i] == '"':
|
||||
i += 1
|
||||
while self.file[i] != '"':
|
||||
token += self.file[i]
|
||||
i += 1
|
||||
self.i = i + 1
|
||||
self.token = '"' + token + '"'
|
||||
return
|
||||
else:
|
||||
while re.match(r'\w', self.file[i]):
|
||||
token += self.file[i]
|
||||
if i + 1 > len(self.file) - 1:
|
||||
break
|
||||
i += 1
|
||||
self.i = i
|
||||
self.token = token
|
||||
return
|
||||
|
||||
def clear_file(self, directory):
|
||||
with open(directory, "r") as my_file:
|
||||
txt = my_file.read()
|
||||
txt = re.sub(r"//.*", "", txt)
|
||||
txt = re.sub(r"/[*][*].*[*]/", "", txt)
|
||||
i = 0
|
||||
# TODO this should be a regex
|
||||
while i < len(txt):
|
||||
if txt[i] == '/' and txt[i + 1] == '*' and txt[i + 2] == '*':
|
||||
start = i
|
||||
while txt[i] != '*' or txt[i + 1] != '/':
|
||||
i += 1
|
||||
stop = i + 2
|
||||
txt = txt[:start] + txt[stop:len(txt)]
|
||||
i = start - 1
|
||||
i += 1
|
||||
self.file = txt
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
class VMWriter:
|
||||
def __init__(self, vm_path):
|
||||
self.my_vm = open(vm_path, "w+")
|
||||
self.label_index = 0
|
||||
|
||||
def write_push(self, segment, index):
|
||||
self.my_vm.write(f'push {segment} {index}\n')
|
||||
print(f'push {segment} {index}')
|
||||
|
||||
def write_lable(self, label):
|
||||
self.my_vm.write(f'label L{label}\n')
|
||||
print(f'label L{label}')
|
||||
|
||||
def write_arithmetic(self, command):
|
||||
if command == '+':
|
||||
self.my_vm.write('add\n')
|
||||
print('add')
|
||||
elif command == '-':
|
||||
self.my_vm.write('sub\n')
|
||||
print('sub')
|
||||
elif command == 'neg':
|
||||
self.my_vm.write('neg\n')
|
||||
print('neg')
|
||||
elif command == '=':
|
||||
self.my_vm.write('eq\n')
|
||||
print('eq')
|
||||
elif command == '>':
|
||||
self.my_vm.write('gt\n')
|
||||
print('gt')
|
||||
elif command == '<':
|
||||
self.my_vm.write('lt\n')
|
||||
print('lt')
|
||||
elif command == '&':
|
||||
self.my_vm.write('and\n')
|
||||
print('and')
|
||||
elif command == '|':
|
||||
self.my_vm.write('or\n')
|
||||
print('or')
|
||||
elif command == '~':
|
||||
self.my_vm.write('not\n')
|
||||
print('not')
|
||||
elif command == '*':
|
||||
self.write_call('Math.multiply', 2)
|
||||
elif command == '/':
|
||||
self.write_call('Math.divide', 2)
|
||||
|
||||
def write_pop(self, segment, index):
|
||||
print(f'pop {segment} {index}')
|
||||
self.my_vm.write(f'pop {segment} {index}\n')
|
||||
|
||||
def write_goto(self, label):
|
||||
self.my_vm.write(f'goto L{label}\n')
|
||||
print(f'goto L{label}')
|
||||
|
||||
def write_if(self, label):
|
||||
self.write_arithmetic('~')
|
||||
self.my_vm.write(f'if-goto L{label}\n')
|
||||
print(f'if-goto L{label}')
|
||||
|
||||
def write_call(self, label, num_args):
|
||||
self.my_vm.write(f'call {label} {num_args}\n')
|
||||
print(f'call {label} {num_args}')
|
||||
|
||||
def write_function(self, label, num_locals):
|
||||
self.my_vm.write(f'function {label} {num_locals}\n')
|
||||
print(f'function {label} {num_locals}')
|
||||
|
||||
def write_return(self, func_type):
|
||||
if func_type == 'void':
|
||||
self.write_push('constant', '0')
|
||||
self.my_vm.write('return\n')
|
||||
print(f'return')
|
||||
|
||||
def close_vm_file(self):
|
||||
self.my_vm.close()
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Array.jack
|
||||
|
||||
/**
|
||||
* Represents an array.
|
||||
* In the Jack language, arrays are instances of the Array class.
|
||||
* Once declared, the array entries can be accessed using the usual
|
||||
* syntax arr[i]. Each array entry can hold a primitive data type as
|
||||
* well as any object type. Different array entries can have different
|
||||
* data types.
|
||||
*/
|
||||
class Array {
|
||||
|
||||
/** Constructs a new Array of the given size. */
|
||||
function Array new(int size) {
|
||||
if(size < 0){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return Memory.alloc(size);
|
||||
}
|
||||
|
||||
/** Disposes this array. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Keyboard.jack
|
||||
|
||||
/**
|
||||
* A library for handling user input from the keyboard.
|
||||
*/
|
||||
|
||||
class Keyboard {
|
||||
static Array mem;
|
||||
/** Initializes the keyboard. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character of the currently pressed key on the keyboard;
|
||||
* if no key is currently pressed, returns 0.
|
||||
*
|
||||
* Recognizes all ASCII characters, as well as the following keys:
|
||||
* new line = 128 = String.newline()
|
||||
* backspace = 129 = String.backspace()
|
||||
* left arrow = 130
|
||||
* up arrow = 131
|
||||
* right arrow = 132
|
||||
* down arrow = 133
|
||||
* home = 134
|
||||
* End = 135
|
||||
* page up = 136
|
||||
* page down = 137
|
||||
* insert = 138
|
||||
* delete = 139
|
||||
* ESC = 140
|
||||
* F1 - F12 = 141 - 152
|
||||
*/
|
||||
function char keyPressed() {
|
||||
return mem[24576];
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until a key is pressed on the keyboard and released,
|
||||
* then echoes the key to the screen, and returns the character
|
||||
* of the pressed key.
|
||||
*/
|
||||
function char readChar() {
|
||||
var char a, b;
|
||||
do Output.printChar(0);
|
||||
while ((b = 0) | (a > 0)){
|
||||
let a = Keyboard.keyPressed();
|
||||
if (a > 0){
|
||||
let b = a;
|
||||
}
|
||||
}
|
||||
do Output.printChar(String.backSpace());
|
||||
do Output.printChar(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its value. Also handles user backspaces.
|
||||
*/
|
||||
function String readLine(String message) {
|
||||
var String s, b;
|
||||
var char c;
|
||||
let s = String.new(100);
|
||||
do Output.printString(message);
|
||||
while (true){
|
||||
let c = Keyboard.readChar();
|
||||
if (c = 128){
|
||||
return s;
|
||||
}
|
||||
else{
|
||||
if (c = 129){
|
||||
do s.eraseLastChar();
|
||||
}
|
||||
else{
|
||||
do s.appendChar(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the message on the screen, reads from the keyboard the entered
|
||||
* text until a newline character is detected, echoes the text to the screen,
|
||||
* and returns its integer value (until the first non-digit character in the
|
||||
* entered text is detected). Also handles user backspaces.
|
||||
*/
|
||||
function int readInt(String message) {
|
||||
var starting a;
|
||||
var int b;
|
||||
let a = Keyboard.readLine(message);
|
||||
let b = String.intValue(a);
|
||||
do String.dispose(a);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/StringTest/Main.jack
|
||||
|
||||
/** Test program for the OS String class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various string manipulations and displays their results. */
|
||||
function void main() {
|
||||
var String s;
|
||||
var String i;
|
||||
|
||||
let s = String.new(0); // a zero-capacity string should be supported
|
||||
do s.dispose();
|
||||
|
||||
let s = String.new(6); // capacity 6, make sure that length 5 is displayed
|
||||
let s = s.appendChar(97);
|
||||
let s = s.appendChar(98);
|
||||
let s = s.appendChar(99);
|
||||
let s = s.appendChar(100);
|
||||
let s = s.appendChar(101);
|
||||
do Output.printString("new: ");
|
||||
do Output.printString(s); // new, appendChar: abcde
|
||||
do Output.println();
|
||||
|
||||
let i = String.new(6);
|
||||
do i.setInt(12345);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: 12345
|
||||
do Output.println();
|
||||
|
||||
do i.setInt(-32767);
|
||||
do Output.printString("setInt: ");
|
||||
do Output.printString(i); // setInt: -32767
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("length: ");
|
||||
do Output.printInt(s.length()); // length: 5
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("charAt[2]: ");
|
||||
do Output.printInt(s.charAt(2)); // charAt[2]: 99
|
||||
do Output.println();
|
||||
|
||||
do s.setCharAt(2, 45);
|
||||
do Output.printString("setCharAt(2,'-'): ");
|
||||
do Output.printString(s); // setCharAt(2,'-'): ab-de
|
||||
do Output.println();
|
||||
|
||||
do s.eraseLastChar();
|
||||
do Output.printString("eraseLastChar: ");
|
||||
do Output.printString(s); // eraseLastChar: ab-d
|
||||
do Output.println();
|
||||
|
||||
let s = "456";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: 456
|
||||
do Output.println();
|
||||
|
||||
let s = "-32123";
|
||||
do Output.printString("intValue: ");
|
||||
do Output.printInt(s.intValue()); // intValue: -32123
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("backSpace: ");
|
||||
do Output.printInt(String.backSpace()); // backSpace: 129
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("doubleQuote: ");
|
||||
do Output.printInt(String.doubleQuote());// doubleQuote: 34
|
||||
do Output.println();
|
||||
|
||||
do Output.printString("newLine: ");
|
||||
do Output.printInt(String.newLine()); // newLine: 128
|
||||
do Output.println();
|
||||
|
||||
do i.dispose();
|
||||
do s.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Math.jack
|
||||
|
||||
/**
|
||||
* A library of commonly used mathematical functions.
|
||||
* Note: Jack compilers implement multiplication and division using OS method calls.
|
||||
*/
|
||||
class Math {
|
||||
static Array st;
|
||||
static int division_tmp, f;
|
||||
|
||||
/** Initializes the library. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the absolute value of x. */
|
||||
function int abs(int x) {
|
||||
if (x > 0){
|
||||
return x;
|
||||
}
|
||||
return -x;
|
||||
}
|
||||
|
||||
/** Returns the product of x and y.
|
||||
* When a Jack compiler detects the multiplication operator '*' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x*y and multiply(x,y) return the same value.
|
||||
*/
|
||||
function int multiply(int x, int y) {
|
||||
var int sum, temp, y_comp, i, neg;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (x < y){
|
||||
let temp = x;
|
||||
let x = y;
|
||||
let y = temp;
|
||||
}
|
||||
if (y = 1){
|
||||
if(neg){
|
||||
return -x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
while((y_comp - 1) < (y - 1)){
|
||||
if ((st[i] & y) > 0) {
|
||||
let sum = sum + x;
|
||||
let y_comp = y_comp + st[i];
|
||||
}
|
||||
let x = x + x;
|
||||
let i = i + 1;
|
||||
}
|
||||
if(neg){
|
||||
let sum = -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Returns the integer part of x/y.
|
||||
* When a Jack compiler detects the multiplication operator '/' in the
|
||||
* program's code, it handles it by invoking this method. In other words,
|
||||
* the Jack expressions x/y and divide(x,y) return the same value.
|
||||
*/
|
||||
function int divide(int x, int y) {
|
||||
var int q, neg;
|
||||
if (f = 0){
|
||||
let division_tmp = 0;
|
||||
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
|
||||
let x = Math.abs(x);
|
||||
let y = Math.abs(y);
|
||||
if (y = 0){
|
||||
do Sys.error(3);
|
||||
}
|
||||
let f = 1;
|
||||
}
|
||||
if ((y > x) | (y < 0)){
|
||||
return 0;
|
||||
}
|
||||
let q = Math.divide(x, y + y);
|
||||
let f = 0;
|
||||
let q = Math.abs(q);
|
||||
if ((q & 1) = 1){
|
||||
let division_tmp = division_tmp + y + y;
|
||||
}
|
||||
if (x - division_tmp < y){
|
||||
if (neg){
|
||||
return -(q + q);
|
||||
}
|
||||
return q + q;
|
||||
}
|
||||
else{
|
||||
if (neg){
|
||||
return -(q + q + 1);
|
||||
}
|
||||
return q + q + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the integer part of the square root of x. */
|
||||
function int sqrt(int x) {
|
||||
var int j, b, d, y;
|
||||
|
||||
if (x < 0){
|
||||
do Sys.error(4);
|
||||
}
|
||||
let j = 7;
|
||||
while (j > -1){
|
||||
let d = y + st[j];
|
||||
let b = d * d;
|
||||
if ((~(b > x)) & (b > 0)){
|
||||
let y = d;
|
||||
}
|
||||
let j = j - 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the greater number. */
|
||||
function int max(int a, int b) {
|
||||
if (a > b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Returns the smaller number. */
|
||||
function int min(int a, int b) {
|
||||
if (a < b){
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Memory.jack
|
||||
|
||||
/**
|
||||
* This library provides two services: direct access to the computer's main
|
||||
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
|
||||
* consists of 32,768 words, each holding a 16-bit binary number.
|
||||
*/
|
||||
class Memory {
|
||||
static Array mem;
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let mem = 0;
|
||||
let mem[2048] = 14334;
|
||||
let mem[2049] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return mem[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let mem[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
var Array current_block;
|
||||
var int tmp;
|
||||
let current_block = 2048;
|
||||
if (size < 0){
|
||||
do Sys.error(5);
|
||||
}
|
||||
if (size = 0){
|
||||
let size = 1;
|
||||
}
|
||||
while (current_block[0] < (size + 2)) {
|
||||
let current_block = current_block[1];
|
||||
}
|
||||
let current_block[0] = current_block[0] - size - 2;
|
||||
let current_block = current_block + current_block[0] + 2;
|
||||
let current_block[0] = size;
|
||||
return current_block + 2;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array current_block;
|
||||
let current_block = 2048;
|
||||
let o[1]= current_block[1];
|
||||
let current_block[1] = o;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Output.jack
|
||||
|
||||
/**
|
||||
* A library of functions for writing text on the screen.
|
||||
* The Hack physical screen consists of 512 rows of 256 pixels each.
|
||||
* The library uses a fixed font, in which each character is displayed
|
||||
* within a frame which is 11 pixels high (including 1 pixel for inter-line
|
||||
* spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
|
||||
* The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
|
||||
* of 64 characters each (indexed 0..63, left to right). The top left
|
||||
* character position on the screen is indexed (0,0). A cursor, implemented
|
||||
* as a small filled square, indicates where the next character will be displayed.
|
||||
*/
|
||||
class Output {
|
||||
|
||||
// Character map for displaying characters
|
||||
static Array charMaps;
|
||||
static int address;
|
||||
static bool half;
|
||||
|
||||
/** Initializes the screen, and locates the cursor at the screen's top-left. */
|
||||
function void init() {
|
||||
do Output.initMap();
|
||||
do Output.moveCursor(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initializes the character map array
|
||||
function void initMap() {
|
||||
var int i;
|
||||
|
||||
let charMaps = Array.new(127);
|
||||
|
||||
// Black square, used for displaying non-printable characters.
|
||||
do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
|
||||
|
||||
// Assigns the bitmap for each character in the charachter set.
|
||||
// The first parameter is the character index, the next 11 numbers
|
||||
// are the values of each row in the frame that represents this character.
|
||||
do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
|
||||
do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
|
||||
do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
|
||||
do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
|
||||
do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
|
||||
do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
|
||||
do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
|
||||
do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
|
||||
do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
|
||||
do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
|
||||
do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
|
||||
do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
|
||||
do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
|
||||
do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
|
||||
do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
|
||||
do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
|
||||
|
||||
do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
|
||||
do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
|
||||
do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
|
||||
do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
|
||||
do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
|
||||
do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
|
||||
do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
|
||||
do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
|
||||
do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
|
||||
do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
|
||||
|
||||
do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
|
||||
do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
|
||||
do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
|
||||
do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
|
||||
do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
|
||||
do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
|
||||
do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
|
||||
|
||||
do Output.create(65,12,30,51,51,63,51,51,51,51,0,0); // A ** TO BE FILLED **
|
||||
do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
|
||||
do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
|
||||
do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
|
||||
do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
|
||||
do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
|
||||
do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
|
||||
do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
|
||||
do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
|
||||
do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
|
||||
do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
|
||||
do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
|
||||
do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
|
||||
do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
|
||||
do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
|
||||
do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
|
||||
do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
|
||||
do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
|
||||
do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
|
||||
do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
|
||||
do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
|
||||
do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
|
||||
do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
|
||||
do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
|
||||
do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
|
||||
do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
|
||||
|
||||
do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
|
||||
do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
|
||||
do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
|
||||
do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
|
||||
do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
|
||||
do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
|
||||
|
||||
do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
|
||||
do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
|
||||
do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
|
||||
do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
|
||||
do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
|
||||
do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
|
||||
do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
|
||||
do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
|
||||
do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
|
||||
do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
|
||||
do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
|
||||
do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
|
||||
do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
|
||||
do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
|
||||
do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
|
||||
do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
|
||||
do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
|
||||
do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
|
||||
do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
|
||||
do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
|
||||
do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
|
||||
do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
|
||||
do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
|
||||
do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
|
||||
do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
|
||||
do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
|
||||
|
||||
do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
|
||||
do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
|
||||
do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
|
||||
do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Creates the character map array of the given character index, using the given values.
|
||||
function void create(int index, int a, int b, int c, int d, int e,
|
||||
int f, int g, int h, int i, int j, int k) {
|
||||
var Array map;
|
||||
|
||||
let map = Array.new(11);
|
||||
let charMaps[index] = map;
|
||||
|
||||
let map[0] = a;
|
||||
let map[1] = b;
|
||||
let map[2] = c;
|
||||
let map[3] = d;
|
||||
let map[4] = e;
|
||||
let map[5] = f;
|
||||
let map[6] = g;
|
||||
let map[7] = h;
|
||||
let map[8] = i;
|
||||
let map[9] = j;
|
||||
let map[10] = k;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns the character map (array of size 11) of the given character.
|
||||
// If the given character is invalid or non-printable, returns the
|
||||
// character map of a black square.
|
||||
function Array getMap(char c) {
|
||||
if ((c < 32) | (c > 126)) {
|
||||
let c = 0;
|
||||
}
|
||||
return charMaps[c];
|
||||
}
|
||||
|
||||
/** Moves the cursor to the j-th column of the i-th row,
|
||||
* and erases the character displayed there. */
|
||||
function void moveCursor(int i, int j) {
|
||||
var int co,display;
|
||||
var Array r,ch;
|
||||
if (j = 0){
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
|
||||
}
|
||||
let address = (352 * i) + (j / 2) + 16384;
|
||||
let ch = Output.getMap(32);
|
||||
|
||||
while (co < 11){
|
||||
if (half){
|
||||
let display = r[address] & (-256);
|
||||
let r[address] = ch[co] | display;
|
||||
}
|
||||
else{
|
||||
let display = r[address] & 255;
|
||||
let r[address] = (ch[co]*256) | display;
|
||||
}
|
||||
let co = co + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
let address = address - 352;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given character at the cursor location,
|
||||
* and advances the cursor one column forward. */
|
||||
function void printChar(char c) {
|
||||
var Array ch;
|
||||
var Array r;
|
||||
var int co;
|
||||
var int ds;
|
||||
let ch = Output.getMap(c);
|
||||
while (co < 11){
|
||||
if (half){
|
||||
let ds = r[address] & (-256);
|
||||
let r[address] = ch[co] | ds;
|
||||
}
|
||||
else{
|
||||
let ds = r[address] & 255;
|
||||
let r[address] = (ch[co]*256) | ds;
|
||||
}
|
||||
let co = co + 1;
|
||||
let address = address + 32;
|
||||
}
|
||||
|
||||
if (half){
|
||||
let address = address - 352;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
if (address > 24480){
|
||||
let address = 16384;
|
||||
let half = true;
|
||||
}
|
||||
else{
|
||||
let address = address - 351;
|
||||
let half = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** displays the given string starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printString(String s) {
|
||||
var int i, length;
|
||||
let length = s.length();
|
||||
while (i < length){
|
||||
do Output.printChar(s.charAt(i));
|
||||
let i = i + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given integer starting at the cursor location,
|
||||
* and advances the cursor appropriately. */
|
||||
function void printInt(int i) {
|
||||
var String s;
|
||||
let s = String.new(6);
|
||||
do s.setInt(i);
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Advances the cursor to the beginning of the next line. */
|
||||
function void println() {
|
||||
var int row;
|
||||
let row = (((address - 16384) / 32)/11) + 1;
|
||||
if (row > 32){
|
||||
let row = 0;
|
||||
}
|
||||
do Output.moveCursor(row, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the cursor one column back. */
|
||||
function void backSpace() {
|
||||
if (address = 16384){
|
||||
let address = 24191;
|
||||
let half = true;
|
||||
return;
|
||||
}
|
||||
if (half){
|
||||
|
||||
let address = address - 1;
|
||||
let half = false;
|
||||
}
|
||||
else{
|
||||
let half = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+206
@@ -0,0 +1,206 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Screen.jack
|
||||
|
||||
/**
|
||||
* A library of functions for displaying graphics on the screen.
|
||||
* The Hack physical screen consists of 256 rows (indexed 0..255, top to bottom)
|
||||
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
|
||||
* the screen is indexed (0,0).
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
static Array mem;
|
||||
static Array st;
|
||||
static boolean color;
|
||||
/** Initializes the Screen. */
|
||||
function void init() {
|
||||
var int a;
|
||||
let st = Array.new(16);
|
||||
let st[0] = 1;
|
||||
while (a < 15){
|
||||
let a = a + 1;
|
||||
let st[a] = st[a - 1] + st[a - 1];
|
||||
}
|
||||
let color = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases the entire screen. */
|
||||
function void clearScreen() {
|
||||
var int a;
|
||||
let a = 16384;
|
||||
while (a < 24575){
|
||||
let mem[a] = 0;
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sets the current color, to be used for all subsequent drawXXX commands.
|
||||
* Black is represented by true, white by false. */
|
||||
function void setColor(boolean b) {
|
||||
let color = b;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the (x,y) pixel, using the current color. */
|
||||
function void drawPixel(int x, int y) {
|
||||
var int value, address, bit, mem_block;
|
||||
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let mem_block = x / 16;
|
||||
let address = (32 * y) + mem_block + 16384;
|
||||
let value = mem[address];
|
||||
let bit = x - (mem_block * 16);
|
||||
if (color){
|
||||
let mem[address] = st[bit] | value;
|
||||
}
|
||||
else{
|
||||
let mem[address] = (~st[bit])& value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
|
||||
function void drawLine(int x1, int y1, int x2, int y2) {
|
||||
var int diff, dx, dy, a, b;
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let dx = x2 - x1;
|
||||
let dy = y2 - y1;
|
||||
if (dx = 0){
|
||||
if (dy > 0){
|
||||
while(~(b > dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(b < dy)){
|
||||
do Screen.drawPixel(x1, y1 + b);
|
||||
let b = b - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dy = 0){
|
||||
if (dx > 0){
|
||||
while(~(a > dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
while(~(a < dx)){
|
||||
do Screen.drawPixel(x1 + a, y1);
|
||||
let a = a - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dx < 0){
|
||||
if (dy < 0){
|
||||
while ((~(a < dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a < dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a - 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff + dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (dy < 0){
|
||||
while ((~(a > dx)) & (~(b < dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff - dy;
|
||||
}
|
||||
else{
|
||||
let b = b - 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
while ((~(a > dx)) & (~(b > dy))){
|
||||
do Screen.drawPixel(x1 + a, y1 + b);
|
||||
if (diff < 0){
|
||||
let a = a + 1;
|
||||
let diff = diff + dy;
|
||||
}
|
||||
else{
|
||||
let b = b + 1;
|
||||
let diff = diff - dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled rectangle whose top left corner is (x1, y1)
|
||||
* and bottom right corner is (x2,y2), using the current color. */
|
||||
function void drawRectangle(int x1, int y1, int x2, int y2) {
|
||||
var int a, tmp;
|
||||
if (x1 > x2){
|
||||
let tmp = x1;
|
||||
let x1 = x2;
|
||||
let x2 = tmp;
|
||||
}
|
||||
if (y1 > y2){
|
||||
let tmp = y1;
|
||||
let y1 = y2;
|
||||
let y2 = tmp;
|
||||
}
|
||||
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
|
||||
do Sys.error(8);
|
||||
}
|
||||
let tmp = y2 - y1;
|
||||
while(a < tmp){
|
||||
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
|
||||
let a = a + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
|
||||
function void drawCircle(int x, int y, int r) {
|
||||
var int dy, dx, tmp;
|
||||
if(r > 181){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let dy = - r;
|
||||
while (dy < r){
|
||||
let tmp = Math.sqrt((r * r) - (dy * dy));
|
||||
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
|
||||
let dy = dy + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+154
@@ -0,0 +1,154 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/String.jack
|
||||
|
||||
/**
|
||||
* Represents character strings. In addition for constructing and disposing
|
||||
* strings, the class features methods for getting and setting individual
|
||||
* characters of the string, for erasing the string's last character,
|
||||
* for appending a character to the string's end, and more typical
|
||||
* string-oriented operations.
|
||||
*/
|
||||
class String {
|
||||
field Array str;
|
||||
field int length;
|
||||
field int strLength;
|
||||
|
||||
/** constructs a new empty string with a mavalimum length of mavalLength
|
||||
* and initial length of 0. */
|
||||
constructor String new(int mavalLength) {
|
||||
if (mavalLength > 0){
|
||||
let str = Array.new(mavalLength);
|
||||
}
|
||||
let strLength = mavalLength;
|
||||
let length = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this string. */
|
||||
method void dispose() {
|
||||
if(length > 0){
|
||||
do str.dispose();
|
||||
}
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the current length of this string. */
|
||||
method int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Returns the character at the j-th location of this string. */
|
||||
method char charAt(int j) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
return str[j];
|
||||
}
|
||||
|
||||
/** Sets the character at the j-th location of this string to c. */
|
||||
method void setCharAt(int j, char c) {
|
||||
if(j > length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[j] = c;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Appends c to this string's end and returns this string. */
|
||||
method String appendChar(char c) {
|
||||
if(strLength = length){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[length] = c;
|
||||
let length = length + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Erases the last character from this string. */
|
||||
method void eraseLastChar() {
|
||||
if (length = 0){
|
||||
do Sys.error(7);
|
||||
}
|
||||
let str[length] = 0;
|
||||
let length = length - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the integer value of this string,
|
||||
* until a non-digit character is detected. */
|
||||
method int intValue() {
|
||||
var int d, sum, i;
|
||||
var bool f;
|
||||
while(i < length){
|
||||
let d = str[i];
|
||||
if ((d > 47) & (d < 58)){
|
||||
let sum = (sum * 10) + (d - 48);
|
||||
}
|
||||
else{
|
||||
if((i = 0) & (d = 45)){
|
||||
let f = true;
|
||||
}
|
||||
else{
|
||||
let i = length;
|
||||
}
|
||||
}
|
||||
let i = i + 1;
|
||||
}
|
||||
if (f){
|
||||
return -sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/** Sets this string to hold a representation of the given value. */
|
||||
method void setInt(int val) {
|
||||
var Array c;
|
||||
var int d, b, a;
|
||||
let c = Array.new(6);
|
||||
if (val < 0){
|
||||
let d = ~0;
|
||||
let val = -val;
|
||||
}
|
||||
let b = val;
|
||||
while(b > 0){
|
||||
let b = val / 10;
|
||||
let c[a] = 48 + val - (b * 10);
|
||||
let a = a + 1;
|
||||
let val = b;
|
||||
}
|
||||
if (d){
|
||||
let c[a] = 45;
|
||||
let a = a + 1;
|
||||
}
|
||||
if (a = 0){
|
||||
let str[0] = 48;
|
||||
let length = 1;
|
||||
}
|
||||
else{
|
||||
let length = 0;
|
||||
while (length < a){
|
||||
let str[length] = c[a - 1 - length];
|
||||
let length = length + 1;
|
||||
}
|
||||
}
|
||||
do Array.dispose(c);
|
||||
return;
|
||||
}
|
||||
/** Returns the new line character. */
|
||||
function char newLine() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
/** Returns the backspace character. */
|
||||
function char backSpace() {
|
||||
return 129;
|
||||
}
|
||||
|
||||
/** Returns the double quote (") character. */
|
||||
function char doubleQuote() {
|
||||
return 34;
|
||||
}
|
||||
}
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/12/Sys.jack
|
||||
|
||||
/**
|
||||
* A library that supports various program execution services.
|
||||
*/
|
||||
class Sys {
|
||||
|
||||
/** Performs all the initializations required by the OS. */
|
||||
function void init() {
|
||||
do Memory.init();
|
||||
do Math.init();
|
||||
do Output.init();
|
||||
do Screen.init();
|
||||
do Keyboard.init();
|
||||
do Main.main();
|
||||
do Sys.halt();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Halts the program execution. */
|
||||
function void halt() {
|
||||
while(true){
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Waits approximately duration milliseconds and returns. */
|
||||
function void wait(int duration) {
|
||||
var int i;
|
||||
while (duration > 0){
|
||||
let i = 100;
|
||||
while(i > 0){
|
||||
let i = i -1;
|
||||
}
|
||||
let duration = duration - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Displays the given error code in the form "ERR<errorCode>",
|
||||
* and halts the program's execution. */
|
||||
function void error(int errorCode) {
|
||||
var String s;
|
||||
let s = String.new(3);
|
||||
do s.setInt(errorCode);
|
||||
do Output.printString("ERR");
|
||||
do Output.printString(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user