Nand2Tetris — 12장
Jack 운영체제
// Math.jack
// OS 구현 예시
// Jack의 모든 * 와 / 는 이 함수들로 컴파일되므로 음수와 0 나누기까지 처리해야 한다
// multiply는 shift-and-add, divide는 shift-and-subtract 로 구현함
class Math {
static Array twoToThe;
function void init() {
var int i, v;
let twoToThe = Array.new(16);
let i = 0;
let v = 1;
while (i < 16) {
let twoToThe[i] = v;
let v = v + v;
let i = i + 1;
}
return;
}
function int abs(int x) {
if (x < 0) { return -x; }
return x;
}
function boolean bit(int x, int i) {
return ~((x & twoToThe[i]) = 0);
}
function int multiply(int x, int y) {
var int sum, shifted, j;
var boolean negative;
let negative = false;
if (x < 0) { let x = -x; let negative = ~negative; }
if (y < 0) { let y = -y; let negative = ~negative; }
let sum = 0;
let shifted = x;
let j = 0;
while (j < 16) {
if (Math.bit(y, j)) { let sum = sum + shifted; }
let shifted = shifted + shifted; // 좌측 1비트 시프트
let j = j + 1;
}
if (negative) { return -sum; }
return sum;
}
// 절댓값 나눗셈. y를 두 배로 키우며 내려가 O(log n) 이다.
function int divideAbs(int x, int y) {
var int q;
if ((y > x) | (y < 0)) { return 0; } // y < 0 은 두 배 키우다 넘친 경우
let q = Math.divideAbs(x, y + y);
if ((x - ((q + q) * y)) < y) { return q + q; }
return (q + q) + 1;
}
function int divide(int x, int y) {
var int q;
var boolean negative;
if (y = 0) { do Sys.error(3); } // 0으로 나누기
let negative = false;
if (x < 0) { let x = -x; let negative = ~negative; }
if (y < 0) { let y = -y; let negative = ~negative; }
let q = Math.divideAbs(x, y);
if (negative) { return -q; }
return q;
}
}
// String.jack
// 문자열 객체 일부 구현
// 내부 배열에 문자를 저장하고 length를 따로 관리함
class String {
field Array data;
field int length;
field int capacity;
constructor String new(int maxLength) {
let capacity = maxLength;
let length = 0;
let data = Array.new(maxLength);
return this;
}
method void dispose() {
do data.dispose();
do Memory.deAlloc(this);
return;
}
method int length() {
return length;
}
method String appendChar(char c) {
let data[length] = c;
let length = length + 1;
return this;
}
method char charAt(int index) {
return data[index];
}
}
// Array.jack
// Array.new는 Heap에서 size만큼 메모리를 할당함
// Jack 배열은 사실상 base address를 가진 메모리 블록임
class Array {
function Array new(int size) {
return Memory.alloc(size);
}
method void dispose() {
do Memory.deAlloc(this);
return;
}
}