Skip to content

Commit

Permalink
feat: add interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
L2ncE committed Mar 23, 2024
1 parent 869dfc2 commit 83aa5f5
Show file tree
Hide file tree
Showing 14 changed files with 508 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: L2ncE
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
32 changes: 32 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**

A clear and concise description of what the bug is.

**To Reproduce**

Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**

A clear and concise description of what you expected to happen.

**Screenshots**

If applicable, add screenshots to help explain your problem.

**Additional context**

Add any other context about the problem here.
24 changes: 24 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**

A clear and concise description of what you want to happen.

**Describe alternatives you've considered**

A clear and concise description of any alternative solutions or features you've considered.

**Additional context**

Add any other context or screenshots about the feature request here.
32 changes: 32 additions & 0 deletions .github/ISSUE_TEMPLATE/question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: Question
about: Ask a question, so we can help you easily
title: ''
labels: ''
assignees: ''

---

**Describe the Question**

A clear and concise description of what the question is.

**Reproducible Code**

Please construct a minimum complete and reproducible example for us to get the same error. And tell us how to reproduce it like how you send a request or send what request.

**Expected behavior**

A clear and concise description of what you expected to happen.

**Screenshots**

If applicable, add screenshots to help explain your question.

**Hertz version:**

Please provide the version of Hertz you are using.

**Additional context**

Add any other context about the question here.
31 changes: 31 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#### What type of PR is this?
<!--
Add one of the following kinds:
build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
docs: Documentation only changes
feat: A new feature
optimize: A new optimization
fix: A bug fix
perf: A code change that improves performance
refactor: A code change that neither fixes a bug nor adds a feature
style: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc)
test: Adding missing tests or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
-->

#### Check the PR title.
<!--
The description of the title will be attached in Release Notes,
so please describe it from user-oriented, what this PR does / why we need it.
Please check your PR title with the below requirements:
-->
- [ ] This PR title match the format: \<type\>(optional scope): \<description\>
- [ ] The description of this PR title is user-oriented and clear enough for others to understand.


#### (Optional) More detail description for this PR.
<!--
Provide more detailed info for review. If it is a perf type PR, perf data is suggested to give.
-->
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: CI

on: [ push, pull_request ]

jobs:
Lint:
runs-on: [ ubuntu-latest ]
steps:
- uses: actions/checkout@v3
16 changes: 16 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "rsck"
version = "0.1.0"
authors = ["L2ncE <llance_24@foxmail.com>"]
edition = "2021"
default-run = "brainfuck_interpreter"

[[bin]]
name = "brainfuck_interpreter"
path = "src/main_interpreter.rs"

[[bin]]
name = "brainfuck_ir"
path = "src/main_ir.rs"

[dependencies]
1 change: 1 addition & 0 deletions example/hello_world.bf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
32 changes: 32 additions & 0 deletions example/sierpinski.bf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
>
+ +
+ +
[ < + +
+ +
+ + + +
> - ] >
+ + + + + + + +
[ >
+ + + +
< - ] >
> + + > > > + >
> > + <
< < < < < < < <
< [ - [ - > + <
] > [ - < + > > > . < < ] > > >
[ [
- > + +
+ + + +
+ + [ > + + + +
< - ] >
. < < [ - > + <
] + > [ - > + +
+ + + + + + + + < < + > ] > . [
- ] > ]
] + < < < [ - [
- > + < ] + > [
- < + > > > - [ - > + < ] + + >
[ - < - > ] < <
< ] < < < < ] + + + + + + + + +
+ . + + + . [ - ] < ] + + + + +
* * * * * M a d e * B y : * N Y Y R I K K I * 2 0 0 2 * * * * *
87 changes: 87 additions & 0 deletions src/ir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use super::opcode;

#[derive(Debug, PartialEq)]
pub enum IR {
SHR(u32),
SHL(u32),
ADD(u8),
SUB(u8),
PUTCHAR,
GETCHAR,
JIZ(u32),
JNZ(u32),
}

#[derive(Debug)]
pub struct Code {
pub instruct: Vec<IR>,
}

impl Code {
pub fn from(data: Vec<opcode::Opcode>) -> Result<Self, Box<dyn std::error::Error>> {
let mut instruct: Vec<IR> = Vec::new();
let mut j_stack: Vec<u32> = Vec::new();
for e in data {
match e {
opcode::Opcode::SHR => match instruct.last_mut() {
Some(IR::SHR(x)) => {
*x += 1;
}
_ => {
instruct.push(IR::SHR(1));
}
},
opcode::Opcode::SHL => match instruct.last_mut() {
Some(IR::SHL(x)) => {
*x += 1;
}
_ => {
instruct.push(IR::SHL(1));
}
},
opcode::Opcode::ADD => match instruct.last_mut() {
Some(IR::ADD(x)) => {
let (b, _) = x.overflowing_add(1);
*x = b;
}
_ => {
instruct.push(IR::ADD(1));
}
},
opcode::Opcode::SUB => match instruct.last_mut() {
Some(IR::SUB(x)) => {
let (b, _) = x.overflowing_add(1);
*x = b;
}
_ => {
instruct.push(IR::SUB(1));
}
},
opcode::Opcode::GETCHAR => {
instruct.push(IR::GETCHAR);
}
opcode::Opcode::PUTCHAR => {
instruct.push(IR::PUTCHAR);
}
opcode::Opcode::LB => {
instruct.push(IR::JIZ(0));
j_stack.push((instruct.len() - 1) as u32);
}
opcode::Opcode::RB => {
let j = j_stack.pop().ok_or("pop from empty list")?;
instruct.push(IR::JNZ(j));
let instrs_len = instruct.len();
match &mut instruct[j as usize] {
IR::JIZ(x) => {
*x = (instrs_len - 1) as u32;
}
_ => {
unimplemented!();
}
}
}
}
}
Ok(Code { instruct })
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod ir;
pub mod opcode;
72 changes: 72 additions & 0 deletions src/main_interpreter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::io::prelude::*;

use rsck::opcode;

struct Interpreter {
stack: Vec<u8>,
}

impl std::default::Default for Interpreter {
fn default() -> Self {
Self { stack: vec![0; 1] }
}
}

impl Interpreter {
fn run(&mut self, data: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
let code = opcode::Code::from(data)?;
let code_len = code.instruct.len();
let mut pc = 0;
let mut ps = 0;
loop {
if pc >= code_len {
break;
}
match code.instruct[pc] {
opcode::Opcode::SHL => ps = if ps == 0 { 0 } else { ps - 1 },
opcode::Opcode::SHR => {
ps += 1;
if ps == self.stack.len() {
self.stack.push(0)
}
}
opcode::Opcode::ADD => {
self.stack[ps] = self.stack[ps].overflowing_add(1).0;
}
opcode::Opcode::SUB => {
self.stack[ps] = self.stack[ps].overflowing_sub(1).0;
}
opcode::Opcode::PUTCHAR => {
std::io::stdout().write_all(&[self.stack[ps]])?;
}
opcode::Opcode::GETCHAR => {
let mut buf: Vec<u8> = vec![0; 1];
std::io::stdin().read_exact(&mut buf)?;
self.stack[ps] = buf[0];
}
opcode::Opcode::LB => {
if self.stack[ps] == 0x00 {
pc = code.j_table[&pc];
}
}
opcode::Opcode::RB => {
if self.stack[ps] != 0x00 {
pc = code.j_table[&pc];
}
}
}
pc += 1;
}
Ok(())
}
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
assert!(args.len() >= 2);
let mut f = std::fs::File::open(&args[1])?;
let mut c: Vec<u8> = Vec::new();
f.read_to_end(&mut c)?;
let mut i = Interpreter::default();
i.run(c)
}
Loading

0 comments on commit 83aa5f5

Please sign in to comment.