Skip to content

Instantly share code, notes, and snippets.

@niconii
Last active November 16, 2016 05:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niconii/0f0ce03ca57ecb6c2317a6cde691f338 to your computer and use it in GitHub Desktop.
Save niconii/0f0ce03ca57ecb6c2317a6cde691f338 to your computer and use it in GitHub Desktop.
(WIP) Prints CrayonForth source code blocks
/*
crayonforth source code block format
each block is 256 dwords (1024 bytes), stored little-endian
31...24 23...16 15...8 7...0
____0ttt aaaaaabb bbbbcccc ccdddddd word
____0000 aaaaaabb bbbbcccc ccdddddd extension of previous word
__ux1ttt ________ hhhhhhhh llllllll number
____1111 ________ ________ ________ end of data
t = tag/color
abcd = 6-bit text, right-aligned, 0-padded
h = number[15...8]
l = number[7...0]
u = 0: print as signed, 1: print as unsigned
x = 0: print as decimal, 1: print as hex
_ = unused
*/
use std::result::Result as StdResult;
fn main() {
use Tag::*;
let mut block = Block::new();
block.push_word(Label, "niconii").unwrap();
block.push_number(Compile, 0x2525, true).unwrap();
block.push_number(Interpret, -1, false).unwrap();
block.dump_ansi();
block.dump_hex();
}
const TAG: u32 = 0x07000000;
const NUMBER: u32 = 0x08000000;
const HEX: u32 = 0x10000000;
const UNSIGNED: u32 = 0x20000000;
const C4_CHARS: [u8; 64] =
*br##" !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[|]^_"##
;
fn char_to_c4(ch: char) -> u8 {
(ch as u8 & 0x40) >> 1 | (ch as u8 & 0x1f)
}
fn c4_to_char(ch: u8) -> char {
C4_CHARS[ch as usize] as char
}
fn word_to_string(mut word: u32) -> String {
let mut s = String::new();
for _ in 0..4 {
let ch = ((word >> 18) & 0x3f) as u8;
if ch != 0 { s.push(c4_to_char(ch)); }
word <<= 6;
}
s
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Error {
BlockFull,
OutOfRange
}
pub type Result = StdResult<(), Error>;
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Tag {
Extension, Comment, Edit, Interpret,
Compile, Postpone, Wordlit, Label
}
pub struct Block {
buf: [u32; 256],
ptr: usize
}
impl Block {
fn new() -> Block {
Block {
buf: [0xffffffff; 256],
ptr: 0
}
}
fn push(&mut self, w: u32) -> Result {
if self.ptr < 256 {
self.buf[self.ptr] = w;
self.ptr += 1;
Ok(())
} else {
Err(Error::BlockFull)
}
}
fn push_number(&mut self, tag: Tag, n: i32, hex: bool) -> Result {
let u = match n {
32768...65535 => UNSIGNED,
-32768...32767 => 0,
_ => return Err(Error::OutOfRange)
};
let x = if hex { HEX } else { 0 };
self.push(u | x | NUMBER | (tag as u32) << 24 | n as u16 as u32)
}
fn push_word(&mut self, tag: Tag, s: &str) -> Result {
let mut words = vec![];
let mut w = 0;
let chars: Vec<char> = s.chars().collect();
for chunk in chars.chunks(4) {
for &ch in chunk {
w <<= 6;
w |= char_to_c4(ch) as u32;
}
words.push(w);
w = 0;
}
for (i, &word) in words.iter().enumerate() {
if i == 0 {
try!(self.push((tag as u32) << 24 | word));
} else {
try!(self.push(word));
}
}
Ok(())
}
fn dump_ansi(&self) {
let mut words = self.buf.iter();
while let Some(&word) = words.next() {
// label + number = end of block data
if word & (TAG | NUMBER) == (TAG | NUMBER) {
break
}
// read tag
match (word & TAG) >> 24 {
0 => print!("\x08"), // extension of previous word
1 => print!("\x1b[37;1m"), // comment (white)
2 => print!("\x1b[34;1m"), // edit (blue)
3 => print!("\x1b[33;1m"), // interpret (yellow)
4 => print!("\x1b[32;1m"), // compile (green)
5 => print!("\x1b[36;1m"), // postpone (cyan)
6 => print!("\x1b[35;1m"), // wordlit (orange, but magenta here)
_ => print!("\x1b[31;1m") // label (red)
}
// extract number
let number = if word & UNSIGNED != 0 {
word as u16 as i32
} else {
word as i16 as i32
};
// check if word or number
match word & NUMBER {
0 => print!("{} ", word_to_string(word)), // word
_ => match word & HEX {
0 => print!("{} ", number), // decimal number
_ => print!("${:x} ", number) // hex number
}
}
}
println!("\x1b[0m");
}
fn dump_hex(&self) {
for &word in self.buf.iter() {
if word & (TAG | NUMBER) == (TAG | NUMBER) {
break
}
print!("{:08x} ", word);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment