16 Commits
v1.0 ... v1.1

Author SHA1 Message Date
avinal
291b239065 headers updated 2020-08-21 19:08:23 +05:30
avinal
4332eae357 minor update 2020-08-21 19:08:04 +05:30
avinal
68748fed47 makefile updated 2020-08-21 19:07:43 +05:30
avinal
25304b4662 source files added 2020-08-21 18:52:02 +05:30
avinal
4ef8187412 redundant files removed 2020-08-21 18:51:41 +05:30
avinal
b4b19da495 headers added 2020-08-21 18:51:18 +05:30
avinal
30921da66c folder reorganised 2020-08-21 18:50:50 +05:30
avinal
d3e3f8f701 folder reorganisation 2020-08-21 18:50:08 +05:30
avinal
5a864e1a78 example files added 2020-08-21 18:49:30 +05:30
avinal
4f577ea7c6 trim command updated 2020-08-21 17:56:06 +05:30
avinal
5444102bef experimental flag added 2020-08-21 17:55:35 +05:30
avinal
7d85cebda1 added filesystem 2020-08-21 17:55:16 +05:30
avinal
236fe8e556 modified for part 2 2020-08-21 17:55:01 +05:30
avinal
274bbde1c4 added newer definations for part 2 2020-08-21 17:54:38 +05:30
avinal
c59bd2122c made slight changes 2020-08-21 17:54:14 +05:30
avinal
1a8a9d38ac gitignore updated 2020-08-21 12:48:43 +05:30
18 changed files with 819 additions and 578 deletions

7
.gitignore vendored
View File

@@ -35,4 +35,9 @@ VMTranslator
*.asm
.vscode
*.zip
FibonacciElement
NestedCall
SimpleFunction
StaticsTest
*.vm
*.zip

View File

@@ -1,31 +0,0 @@
// 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/07/MemoryAccess/BasicTest/BasicTest.vm
// Executes pop and push commands using the virtual memory segments.
push constant 10
pop local 0
push constant 21
push constant 22
pop argument 2
pop argument 1
push constant 36
pop this 6
push constant 42
push constant 45
pop that 5
pop that 2
push constant 510
pop temp 6
push local 0
push that 5
add
push argument 1
sub
push this 6
push this 6
add
sub
push temp 6
add

View File

@@ -1,9 +0,0 @@
#include "code_writer.hpp"
#include <iostream>
int main(int argc, char const *argv[])
{
code_writer toassembly(argv[1]);
toassembly.write_assembly();
return 0;
}

View File

@@ -1,29 +1,25 @@
CXX = g++
STDVERSION = -std=c++17
STDVERSION = -std=c++17 -lstdc++fs
WARNINGS = -pedantic -Wall -Wfatal-errors -Wextra -Wno-unused-parameter -Wno-unused-variable
TARGET = VMTranslator
OBJ_DIR = build
OBJECTS = code_writer.o parser.o vutility.o
TEST_OBJS = parser_test.o
all:$(TARGET)
$(TARGET): $(OBJECTS)
$(CXX) $(WARNINGS) $(STDVERSION) -o $(TARGET) Main.cpp $(OBJECTS)
$(CXX) $(WARNINGS) -o $(TARGET) src/Main.cpp $(OBJECTS) $(STDVERSION)
vutility.o: vutility.cpp vutility.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c vutility.cpp -o vutility.o
vutility.o: src/vutility.cpp include/vutility.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/vutility.cpp -o vutility.o
parser.o: parser.cpp parser.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c parser.cpp -o parser.o
parser.o: src/parser.cpp include/parser.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/parser.cpp -o parser.o
code_writer.o:code_writer.cpp code_writer.hpp
$(CXX) $(STDVERSION) -c code_writer.cpp -o code_writer.o
code_writer.o: src/code_writer.cpp include/code_writer.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/code_writer.cpp -o code_writer.o
test:
$(CXX) $(STDVERSION) tests/*.cpp tests/catch/catch_main.cpp parser.cpp code_writer.cpp -o test
clean:
rm -rf *.o $(TARGET) *.asm

View File

@@ -1,22 +0,0 @@
// 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/07/MemoryAccess/PointerTest/PointerTest.vm
// Executes pop and push commands using the
// pointer, this, and that segments.
push constant 3030
pop pointer 0
push constant 3040
pop pointer 1
push constant 32
pop this 2
push constant 46
pop that 6
push pointer 0
push pointer 1
add
push this 2
sub
push that 6
add

View File

@@ -1,9 +0,0 @@
// 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/07/StackArithmetic/SimpleAdd/SimpleAdd.vm
// Pushes and adds two constants.
push constant 7
push constant 8
add

View File

@@ -1,45 +0,0 @@
// 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/07/StackArithmetic/StackTest/StackTest.vm
// Executes a sequence of arithmetic and logical operations
// on the stack.
push constant 17
push constant 17
eq
push constant 17
push constant 16
eq
push constant 16
push constant 17
eq
push constant 892
push constant 891
lt
push constant 891
push constant 892
lt
push constant 891
push constant 891
lt
push constant 32767
push constant 32766
gt
push constant 32766
push constant 32767
gt
push constant 32766
push constant 32766
gt
push constant 57
push constant 31
push constant 53
add
push constant 112
sub
neg
and
push constant 82
or
not

View File

@@ -1,17 +0,0 @@
// 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/07/MemoryAccess/StaticTest/StaticTest.vm
// Executes pop and push commands using the static segment.
push constant 111
push constant 333
push constant 888
pop static 8
pop static 3
pop static 1
push static 3
push static 1
sub
push static 8
add

View File

@@ -1,390 +0,0 @@
#include "code_writer.hpp"
code_writer::code_writer(std::string name)
{
file_name = name;
name.erase(name.find('.'));
name.append(".asm");
outfile.open(name);
}
void code_writer::write_assembly()
{
parser toparse(file_name);
toparse.parse();
commands = toparse.get_commands();
std::unordered_map<c_type,
std::function<void(std::string, int, bool)>>
write_map({{C_ARITHMETIC,
[this](std::string arg1, int arg2, bool arg3) {
this->write_arithmetic(arg1, arg2, arg3);
}},
{C_PUSH,
[this](std::string arg1, int arg2, bool arg3) {
this->write_push(arg1, arg2, arg3);
}},
{C_POP,
[this](std::string arg1, int arg2, bool arg3) {
this->write_pop(arg1, arg2, arg3);
}}});
for (auto curr : commands)
{
c_type write_type;
std::string instruction;
int index;
std::tie(write_type, instruction, index) = curr;
if (outfile.is_open())
{
write_map[write_type](instruction, index, this->dbg);
}
}
outfile.close();
}
void code_writer::write_push(std::string segment, int index, bool debug)
{
std::string toname = file_name;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug)
{
outfile << "// push " << segment << " " << index << std::endl;
}
if (segment == "constant")
{
outfile << "@" << index << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "static")
{
outfile << "@" << toname << "." << index << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "temp")
{
outfile << "@" << index + 5 << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "A=D" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 10;
}
}
void code_writer::write_pop(std::string segment, int index, bool debug)
{
std::string toname = file_name;
toname = toname.substr(toname.find_last_of('/')+1);
toname = toname.erase(toname.find('.'));
if (debug && segment != "constant")
{
outfile << "// pop " << segment << " " << index << std::endl;
}
if (segment == "static")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << toname << "." << index << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << which << std::endl
<< "M=D" << std::endl;
this->ins_no += 4;
}
else if (segment == "temp")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << index + 5 << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "@R13" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@R13" << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 12;
}
}
void code_writer::write_arithmetic(std::string comm, int index, bool debug)
{
std::unordered_map<std::string,
std::function<void(bool)>>
arith_mapic({
{"add",
[this](bool arg1) { this->write_add(arg1); }},
{"sub",
[this](bool arg1) { this->write_sub(arg1); }},
{"neg",
[this](bool arg1) { this->write_neg(arg1); }},
{"and",
[this](bool arg1) { this->write_and(arg1); }},
{"or",
[this](bool arg1) { this->write_or(arg1); }},
{"not",
[this](bool arg1) { this->write_not(arg1); }},
{"gt",
[this](bool arg1) { this->write_gt(arg1); }},
{"lt",
[this](bool arg1) { this->write_lt(arg1); }},
{"eq",
[this](bool arg1) { this->write_eq(arg1); }},
});
arith_mapic[comm](debug);
}
void code_writer::write_add(bool debug)
{
if (debug)
{
outfile << "// add" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D+M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_sub(bool debug)
{
if (debug)
{
outfile << "// sub" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=M-D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_neg(bool debug)
{
if (debug)
{
outfile << "// neg" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=-M" << std::endl;
this->ins_no += 3;
}
void code_writer::write_eq(bool debug)
{
if (debug)
{
outfile << "// eq" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JEQ" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_lt(bool debug)
{
if (debug)
{
outfile << "// lt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JLT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_gt(bool debug)
{
if (debug)
{
outfile << "// gt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JGT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_and(bool debug)
{
if (debug)
{
outfile << "// and" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D&M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_or(bool debug)
{
if (debug)
{
outfile << "// or" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D|M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_not(bool debug)
{
if (debug)
{
outfile << "// not" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=!M" << std::endl;
this->ins_no += 3;
}

View File

@@ -1,28 +0,0 @@
#include "parser.hpp"
#include <functional>
class code_writer
{
private:
std::string file_name;
std::vector<vmcommand> commands;
std::ofstream outfile;
int ins_no = -1;
bool dbg = false;
public:
code_writer(std::string name);
void write_assembly();
void write_push(std::string segment, int index, bool debug);
void write_pop(std::string segment, int index, bool debug);
void write_arithmetic(std::string comm, int index, bool debug);
void write_add(bool debug);
void write_sub(bool debug);
void write_neg(bool debug);
void write_and(bool debug);
void write_or(bool debug);
void write_not(bool debug);
void write_eq(bool debug);
void write_lt(bool debug);
void write_gt(bool debug);
};

64
include/code_writer.hpp Normal file
View File

@@ -0,0 +1,64 @@
#include "parser.hpp"
#include <functional>
#include <string>
typedef std::vector<std::string> lots_of_files;
const std::unordered_map<std::string, std::string> operation_map({{"add", "M+D"},
{"sub", "M-D"},
{"neg", "-M"},
{"and", "D&M"},
{"or", "D|M"},
{"not", "!M"},
{"eq", "JEQ"},
{"lt", "JLT"},
{"gt", "LGT"}});
class code_writer
{
private:
lots_of_files files;
std::vector<vmcommand> commands;
std::ofstream outfile;
std::string current_file = "";
std::string current_function = "";
int ins_no = -1;
bool dbg = true;
bool is_dir = false;
public:
code_writer(lots_of_files name);
void write_assembly();
void write_push(std::string segment, int index, bool debug);
void write_push(std::string segment, bool debug);
void write_pop(std::string segment, int index, bool debug);
void write_pop(std::string segment, bool debug);
void write_arithmetic(std::string comm, int index, bool debug);
void write_add_sub_and_or(std::string op, bool debug);
void write_neg_not(std::string op, bool debug);
void write_eq_lt_gt(std::string op, bool debug);
/*
void write_add(bool debug);
void write_sub(bool debug);
void write_neg(bool debug);
void write_and(bool debug);
void write_or(bool debug);
void write_not(bool debug);
void write_eq(bool debug);
void write_lt(bool debug);
void write_gt(bool debug);
*/
void write_init(bool debug);
void write_label(std::string label, int index, bool debug);
void write_goto(std::string label, int index, bool debug);
void write_if(std::string label, int index, bool debug);
void write_call(std::string fun_name, int args, bool debug);
void write_return(bool debug);
void write_function(std::string fun_name, int locals, bool debug);
void write_frame_restore(std::string segment, int minus, bool debug);
};

View File

@@ -27,7 +27,7 @@ private:
std::vector<vmcommand> parsed;
public:
parser(std::string file) : input_file(file) {}
bool change_file(std::string name);
std::vector<vmcommand> get_commands();
c_type command_type(std::string com);
void parse();

View File

@@ -1,7 +1,7 @@
#include <vector>
#include <string>
#include<sstream>
#include <sstream>
class vutility
{
private:

View File

@@ -1,2 +0,0 @@
c++
debug

37
src/Main.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "../include/code_writer.hpp"
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main(int argc, char const *argv[])
{
lots_of_files files;
std::string input(argv[1]);
if (fs::is_directory(input))
{
files.push_back(input);
for (auto &entry : fs::directory_iterator(input))
{
if (entry.path().extension() == ".vm")
{
std::string vmfile = entry.path().string();
if (entry.path().filename() == "Sys.vm")
{
files.insert(files.begin() + 1, vmfile);
}
else
{
files.push_back(vmfile);
}
}
}
}
else
{
files.push_back(input);
}
code_writer toassembly(files);
toassembly.write_assembly();
return 0;
}

679
src/code_writer.cpp Normal file
View File

@@ -0,0 +1,679 @@
#include "../include/code_writer.hpp"
code_writer::code_writer(lots_of_files names)
{
this->files = names;
std::string outfile_name;
outfile_name = files.front();
if (files.size() > 1)
{
files.erase(files.begin());
std::string check = files.front();
if (check.substr(check.length() - 6) == "Sys.vm")
{
this->is_dir = true;
}
outfile_name = outfile_name + "/" + outfile_name;
}
else
{
outfile_name.erase(outfile_name.find('.'));
}
outfile_name.append(".asm");
outfile.open(outfile_name);
}
void code_writer::write_assembly()
{
std::unordered_map<c_type,
std::function<void(std::string, int, bool)>>
write_map({{C_ARITHMETIC,
[this](std::string arg1, int arg2, bool arg3) {
this->write_arithmetic(arg1, arg2, arg3);
}},
{C_PUSH,
[this](std::string arg1, int arg2, bool arg3) {
this->write_push(arg1, arg2, arg3);
}},
{C_POP,
[this](std::string arg1, int arg2, bool arg3) {
this->write_pop(arg1, arg2, arg3);
}},
{C_LABEL,
[this](std::string arg1, int arg2, bool arg3) {
this->write_label(arg1, arg2, arg3);
}},
{C_FUNCTION,
[this](std::string arg1, int arg2, bool arg3) {
this->write_function(arg1, arg2, arg3);
}},
{C_RETURN,
[this](std::string arg1, int arg2, bool arg3) {
this->write_return(arg3);
}},
{C_GOTO,
[this](std::string arg1, int arg2, bool arg3) {
this->write_goto(arg1, arg2, arg3);
}},
{C_IF,
[this](std::string arg1, int arg2, bool arg3) {
this->write_if(arg1, arg2, arg3);
}},
{C_CALL,
[this](std::string arg1, int arg2, bool arg3) {
this->write_call(arg1, arg2, arg3);
}}});
parser lets_parse;
this->write_init(this->dbg);
for (auto curr_file : this->files)
{
lets_parse.change_file(curr_file);
lets_parse.parse();
this->commands = lets_parse.get_commands();
this->current_file = curr_file;
for (auto curr : commands)
{
c_type write_type;
std::string instruction;
int index;
std::tie(write_type, instruction, index) = curr;
if (outfile.is_open())
{
write_map[write_type](instruction, index, this->dbg);
}
}
this->commands.clear();
}
outfile.close();
}
void code_writer::write_push(std::string segment, int index, bool debug)
{
std::string toname = this->current_file;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug)
{
outfile << "// push " << segment << " " << index << " " << this->ins_no << std::endl;
}
if (segment == "constant")
{
outfile << "@" << index << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "static")
{
outfile << "@" << toname << "." << index << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "temp")
{
outfile << "@" << index + 5 << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "A=D" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 10;
}
}
void code_writer::write_push(std::string segment, bool debug)
{
if (debug)
{
outfile << "// push " << segment << " " << this->ins_no << std::endl;
}
outfile << "@" << segment << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_pop(std::string segment, int index, bool debug)
{
std::string toname = this->current_file;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug && segment != "constant")
{
outfile << "// pop " << segment << " " << index << " " << this->ins_no << std::endl;
}
if (segment == "static")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << toname << "." << index << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << which << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "temp")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << index + 5 << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "@R13" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@R13" << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 12;
}
}
void code_writer::write_pop(std::string segment, bool debug)
{
if (debug)
{
outfile << "// pop " << segment << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << segment << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_arithmetic(std::string comm, int index, bool debug)
{
std::unordered_map<std::string,
std::function<void(std::string, bool)>>
arith_mapic({
{"add",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"sub",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"and",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"or",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"neg",
[this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }},
{"not",
[this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }},
{"gt",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
{"lt",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
{"eq",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
});
arith_mapic[comm](comm, debug);
}
void code_writer::write_add_sub_and_or(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=" << operation_map.at(op) << std::endl;
this->ins_no += 6;
}
void code_writer::write_neg_not(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=" << operation_map.at(op) << std::endl;
this->ins_no += 3;
}
void code_writer::write_eq_lt_gt(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;" << operation_map.at(op) << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
/*
void code_writer::write_add(bool debug)
{
if (debug)
{
outfile << "// add" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D+M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_sub(bool debug)
{
if (debug)
{
outfile << "// sub" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=M-D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_neg(bool debug)
{
if (debug)
{
outfile << "// neg" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=-M" << std::endl;
this->ins_no += 3;
}
void code_writer::write_and(bool debug)
{
if (debug)
{
outfile << "// and" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D&M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_or(bool debug)
{
if (debug)
{
outfile << "// or" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D|M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_not(bool debug)
{
if (debug)
{
outfile << "// not" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=!M" << std::endl;
this->ins_no += 3;
}
void code_writer::write_eq(bool debug)
{
if (debug)
{
outfile << "// eq" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JEQ" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_lt(bool debug)
{
if (debug)
{
outfile << "// lt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JLT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_gt(bool debug)
{
if (debug)
{
outfile << "// gt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JGT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
*/
void code_writer::write_init(bool debug)
{
if (debug)
{
outfile << "// bootstrap code"
<< " " << this->ins_no << std::endl;
}
outfile << "@256" << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "M=D" << std::endl;
this->ins_no += 4;
if (this->is_dir)
{
outfile << "// Sys.init defined adding function call..."
<< " " << this->ins_no << std::endl;
this->write_call("Sys.init", 0, debug);
}
}
void code_writer::write_call(std::string fun_name, int args, bool debug)
{
if (debug)
{
outfile << "// call" << fun_name << " " << args << " " << this->ins_no << std::endl;
}
std::string curr_ins = std::to_string(this->ins_no);
std::string ret_label("ret." + fun_name + "$" + curr_ins);
outfile << "@" << ret_label << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
this->write_push("LCL", debug);
this->write_push("ARG", debug);
this->write_push("THIS", debug);
this->write_push("THAT", debug);
outfile << "@SP" << std::endl
<< "D=M" << std::endl
<< "@5" << std::endl
<< "D=D-A" << std::endl
<< "@" << args << std::endl
<< "D=D-A" << std::endl
<< "@ARG" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "D=M" << std::endl
<< "@LCL" << std::endl
<< "M=D" << std::endl
<< "@" << fun_name << std::endl
<< "0;JMP" << std::endl
<< "(" << ret_label << ")" << std::endl;
this->ins_no += 14;
}
void code_writer::write_label(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// label " << label << " " << this->ins_no << std::endl;
}
outfile << "(" << current_function << "$" << label << ")" << std::endl;
}
void code_writer::write_goto(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// goto " << label << " " << this->ins_no << std::endl;
}
outfile << "@" << current_function << "$" << label << std::endl
<< "0;JMP" << std::endl;
this->ins_no += 2;
}
void code_writer::write_function(std::string fun_name, int locals, bool debug)
{
if (debug)
{
outfile << "// function " << fun_name << " " << locals << " " << this->ins_no << std::endl;
}
current_function = fun_name;
outfile << "(" << fun_name << ")" << std::endl;
for (int l = 0; l < locals; l++)
{
this->write_push("constant", 0, debug);
}
}
void code_writer::write_return(bool debug)
{
if (debug)
{
outfile << "// return " << current_function << " " << this->ins_no << std::endl;
}
outfile << "@LCL" << std::endl
<< "D=M" << std::endl
<< "@R7" << std::endl
<< "M=D" << std::endl
<< "@5" << std::endl
<< "A=D-A" << std::endl
<< "D=M" << std::endl
<< "@R14" << std::endl
<< "M=D" << std::endl;
this->ins_no += 9;
this->write_pop("ARG", debug);
outfile << "@ARG" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "M=D+1" << std::endl;
this->ins_no += 4;
this->write_frame_restore("THAT", 1, debug);
this->write_frame_restore("THIS", 2, debug);
this->write_frame_restore("ARG", 3, debug);
this->write_frame_restore("LCL", 4, debug);
outfile << "@R14" << std::endl
<< "A=M" << std ::endl
<< "0;JMP" << std::endl;
this->ins_no += 3;
}
void code_writer::write_frame_restore(std::string segment, int minus, bool debug)
{
if (debug)
{
outfile << "// restoring " << segment << " " << this->ins_no << std::endl;
}
outfile << "@R7" << std::endl
<< "D=M" << std::endl
<< "@" << minus << std::endl
<< "A=D-A" << std::endl
<< "D=M" << std::endl
<< "@" << segment << std::endl
<< "M=D" << std::endl;
this->ins_no += 7;
}
void code_writer::write_if(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// if " << label << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << current_function << "$" << label << std::endl
<< "D;JNE" << std::endl;
this->ins_no += 5;
}

View File

@@ -1,4 +1,4 @@
#include "parser.hpp"
#include "../include/parser.hpp"
c_type parser::command_type(std::string com)
{
@@ -76,3 +76,18 @@ std::vector<vmcommand> parser::get_commands()
{
return this->parsed;
}
bool parser::change_file(std::string name)
{
this->parsed.clear();
this->input_file = name;
if (this->parsed.size() == 0 && input_file == name)
{
return true;
}
else
{
return false;
}
}

View File

@@ -1,4 +1,4 @@
#include "vutility.hpp"
#include "../include/vutility.hpp"
std::vector<std::string> vutility::split(std::string str, char delimit)
{
@@ -14,14 +14,12 @@ std::vector<std::string> vutility::split(std::string str, char delimit)
std::string vutility::trim(std::string str)
{
if (str.substr(0, 2) == "//")
if (str.find('/') != std::string::npos) // comments
{
str.erase();
}
else
{
str.erase(0, str.find_first_not_of(" \r\t\v\n")); //prefixing
str.erase(str.find_last_not_of(" \r\t\v\n") + 1); //surfixing}
str.erase(str.find('/'));
}
str.erase(0, str.find_first_not_of(" \r\t\v\n")); //prefixing
str.erase(str.find_last_not_of(" \r\t\v\n") + 1); //surfixing}
return str;
}