mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-14 16:45:08 +01:00
interrupts!
This commit is contained in:
parent
b56c293581
commit
ce7deb7dc6
4 changed files with 64 additions and 17 deletions
22
README.md
22
README.md
|
|
@ -88,6 +88,14 @@ The result is stored in the `place` `A`.
|
|||
Div divides the `place` `A` by the `value` `B`.
|
||||
The result is stored in the `place` `A`.
|
||||
|
||||
### Int
|
||||
|
||||
`int N`
|
||||
|
||||
Int performs the interrupt with the number `N`. `N` must be a number literal.
|
||||
|
||||
For a list of interrupts, see the list below.
|
||||
|
||||
### Cmp
|
||||
|
||||
`cmp A, B`
|
||||
|
|
@ -112,4 +120,16 @@ the next instruction executed will be the instruction located at `L`.
|
|||
`<IDENT>:`
|
||||
|
||||
A label is an identifier (regex: `[a-zA-Z]\w+`) followed by a colon (`:`). Jumps (like `jmp` or `je`) will be able
|
||||
to jump to this label. A label is applied to the *next* instruction in the code.
|
||||
to jump to this label. A label is applied to the *next* instruction in the code.
|
||||
|
||||
## Interrupts
|
||||
|
||||
### `int 0`
|
||||
|
||||
The interrupt 0 exits the program. The exit code is passed in `r0`.
|
||||
|
||||
### `int 1`
|
||||
|
||||
The interrupt 0 writes a string to standard output. `r0` contains the address of the string data.
|
||||
`r1` contains the length of the string. The string is encoded as `UTF-8`. After the interrupt completed,
|
||||
`r0` will contain a 0 if writing was successful, or a `1` if it failed.
|
||||
|
|
@ -22,29 +22,27 @@ impl Register {
|
|||
}
|
||||
}
|
||||
|
||||
const MEMORY_SIZE = 1024 * 1024 * 1024;
|
||||
const MEMORY_SIZE: usize = 1024 * 1024 * 1024;
|
||||
|
||||
struct InterpretCtx {
|
||||
memory: Vec<u8>,
|
||||
registers: [u64; 16],
|
||||
flag: bool,
|
||||
stmts: Vec<Stmt>,
|
||||
spans: Vec<Span>,
|
||||
ip: usize,
|
||||
}
|
||||
|
||||
impl InterpretCtx {
|
||||
fn interpret(&mut self) -> Result<()> {
|
||||
fn interpret(&mut self, stmts: Vec<Stmt>) -> Result<()> {
|
||||
let stmt_i = self.ip;
|
||||
while stmt_i < self.stmts.len() {
|
||||
while stmt_i < stmts.len() {
|
||||
self.ip += 1;
|
||||
self.interpret_stmt(stmt_i)?
|
||||
self.interpret_stmt(stmt_i, &stmts)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn interpret_stmt(&mut self, stmt_i: usize) -> Result<()> {
|
||||
let stmt = &self.stmts[stmt_i];
|
||||
fn interpret_stmt(&mut self, stmt_i: usize, stmts: &[Stmt]) -> Result<()> {
|
||||
let stmt = &stmts[stmt_i];
|
||||
match stmt {
|
||||
Stmt::Mov { from, to } => {
|
||||
let value = self.read_value(from);
|
||||
|
|
@ -74,6 +72,9 @@ impl InterpretCtx {
|
|||
let new = old.wrapping_div(value);
|
||||
self.write_place(to, new);
|
||||
}
|
||||
Stmt::Int { number } => {
|
||||
self.interrupt(*number);
|
||||
}
|
||||
Stmt::Jmp { to } => {
|
||||
let index = to.index;
|
||||
self.ip = index;
|
||||
|
|
@ -93,6 +94,14 @@ impl InterpretCtx {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn interrupt(&mut self, number: u64) {
|
||||
match number {
|
||||
0 => todo!("exit"),
|
||||
1 => todo!("print"),
|
||||
_ => panic!("invalid interrupt!"),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_value(&self, value: &Value) -> u64 {
|
||||
match value {
|
||||
Value::Literal(n) => *n,
|
||||
|
|
@ -153,16 +162,13 @@ impl InterpretCtx {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn interpret(stmts: Vec<Stmt>, spans: Vec<Span>) -> Result<()> {
|
||||
pub fn interpret(stmts: Vec<Stmt>, _spans: Vec<Span>) -> Result<()> {
|
||||
let mut ctx = InterpretCtx {
|
||||
memory: vec![0; MEMORY_SIZE],
|
||||
registers: [0; 16],
|
||||
flag: false,
|
||||
stmts,
|
||||
spans,
|
||||
ip: 0,
|
||||
};
|
||||
|
||||
ctx.interpret()
|
||||
ctx.interpret(stmts)
|
||||
}
|
||||
|
|
|
|||
12
src/ir.rs
12
src/ir.rs
|
|
@ -1,5 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use std::{collections::HashMap, mem};
|
||||
|
||||
use dbg_pls::DebugPls;
|
||||
use logos::Span;
|
||||
|
|
@ -40,6 +39,7 @@ pub enum Stmt {
|
|||
Sub { to: Place, value: Value },
|
||||
Mul { to: Place, value: Value },
|
||||
Div { to: Place, value: Value },
|
||||
Int { number: u64 },
|
||||
Jmp { to: Location },
|
||||
Je { to: Location },
|
||||
Cmp { lhs: Value, rhs: Value },
|
||||
|
|
@ -95,6 +95,12 @@ impl CompileCtx {
|
|||
let value = self.compile_value(value)?;
|
||||
Stmt::Div { to, value }
|
||||
}
|
||||
StmtKind::Int { number } => {
|
||||
if number > 1 {
|
||||
return Err(CompilerError::simple("invalid interrupt".to_string(), p_stmt.span));
|
||||
}
|
||||
Stmt::Int { number }
|
||||
},
|
||||
StmtKind::Jmp { to } => {
|
||||
let to = self.compile_location(to, self.stmts.len())?;
|
||||
Stmt::Jmp { to }
|
||||
|
|
@ -194,7 +200,7 @@ impl CompileCtx {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn resolve_location(&mut self, index: usize, label: &str) -> Result<()>{
|
||||
fn resolve_location(&mut self, index: usize, label: &str) -> Result<()> {
|
||||
let (location, _) = self.labels.get(label).ok_or_else(|| {
|
||||
CompilerError::simple(
|
||||
format!("label {label} not found"),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ pub enum Token<'a> {
|
|||
Mul,
|
||||
#[token("div")]
|
||||
Div,
|
||||
#[token("int")]
|
||||
Int,
|
||||
#[token("[")]
|
||||
BracketOpen,
|
||||
#[token("]")]
|
||||
|
|
@ -65,6 +67,7 @@ pub enum StmtKind {
|
|||
Sub { to: Expr, value: Expr },
|
||||
Mul { to: Expr, value: Expr },
|
||||
Div { to: Expr, value: Expr },
|
||||
Int { number: u64 },
|
||||
Jmp { to: Expr },
|
||||
Je { to: Expr },
|
||||
Cmp { lhs: Expr, rhs: Expr },
|
||||
|
|
@ -195,6 +198,17 @@ where
|
|||
let value = self.expr()?;
|
||||
stmt(span.start..value.span.end, StmtKind::Div { to, value })
|
||||
}
|
||||
Token::Int => {
|
||||
let (next, next_span) = self.next()?;
|
||||
if let Token::Number(number) = next {
|
||||
stmt(span.start..next_span.end, StmtKind::Int { number })
|
||||
} else {
|
||||
return Err(CompilerError::simple(
|
||||
format!("Expected number, found {:?}", next,),
|
||||
next_span,
|
||||
));
|
||||
}
|
||||
}
|
||||
Token::Label(name) => {
|
||||
let name = name
|
||||
.strip_suffix(":")
|
||||
|
|
@ -253,6 +267,7 @@ where
|
|||
Token::Sub => return Err(CompilerError::not_allowed(span, "sub")),
|
||||
Token::Mul => return Err(CompilerError::not_allowed(span, "mul")),
|
||||
Token::Div => return Err(CompilerError::not_allowed(span, "div")),
|
||||
Token::Int => return Err(CompilerError::not_allowed(span, "int")),
|
||||
Token::BracketClose => return Err(CompilerError::not_allowed(span, "]")),
|
||||
Token::Comma => return Err(CompilerError::not_allowed(span, ",")),
|
||||
Token::Label(_) => return Err(CompilerError::not_allowed(span, "{label}")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue