mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-14 16:45:08 +01:00
mob
This commit is contained in:
parent
ce7deb7dc6
commit
f9a3d93558
5 changed files with 108 additions and 27 deletions
|
|
@ -9,6 +9,8 @@
|
|||
//! Decimal 1
|
||||
//! ```
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use logos::Span;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -33,8 +35,8 @@ struct InterpretCtx {
|
|||
|
||||
impl InterpretCtx {
|
||||
fn interpret(&mut self, stmts: Vec<Stmt>) -> Result<()> {
|
||||
let stmt_i = self.ip;
|
||||
while stmt_i < stmts.len() {
|
||||
while self.ip < stmts.len() {
|
||||
let stmt_i = self.ip;
|
||||
self.ip += 1;
|
||||
self.interpret_stmt(stmt_i, &stmts)?
|
||||
}
|
||||
|
|
@ -48,6 +50,10 @@ impl InterpretCtx {
|
|||
let value = self.read_value(from);
|
||||
self.write_place(to, value);
|
||||
}
|
||||
Stmt::Movb { from, to } => {
|
||||
let value = self.read_byte_value(from);
|
||||
self.write_byte_place(to, value);
|
||||
}
|
||||
Stmt::Add { to, value } => {
|
||||
let old = self.read_place(to);
|
||||
let value = self.read_value(value);
|
||||
|
|
@ -96,8 +102,17 @@ impl InterpretCtx {
|
|||
|
||||
fn interrupt(&mut self, number: u64) {
|
||||
match number {
|
||||
0 => todo!("exit"),
|
||||
1 => todo!("print"),
|
||||
0 => {
|
||||
let code = self.reg(Register(0));
|
||||
std::process::exit(code as i32);
|
||||
}
|
||||
1 => {
|
||||
let str_addr = self.reg_addr(Register(0));
|
||||
let str_len = self.reg_addr(Register(1));
|
||||
let slice = &self.memory[str_addr..][..str_len];
|
||||
let is_ok = std::io::stdout().lock().write_all(slice).is_ok();
|
||||
*self.reg_mut(Register(0)) = if is_ok { 0 } else { 1 };
|
||||
}
|
||||
_ => panic!("invalid interrupt!"),
|
||||
}
|
||||
}
|
||||
|
|
@ -109,11 +124,18 @@ impl InterpretCtx {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_byte_value(&self, value: &Value) -> u8 {
|
||||
match value {
|
||||
Value::Literal(n) => *n as u8,
|
||||
Value::Place(place) => self.read_byte_place(place),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_place(&self, place: &Place) -> u64 {
|
||||
match place {
|
||||
Place::Register(reg) => self.registers[reg.as_index()],
|
||||
Place::Register(reg) => self.reg(*reg),
|
||||
Place::AddrRegister(reg) => {
|
||||
let addr = self.registers[reg.as_index()] as usize;
|
||||
let addr = self.reg_addr(*reg);
|
||||
self.read_addr(addr)
|
||||
}
|
||||
Place::AddrLiteral(addr) => {
|
||||
|
|
@ -123,14 +145,27 @@ impl InterpretCtx {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_byte_place(&self, place: &Place) -> u8 {
|
||||
match place {
|
||||
Place::Register(reg) => self.reg(*reg) as u8,
|
||||
Place::AddrRegister(reg) => {
|
||||
let addr = self.reg_addr(*reg);
|
||||
self.memory[addr]
|
||||
}
|
||||
Place::AddrLiteral(addr) => {
|
||||
let addr = *addr as usize;
|
||||
self.memory[addr]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_place(&mut self, place: &Place, value: u64) {
|
||||
match place {
|
||||
Place::Register(reg) => {
|
||||
let r = &mut self.registers[reg.as_index()];
|
||||
*r = value;
|
||||
*self.reg_mut(*reg) = value;
|
||||
}
|
||||
Place::AddrRegister(reg) => {
|
||||
let addr = self.registers[reg.as_index()] as usize;
|
||||
let addr = self.reg_addr(*reg);
|
||||
self.write_addr(addr, value);
|
||||
}
|
||||
Place::AddrLiteral(addr) => {
|
||||
|
|
@ -140,6 +175,22 @@ impl InterpretCtx {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_byte_place(&mut self, place: &Place, value: u8) {
|
||||
match place {
|
||||
Place::Register(reg) => {
|
||||
*self.reg_mut(*reg) = value.into();
|
||||
}
|
||||
Place::AddrRegister(reg) => {
|
||||
let addr = self.reg_addr(*reg);
|
||||
self.memory[addr] = value;
|
||||
}
|
||||
Place::AddrLiteral(addr) => {
|
||||
let addr = *addr as usize;
|
||||
self.memory[addr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_addr(&self, addr: usize) -> u64 {
|
||||
u64::from_le_bytes([
|
||||
self.memory[addr],
|
||||
|
|
@ -160,6 +211,18 @@ impl InterpretCtx {
|
|||
self.memory[addr + i] = bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
fn reg(&self, reg: Register) -> u64 {
|
||||
self.registers[reg.as_index()]
|
||||
}
|
||||
|
||||
fn reg_mut(&mut self, reg: Register) -> &mut u64 {
|
||||
&mut self.registers[reg.as_index()]
|
||||
}
|
||||
|
||||
fn reg_addr(&self, reg: Register) -> usize {
|
||||
self.reg(reg) as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interpret(stmts: Vec<Stmt>, _spans: Vec<Span>) -> Result<()> {
|
||||
|
|
|
|||
13
src/ir.rs
13
src/ir.rs
|
|
@ -35,6 +35,7 @@ pub struct Location {
|
|||
#[derive(Debug, Clone, Copy, DebugPls)]
|
||||
pub enum Stmt {
|
||||
Mov { to: Place, from: Value },
|
||||
Movb { to: Place, from: Value },
|
||||
Add { to: Place, value: Value },
|
||||
Sub { to: Place, value: Value },
|
||||
Mul { to: Place, value: Value },
|
||||
|
|
@ -75,6 +76,11 @@ impl CompileCtx {
|
|||
let to = self.compile_place(to)?;
|
||||
Stmt::Mov { from, to }
|
||||
}
|
||||
StmtKind::Movb { from, to } => {
|
||||
let from = self.compile_value(from)?;
|
||||
let to = self.compile_place(to)?;
|
||||
Stmt::Movb { from, to }
|
||||
}
|
||||
StmtKind::Add { to, value } => {
|
||||
let to = self.compile_place(to)?;
|
||||
let value = self.compile_value(value)?;
|
||||
|
|
@ -97,10 +103,13 @@ impl CompileCtx {
|
|||
}
|
||||
StmtKind::Int { number } => {
|
||||
if number > 1 {
|
||||
return Err(CompilerError::simple("invalid interrupt".to_string(), p_stmt.span));
|
||||
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 }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use crate::error::{CompilerError, Result};
|
|||
pub enum Token<'a> {
|
||||
#[token("mov")]
|
||||
Mov,
|
||||
#[token("movb")]
|
||||
Movb,
|
||||
#[token("jmp")]
|
||||
Jmp,
|
||||
#[token("je")]
|
||||
|
|
@ -63,6 +65,7 @@ impl DebugPls for Stmt {
|
|||
#[derive(Debug, PartialEq, Eq, DebugPls)]
|
||||
pub enum StmtKind {
|
||||
Mov { to: Expr, from: Expr },
|
||||
Movb { to: Expr, from: Expr },
|
||||
Add { to: Expr, value: Expr },
|
||||
Sub { to: Expr, value: Expr },
|
||||
Mul { to: Expr, value: Expr },
|
||||
|
|
@ -160,6 +163,12 @@ where
|
|||
let from = self.expr()?;
|
||||
stmt(span.start..from.span.end, StmtKind::Mov { to, from })
|
||||
}
|
||||
Token::Movb => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
let from = self.expr()?;
|
||||
stmt(span.start..from.span.end, StmtKind::Movb { to, from })
|
||||
}
|
||||
Token::Jmp => {
|
||||
let to = self.expr()?;
|
||||
stmt(span.start..to.span.end, StmtKind::Jmp { to })
|
||||
|
|
@ -260,6 +269,7 @@ where
|
|||
expr(ExprKind::Symbol(name.to_owned()), span)
|
||||
}
|
||||
Token::Mov => return Err(CompilerError::not_allowed(span, "mov")),
|
||||
Token::Movb => return Err(CompilerError::not_allowed(span, "movb")),
|
||||
Token::Jmp => return Err(CompilerError::not_allowed(span, "jmp")),
|
||||
Token::Je => return Err(CompilerError::not_allowed(span, "je")),
|
||||
Token::Cmp => return Err(CompilerError::not_allowed(span, "cmp")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue