年賀状でふざけるために言語作ってみた

# 年賀状でふざけたい！
と言うことで、年賀状を難読プログラミング言語で書くことにしました

## どの言語にするか
Brainfuck は王道すぎてつまらない
Ook! とかもいいけど、正月感がない

### そうだ、作ってしまえ！
作ることにしました
色々考えた末、 Ook! の形式で、`Happy` `New` `Year` で構成することにしました
名前は `Happy` `New` `Year` の頭文字をとって `hnyfuck` とします

リポジトリはこちらです
https://github.com/kimuti-tsukai/hnyfuck

## 作る過程
※初めての言語作成で、多少下手なところがあると思いますが、温かい目でお見守り下さい

命令はそれぞれ次のようにします
`<` => `Happy New`
`>` =>  `New Year`
`+` => `Year Happy`
`-` => `Happy Year`
`.` => `Year New`
`,` => `New Happy`
`[` => `Happy Happy`
`]` => `New New`

初めてとは言っても、 Rust の proc_macro はたまに作るので、 proc_macro, syn を真似て作ってみます

とりあえず命令をこんなふうに定義します
```rs
const SHIFT_LEFT: (&str, &str) = ("Happy", "New");
const SHIFT_RIGHT: (&str, &str) = ("New", "Year");
const INCREMENT: (&str, &str) = ("Year", "Happy");
const DECREMENT: (&str, &str) = ("Happy", "Year");
const OUTPUT: (&str, &str) = ("Year", "New");
const INPUT: (&str, &str) = ("New", "Happy");
const LOOP_START: (&str, &str) = ("Happy", "Happy");
const LOOP_END: (&str, &str) = ("New", "New");
```

TokenStream を実装します
Queue のように使いたいので VecDeque をラップします
```rs
#[derive(Debug, Clone)]
struct TokenStream {
    tokens: VecDeque<String>,
}

impl TokenStream {
    fn new() -> TokenStream {
        TokenStream {
            tokens: VecDeque::new(),
        }
    }

    fn push(&mut self, token: String) {
        self.tokens.push_back(token);
    }

    fn from_str(input: &str) -> TokenStream {
        let mut stream = TokenStream::new();
        for token in input.split_whitespace() {
            stream.push(token.to_string());
        }
        stream
    }

    fn next(&mut self) -> Option<String> {
        self.tokens.pop_front()
    }

    fn next2(&mut self) -> Option<(String, String)> {
        let first = self.next();
        let second = self.next();
        match (first, second) {
            (Some(f), Some(s)) => Some((f, s)),
            _ => None,
        }
    }

    fn peek(&self) -> Option<&String> {
        self.tokens.front()
    }

    fn peekn(&self, n: usize) -> Option<&String> {
        self.tokens.get(n)
    }
}
```

標準入力を受け取るために InputStream を実装します
```rs
#[derive(Debug)]
struct InputStream {
    stdin: io::Bytes<io::Stdin>,
}

impl InputStream {
    fn new() -> InputStream {
        InputStream {
            stdin: io::stdin().bytes(),
        }
    }

    fn next(&mut self) -> Option<u8> {
        self.stdin.next().and_then(|result| result.ok())
    }
}
```

状態を管理するために、 State と言う構造体を定義します
先頭への追加も高速に行いたいので VecDeque を使います
```rs
#[derive(Debug)]
struct State {
    state: VecDeque<u8>,
    index: usize,
    input: InputStream,
}
```

命令を実装します
```rs
impl State {
    fn new() -> State {
        let mut state = VecDeque::new();
        state.push_back(0);
        State {
            state,
            index: 0,
            input: InputStream::new(),
        }
    }

    fn shift_left(&mut self) {
        match self.index {
            0 => self.state.push_front(0),
            _ => self.index -= 1,
        }
    }

    fn shiht_right(&mut self) {
        match self.index {
            i if i == self.state.len() - 1 => {
                self.state.push_back(0);
                self.index += 1;
            }
            _ => self.index += 1,
        }
    }

    fn increment(&mut self) {
        if let Some(cell) = self.state.get_mut(self.index) {
            *cell += 1;
        }
    }

    fn decrement(&mut self) {
        if let Some(cell) = self.state.get_mut(self.index) {
            *cell -= 1;
        }
    }

    fn output(&mut self) {
        if let Some(cell) = self.state.get(self.index) {
            print!("{}", *cell as char);
        }
    }

    fn input(&mut self) {
        if let Some(cell) = self.state.get_mut(self.index) {
            if let Some(byte) = self.input.next() {
                *cell = byte;
            }
        }
    }

    fn cond(&self) -> bool {
        self.state.get(self.index).map_or(false, |cell| *cell != 0)
    }
}
```

プログラムの状態を初期化、実行するための HnyFuck と言う構造体を定義します
```rs
#[derive(Debug)]
struct HnyFuck {
    stream: TokenStream,
    state: State,
}
```

ループの実装の仕方はよく知らないので、今回はループ内のコードをコピーして現在の状態で実装します
```rs
impl HnyFuck {
    fn new(stream: TokenStream) -> Self {
        Self {
            stream,
            state: State::new(),
        }
    }

    fn from_str(input: &str) -> Self {
        Self::new(TokenStream::from_str(input))
    }

    fn run(&mut self) {
        while let Some((first, second)) = self.stream.next2() {
            match (first.as_str(), second.as_str()) {
                SHIFT_LEFT => self.state.shift_left(),
                SHIFT_RIGHT => self.state.shiht_right(),
                INCREMENT => self.state.increment(),
                DECREMENT => self.state.decrement(),
                OUTPUT => self.state.output(),
                INPUT => self.state.input(),
                LOOP_START => {
                    let mut token_stream = TokenStream::new();
                    let mut depth = 1;
                    while let Some((token1, token2)) = self.stream.next2() {
                        match (token1.as_str(), token2.as_str()) {
                            LOOP_START => depth += 1,
                            LOOP_END => {
                                depth -= 1;
                                if depth == 0 {
                                    break;
                                }
                            }
                            _ => (),
                        }
                        token_stream.push(token1);
                        token_stream.push(token2);
                    }

                    let state = std::mem::replace(&mut self.state, State::new());

                    let mut nest = Self {
                        stream: token_stream.clone(),
                        state,
                    };

                    while {
                        nest.run();

                        nest.stream = token_stream.clone();

                        nest.state.cond()
                    } {}

                    self.state = nest.state;
                }
                _ => panic!("Invalid token"),
            }
        }
    }
}
```

これで完成です

Brainfuck から変換するやつも実装したのでどうぞ
```rs
fn from_brainfuck(code: &str) -> String {
    code
        .chars()
        .map(|c| match c {
            '>' => SHIFT_RIGHT,
            '<' => SHIFT_LEFT,
            '+' => INCREMENT,
            '-' => DECREMENT,
            '.' => OUTPUT,
            ',' => INPUT,
            '[' => LOOP_START,
            ']' => LOOP_END,
            _ => panic!("Invalid character"),
        })
        .map(|(a, b)| format!("{} {}", a, b))
        .collect::<Vec<String>>()
        .join(" ")
}
```

ほとんどコードの記事になってすみません