Skip to content

Commit

Permalink
made code more functional
Browse files Browse the repository at this point in the history
  • Loading branch information
Evoniuk committed Jun 12, 2020
1 parent bea07de commit 54808ae
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 79 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Hack-Assembler
# Hack Assembler
This is an assembler from the Hack assembly language into the Hack machine language. [Try for yourself here](https://evoniuk.github.io/Hack-Assembler/).

## The Hack Language
Hack is a language developed for the conceptual Hack computer, built as a part of [the Nand To Tetris course](https://www.nand2tetris.org). Hack is a 16 bit computer.
10 changes: 4 additions & 6 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ document.getElementById('inputCode').addEventListener('click', function() {

function displayCode (code) {
const outputOriginal = document.getElementById('outputOriginal');
outputOriginal.textContent = '';

const outputArea = document.getElementById('output');
outputOriginal.textContent = '';
outputArea.textContent = '';

const processedCode = process(code);
Expand All @@ -29,8 +28,7 @@ function displayCode (code) {
}

function process(code) {
code = parse(code);
code = handleSymbols(code);
originalCode = code.map(line => line);
return [originalCode, assemble(code)];
const parsedCode = parse(code);
const unSymbolized = handleSymbols(parsedCode);
return [unSymbolized, assemble(unSymbolized)];
}
77 changes: 35 additions & 42 deletions src/assemble.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
function assemble(code) {
for (let i = 0; i < code.length; i++) {
if (code[i][0] === '@')
code[i] = assembleAinstruction(code[i]);
else code[i] = assembleCinstruction(code[i]);
}

return code;
return code.map(line => line[0] === '@' ?
assembleAinstruction(line):
assembleCinstruction(line));
}

function assembleAinstruction(line) {
let num = line.substring(1);
num = parseInt(num, 10).toString(2);

let result = '0';
for (let i = 0; i < 15 - num.length; i++)
result += '0';
const num = line.substring(1);
const binaryNum = parseInt(num, 10).toString(2);
const leadingZeros = '0'.repeat(16 - binaryNum.length);

return result + num;
return leadingZeros + binaryNum;
}

function assembleCinstruction(line) {
Expand All @@ -30,8 +23,8 @@ function assembleCinstruction(line) {

function parseCinstruction(line) {
// splits into [dest, comp, jmp]
let splitLine = line.split(/[=;]+/);
if (!line.includes('=')) splitLine = [''].concat(splitLine);
const splitLine = line.split(/[=;]+/);
if (!line.includes('=')) splitLine.unshift('')
if (!line.includes(';')) splitLine.push('');

return splitLine;
Expand All @@ -47,37 +40,37 @@ function getDestCode(dest) {
function getCompCode(comp) {
const aBit = comp.includes('M') ? '1' : '0';

comp = comp.replace(/A|M/, 'X');
const compare = comp.replace(/A|M/, 'X');
const cBits =
comp === '0' ? '101010':
comp === '1' ? '111111':
comp === '-1' ? '111010':
comp === 'D' ? '001100':
comp === 'X' ? '110000':
comp === '!D' ? '001101':
comp === '!X' ? '110001':
comp === '-D' ? '001111':
comp === '-X' ? '110011':
comp === 'D+1' ? '011111':
comp === 'X+1' ? '110111':
comp === 'D-1' ? '001110':
comp === 'X-1' ? '110010':
comp === 'D+X' ? '000010':
comp === 'D-X' ? '010011':
comp === 'X-D' ? '000111':
comp === 'D&X' ? '000000':
'010101';
compare === '0' ? '101010':
compare === '1' ? '111111':
compare === '-1' ? '111010':
compare === 'D' ? '001100':
compare === 'X' ? '110000':
compare === '!D' ? '001101':
compare === '!X' ? '110001':
compare === '-D' ? '001111':
compare === '-X' ? '110011':
compare === 'D+1' ? '011111':
compare === 'X+1' ? '110111':
compare === 'D-1' ? '001110':
compare === 'X-1' ? '110010':
compare === 'D+X' ? '000010':
compare === 'D-X' ? '010011':
compare === 'X-D' ? '000111':
compare === 'D&X' ? '000000':
'010101';

return aBit + cBits;
}

function getJumpCode(jump) {
return jump === '' ? '000':
jump === 'JGT' ? '001':
jump === 'JEQ' ? '010':
jump === 'JGE' ? '011':
jump === 'JLT' ? '100':
jump === 'JNE' ? '101':
jump === 'JLE' ? '110':
'111';
jump === 'JGT' ? '001':
jump === 'JEQ' ? '010':
jump === 'JGE' ? '011':
jump === 'JLT' ? '100':
jump === 'JNE' ? '101':
jump === 'JLE' ? '110':
'111';
}
28 changes: 11 additions & 17 deletions src/handleSymbols.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ function handleSymbols(code) {
THAT: 4,
};

code = handleLabels(code, symbolTable);
code = handleVariables(code, symbolTable);
enterLabelsIntoSymbolTable(code, symbolTable);
enterVarsIntoSymbolTable(code, symbolTable);

return code;
const noLabels = code.filter(line => line[0] !== '(');
return replaceVars(noLabels, symbolTable);
}

function handleLabels(code, symbolTable) {
// enter value of labels into symbol table
function enterLabelsIntoSymbolTable(code, symbolTable) {
let numberOfLabelsSeen = 0;
for (let i = 0; i < code.length; i++) {
if (code[i][0] === '(') {
Expand All @@ -41,25 +41,19 @@ function handleLabels(code, symbolTable) {
numberOfLabelsSeen++;
}
}

// remove labels from code
return code.filter(line => line[0] !== '(');
}

function handleVariables(code, symbolTable) {
// enter variables into symbol table
function enterVarsIntoSymbolTable(code, symbolTable) {
let variableIndex = 16;
for (let i = 0; i < code.length; i++)
if (lineIsNewVariable(code[i], symbolTable))
symbolTable[code[i].substring(1)] = variableIndex++;
}

// enter value of variables and labels where they occur
for (let i = 0; i < code.length; i++) {
if (code[i][0] === '@' && code[i].substring(1) in symbolTable)
code[i] = '@' + symbolTable[code[i].substring(1)];
}

return code;
function replaceVars(code, symbolTable) {
return code.map(line => line[0] === '@' && line.substring(1) in symbolTable ?
'@' + symbolTable[line.substring(1)]:
line)
}

function lineIsNewVariable(line, symbolTable) {
Expand Down
19 changes: 6 additions & 13 deletions src/parser.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
function parse(code) {
code = code.split(/\r?\n/); // splits each line
return code.map(stripWhitespace).filter(line => line !== '');
lines = code.split(/\r?\n/); // splits each line
return lines.map(stripWhitespace).filter(line => line !== '');
}

function stripWhitespace(line) {
if (line[0] === '/') return ''; // remove line comments
line = line.replace(/\s/g,''); // remove spaces

// remove inline comments
let result = '';
for (let i = 0; i < line.length; i++) {
if (line[i] === '/') break;
result += line[i];
}

return result;
noSpaces = line.replace(/\s/g,''); // remove spaces
return noSpaces.includes('/') ?
noSpaces.substring(0, noSpaces.indexOf('/')):
noSpaces;
}

0 comments on commit 54808ae

Please sign in to comment.