Skip to content
This repository was archived by the owner on Nov 25, 2019. It is now read-only.

Commit aa3d636

Browse files
committed
Start on a Rust implementation
1 parent 645fde6 commit aa3d636

File tree

3 files changed

+125
-6
lines changed

3 files changed

+125
-6
lines changed

Makefile

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
1-
CC=g++
2-
SOURCES=./src/qqq.cpp
3-
EXECUTABLE=./bin/qqq
1+
OS ?= $(shell uname)
42

5-
all:
6-
$(CC) $(SOURCES) -o $(EXECUTABLE) -Wall -O0
3+
# Assume Visual C++ on Windows
4+
# Environments like Cygwin will hopefully fall through and pick up the
5+
# appropriate Unix-like options
6+
ifeq ($(OS),Windows_NT)
7+
EXE := bin\qqq.exe
8+
OUT := /out:$(EXE)
9+
CXX := cl
10+
CXXFLAGS := /EHsc /W4
11+
else
12+
EXE := bin/qqq
13+
OUT := -o $(EXE)
14+
CXXFLAGS := -Wall -O0
15+
ifneq (,$(findstring $(OS),Darwin FreeBSD))
16+
CXX := clang++
17+
else
18+
CXX := g++
19+
endif # macOS or FreeBSD
20+
endif # Windows
21+
22+
setup:
23+
-mkdir bin
24+
25+
cpp: setup
26+
$(CXX) cpp/qqq.cpp $(OUT) $(CXXFLAGS)
27+
28+
rust: setup
29+
rustc rust/main.rs $(OUT)
730

831
clean:
9-
rm $(EXECUTABLE)
32+
-rm $(EXE)

bin/.gitkeep

Whitespace-only changes.

rust/main.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use std::io::{stdin, stdout, Read, Write};
2+
3+
fn parse_instructions(code: String) -> Vec<char> {
4+
let mut instructions = Vec::new();
5+
let mut is_open = true;
6+
let mut bracket_depth = 0;
7+
while let Some(c) = code.chars().next() {
8+
match c {
9+
'!' | '?' | '.' | ',' | '-' | ';' => instructions.push(c),
10+
'\'' => {
11+
is_open = !is_open;
12+
},
13+
'"' if is_open => {
14+
bracket_depth += 1;
15+
instructions.push('[');
16+
},
17+
'"' if !is_open => {
18+
bracket_depth -= 1;
19+
instructions.push(']');
20+
},
21+
_ => continue,
22+
}
23+
}
24+
if bracket_depth != 0 {
25+
panic!("Unmatched quotes detected!")
26+
}
27+
instructions
28+
}
29+
30+
fn evaluate(instructions: Vec<char>) {
31+
if instructions.is_empty() {
32+
return;
33+
}
34+
let mut tape = vec![0x00];
35+
let mut ins_ptr = 0; // instruction pointer: index in `instructions` of current instruction
36+
let mut mem_ptr = 0; // memory pointer: index in `tape` of current memory cell
37+
while ins_ptr != instructions.len() - 1 {
38+
match instructions[ins_ptr] {
39+
'-' => {
40+
// can't travel left of the starting cell
41+
if mem_ptr != 0 { mem_ptr -= 1 }
42+
},
43+
';' => {
44+
mem_ptr += 1;
45+
// lazily grow the tape as needed
46+
if mem_ptr > tape.len() - 1 { tape.resize(mem_ptr + 1, 0x00) }
47+
},
48+
'.' => {
49+
tape[mem_ptr] += 0x01;
50+
},
51+
',' => {
52+
tape[mem_ptr] -= 0x01;
53+
},
54+
'?' => {
55+
let input: Option<u8> = io::stdin().bytes()
56+
.next()
57+
.map(|b| b as u8)
58+
.expect("No input received");
59+
tape[mem_ptr] = input.unwrap();
60+
},
61+
'!' => {
62+
// print as char if printable ASCII, otherwise print raw
63+
if tape[mem_ptr] >= 0x20 && tape[mem_ptr] <= 0x7e {
64+
print!("{}", tape[mem_ptr] as char)
65+
} else {
66+
print!("{}", tape[mem_ptr])
67+
}
68+
io::stdout().flush().unwrap();
69+
},
70+
'[' => {
71+
if tape[mem_ptr] == 0x00 {
72+
// advance to matching close bracket
73+
while instructions[ins_ptr] != ']' {
74+
ins_ptr += 1
75+
}
76+
}
77+
continue
78+
},
79+
']' => {
80+
if tape[mem_ptr] == 0x00 {
81+
// move back to just before the matching open bracket
82+
while instructions[ins_ptr] != '[' {
83+
ins_ptr -= 1
84+
}
85+
ins_ptr -= 1
86+
}
87+
continue
88+
}
89+
}
90+
ins_ptr += 1
91+
}
92+
}
93+
94+
fn main() {
95+
// TODO
96+
}

0 commit comments

Comments
 (0)