Base compilation of some kind of file to a list of instructions seems to work(!)
I'm able to compile some basic expressions into instructions using the `not` binary. Big first step, now we need to introduce branches and loops to the syntax. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -69,7 +69,10 @@ impl BasicBlockList {
|
||||
body.push(Inst::Jump(addr));
|
||||
}
|
||||
}
|
||||
BasicBlock::Branch { block_true, block_false } => {
|
||||
BasicBlock::Branch {
|
||||
block_true,
|
||||
block_false,
|
||||
} => {
|
||||
// insert conditional jump to true statement, and unconditional jump to false
|
||||
// statement
|
||||
let addr_true = addr_rev[&block_true];
|
||||
@@ -96,10 +99,22 @@ impl BasicBlockList {
|
||||
let mut blocks = Vec::with_capacity(self.len());
|
||||
let mut entry_map = BTreeMap::new();
|
||||
// first pass: add blocks to the "blocks" list, and map block indices
|
||||
let mut last_block_index = 0;
|
||||
for (new_index, (index, block)) in self.blocks.into_iter().enumerate() {
|
||||
// search for the largest block index referred to in here - that is the last block
|
||||
match block {
|
||||
BasicBlock::Block { exit, .. } => last_block_index = exit.max(last_block_index),
|
||||
BasicBlock::Branch {
|
||||
block_true,
|
||||
block_false,
|
||||
} => last_block_index = block_true.max(block_false.max(last_block_index)),
|
||||
}
|
||||
blocks.push(block);
|
||||
entry_map.insert(index, new_index);
|
||||
}
|
||||
// this inserts a "dummy" mapping for the last block index because it will point out of bounds
|
||||
let last_index = entry_map.len();
|
||||
entry_map.insert(dbg!(last_block_index), dbg!(last_index));
|
||||
// second pass: update blocks in-place with their newly mapped addresses
|
||||
blocks
|
||||
.into_iter()
|
||||
|
||||
@@ -3,9 +3,10 @@ pub mod error;
|
||||
mod locals;
|
||||
pub mod thunk;
|
||||
|
||||
use crate::{syn::ast::Body, obj::prelude::*, vm::consts::*};
|
||||
use crate::{syn::ast::Body, obj::prelude::*, vm::{consts::*, inst::Inst}};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Compile {
|
||||
const_data: ConstData,
|
||||
globals: BTreeMap<Sym, Local>,
|
||||
@@ -16,12 +17,16 @@ pub struct Compile {
|
||||
impl Compile {
|
||||
/// Creates a new compiler using the given text.
|
||||
pub fn new() -> Self {
|
||||
Compile {
|
||||
const_data: Default::default(),
|
||||
globals: Default::default(),
|
||||
locals: Default::default(),
|
||||
next_local: Default::default(),
|
||||
}
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Compiles the given AST body.
|
||||
pub fn compile<'c>(&'c mut self, body: &Body) -> error::Result<(Vec<Inst>, &'c ConstPool)> {
|
||||
let main = thunk::CompileBody::new(self)
|
||||
.compile(body)?
|
||||
.flatten()
|
||||
.to_vec();
|
||||
Ok((main, &self.const_data.const_pool))
|
||||
}
|
||||
|
||||
/// Gets the constant data that is interned in this compile session.
|
||||
|
||||
@@ -234,7 +234,7 @@ impl Visit for CompileBody<'_> {
|
||||
self.compile.collect_locals(body);
|
||||
let mut thunk = Thunk::Nop;
|
||||
|
||||
for stmt in body.body.iter() {
|
||||
for stmt in body.iter() {
|
||||
thunk.push_thunk(stmt.accept(self)?);
|
||||
}
|
||||
|
||||
@@ -347,7 +347,13 @@ impl Visit for CompileBody<'_> {
|
||||
let thunk = match atom {
|
||||
Atom::Ident(ident) => {
|
||||
let sym = global_sym(ident.to_string());
|
||||
let local = self.compile.lookup_scope(sym).unwrap();
|
||||
let local = if let Some(local) = self.compile.lookup_scope(sym) {
|
||||
local
|
||||
} else {
|
||||
// create a global that gets looked up instead, since nothing with this name
|
||||
// has been declared/assigned in this scope
|
||||
self.compile.create_global(sym)
|
||||
};
|
||||
// get local
|
||||
Inst::PushLocal(local).into()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user