239 lines
6.7 KiB
Hare
239 lines
6.7 KiB
Hare
// ilo.ha, an ilo in hare
|
|
|
|
use bufio;
|
|
use fmt;
|
|
use fs;
|
|
use io;
|
|
use math;
|
|
use os;
|
|
|
|
let ds: [33]i32 = [0...];
|
|
let rs: [257]i32 = [0...];
|
|
let m: [65536]i32 = [0...];
|
|
let sp: i32 = 0;
|
|
let rp: i32 = 0;
|
|
let ip: i32 = 0;
|
|
let a: i32 = 0;
|
|
let b: i32 = 0;
|
|
let c: i32 = 0;
|
|
|
|
fn initialize() void = {
|
|
sp = 0;
|
|
rp = 0;
|
|
ip = 0;
|
|
load();
|
|
};
|
|
|
|
fn load() void = {
|
|
const input = match (os::open("ilo.rom")) {
|
|
case let file: io::file =>
|
|
yield file;
|
|
case let err: fs::error =>
|
|
fmt::fatalf("Error opening {}: {}",
|
|
os::args[1], fs::strerror(err));
|
|
};
|
|
defer io::close(input)!;
|
|
let rdbuf: [os::BUFSZ]u8 = [0...];
|
|
let input = &bufio::init(input, rdbuf, []);
|
|
let i = 0;
|
|
let buf: [4]u8 = [0, 0, 0, 0];
|
|
for (!(io::read(input, buf)! is io::EOF)) {
|
|
let x: u32 = m[i]:u32;
|
|
x = x + (buf[3]:u32 << 24);
|
|
x = x + (buf[2]:u32 << 16);
|
|
x = x + (buf[1]:u32 << 8);
|
|
x = x + (buf[0]:u32 << 0);
|
|
m[i] = x:i32;
|
|
i = i + 1;
|
|
};
|
|
};
|
|
|
|
fn read_block(block:i32, buffer:i32) void = {
|
|
const block_store = match (os::open("ilo.blocks")) {
|
|
case let file: io::file =>
|
|
yield file;
|
|
case let err: fs::error =>
|
|
fmt::fatalf("Error opening {}: {}",
|
|
"ilo.blocks", fs::strerror(err));
|
|
};
|
|
defer io::close(block_store)!;
|
|
|
|
let rdbuf: [os::BUFSZ]u8 = [0...];
|
|
let block_store = &bufio::init(block_store, rdbuf, []);
|
|
|
|
let i: i32 = 0;
|
|
let buf: [4096]u8 = [0...];
|
|
|
|
// this is not an optimal way, need to figure out
|
|
// io::seek
|
|
// io::seek(block_store, block * 4096, io::whence::SET)!;
|
|
let za:i32 = 0;
|
|
for (za < block) {
|
|
io::read(block_store, buf)!;
|
|
za = za + 1;
|
|
};
|
|
|
|
let cell: [4]u8 = [0...];
|
|
|
|
// read in the block
|
|
for (i < 1024) {
|
|
io::read(block_store, cell)!;
|
|
let x: u32 = 0;
|
|
x = x + (cell[3]:u32 << 24);
|
|
x = x + (cell[2]:u32 << 16);
|
|
x = x + (cell[1]:u32 << 8);
|
|
x = x + (cell[0]:u32 << 0);
|
|
let t:i32 = buffer + i;
|
|
m[t] = x:i32;
|
|
i = i + 1;
|
|
};
|
|
};
|
|
|
|
fn write_block(block:i32, buffer:i32) void = {
|
|
const block_store = match (os::open("ilo.blocks", fs::flag::RDWR)) {
|
|
case let file: io::file =>
|
|
yield file;
|
|
case let err: fs::error =>
|
|
fmt::fatalf("Error opening {}: {}",
|
|
"ilo.blocks", fs::strerror(err));
|
|
};
|
|
defer io::close(block_store)!;
|
|
|
|
let rdbuf: [os::BUFSZ]u8 = [0...];
|
|
let wrbuf: [os::BUFSZ]u8 = [0...];
|
|
let block_store = &bufio::init(block_store, rdbuf, wrbuf);
|
|
|
|
let i: i32 = 0;
|
|
let buf: [4096]u8 = [0...];
|
|
|
|
let za:i32 = 0;
|
|
for (za < block) {
|
|
io::read(block_store, buf)!;
|
|
za = za + 1;
|
|
};
|
|
|
|
let cell: [4]u8 = [0...];
|
|
|
|
// read in the block
|
|
for (i < 1024) {
|
|
let t:i32 = buffer + i;
|
|
let x: u32 = m[t]:u32;
|
|
cell[3] = ((x >> 24) & 0xFF):u8;
|
|
cell[2] = ((x >> 16) & 0xFF):u8;
|
|
cell[1] = ((x >> 8) & 0xFF):u8;
|
|
cell[0] = ((x >> 0) & 0xFF):u8;
|
|
io::write(block_store, cell)!;
|
|
i = i + 1;
|
|
};
|
|
io::close(block_store)!;
|
|
};
|
|
|
|
fn push(v: i32) void = { sp = sp + 1; ds[sp] = v; };
|
|
fn pop() i32 = { sp = sp - 1; return ds[sp + 1]; };
|
|
fn save_ip() void = { rp = rp + 1; rs[rp] = ip; };
|
|
|
|
fn no() void = { return; };
|
|
fn li() void = { ip = ip + 1; push(m[ip]); };
|
|
fn du() void = { push(ds[sp]); };
|
|
fn dr() void = { pop(); };
|
|
fn sw() void = { a = pop(); b = pop(); push(a); push(b); };
|
|
fn pu() void = { rp = rp + 1; rs[rp] = pop(); };
|
|
fn po() void = { push(rs[rp]); rp = rp - 1; };
|
|
fn ju() void = { ip = pop() - 1; };
|
|
fn ca() void = { save_ip(); ip = pop() - 1; };
|
|
fn cc() void = { a = pop(); if (pop() != 0) { save_ip(); ip = a - 1; }; };
|
|
fn cj() void = { a = pop(); if (pop() != 0) { ip = a - 1; }; };
|
|
fn re() void = { ip = rs[rp]; rp = rp - 1; };
|
|
fn eq() void = { a = pop(); b = pop();
|
|
if (a == b) { push(-1); } else { push(0); }; };
|
|
fn ne() void = { a = pop(); b = pop();
|
|
if (a != b) { push(-1); } else { push(0); }; };
|
|
fn lt() void = { a = pop(); b = pop();
|
|
if (b < a) { push(-1); } else { push(0); }; };
|
|
fn gt() void = { a = pop(); b = pop();
|
|
if (b > a) { push(-1); } else { push(0); }; };
|
|
fn fe() void = { ds[sp] = m[ds[sp]]; };
|
|
fn st() void = { m[ds[sp]] = ds[sp - 1]; sp = sp - 2; };
|
|
fn ad() void = { ds[sp - 1] = ds[sp - 1] + ds[sp]; pop(); };
|
|
fn su() void = { ds[sp - 1] = ds[sp - 1] - ds[sp]; pop(); };
|
|
fn mu() void = { ds[sp - 1] = ds[sp - 1] * ds[sp]; pop(); };
|
|
fn di() void = { a = ds[sp]; b = ds[sp - 1];
|
|
ds[sp] = b / a; ds[sp - 1] = b % a; };
|
|
fn an() void = { ds[sp - 1] = ds[sp - 1] & ds[sp]; pop(); };
|
|
fn or() void = { ds[sp - 1] = ds[sp - 1] | ds[sp]; pop(); };
|
|
fn xo() void = { ds[sp - 1] = ds[sp - 1] ^ ds[sp]; pop(); };
|
|
fn sl() void = { ds[sp - 1] = ds[sp - 1] << ds[sp]; pop(); };
|
|
fn sr() void = { ds[sp - 1] = ds[sp - 1] >> ds[sp]; pop(); };
|
|
fn cp() void = {
|
|
a = pop(); b = pop(); c = pop(); push(-1);
|
|
for (a > 0; a = a - 1) {
|
|
if (m[b] != m[c]) { ds[sp] = 0; };
|
|
b = b + 1;
|
|
c = c + 1;
|
|
};
|
|
};
|
|
fn cy() void = {
|
|
a = pop(); b = pop(); c = pop();
|
|
for (a > 0; a = a - 1) {
|
|
m[b] = m[c];
|
|
b = b + 1;
|
|
c = c + 1;
|
|
};
|
|
};
|
|
fn io() void = {
|
|
switch (pop()) {
|
|
case => return;
|
|
case 0 => fmt::printf("{}", pop():rune)!; return;
|
|
case 1 => let buf: [1]u8 = [0];
|
|
io::read(os::stdin, buf)!;
|
|
let z:i32 = buf[0]:i32;
|
|
push(z); return;
|
|
case 2 => let buf = pop(); let blk = pop();
|
|
read_block(blk, buf);
|
|
return;
|
|
case 3 => let buf = pop(); let blk = pop();
|
|
write_block(blk, buf);
|
|
return;
|
|
case 4 => return;
|
|
case 5 => initialize(); ip = -1; return;
|
|
case 6 => fmt::fatal("BYE!");
|
|
case 7 => push(sp); push(rp); return;
|
|
};
|
|
};
|
|
|
|
fn process(o: i32) void = {
|
|
switch (o) {
|
|
case => return;
|
|
case 0 => return; case 1 => return li();
|
|
case 2 => return du(); case 3 => return dr();
|
|
case 4 => return sw(); case 5 => return pu();
|
|
case 6 => return po(); case 7 => return ju();
|
|
case 8 => return ca(); case 9 => return cc();
|
|
case 10 => return cj(); case 11 => return re();
|
|
case 12 => return eq(); case 13 => return ne();
|
|
case 14 => return lt(); case 15 => return gt();
|
|
case 16 => return fe(); case 17 => return st();
|
|
case 18 => return ad(); case 19 => return su();
|
|
case 20 => return mu(); case 21 => return di();
|
|
case 22 => return an(); case 23 => return or();
|
|
case 24 => return xo(); case 25 => return sl();
|
|
case 26 => return sr(); case 27 => return cp();
|
|
case 28 => return cy(); case 29 => return io();
|
|
};
|
|
};
|
|
|
|
fn execute() void = {
|
|
for (ip < 65536) {
|
|
let opcode = m[ip];
|
|
process(opcode & 0xFF);
|
|
process((opcode >> 8) & 0xFF);
|
|
process((opcode >> 16) & 0xFF);
|
|
process((opcode >> 24) & 0xFF);
|
|
ip = ip + 1;
|
|
};
|
|
};
|
|
|
|
export fn main() void = {
|
|
initialize();
|
|
execute();
|
|
};
|