type checking !?!?
This commit is contained in:
@@ -1,17 +1,33 @@
|
||||
use crate::{compiler::arch::riscv64::*, ir::VarID};
|
||||
use crate::{
|
||||
compiler::arch::riscv64::*,
|
||||
ir::{VarID, VarInst},
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RV64Instruction {
|
||||
Ecall,
|
||||
Li { dest: RegRef, imm: i64 },
|
||||
Mv { dest: RegRef, src: RegRef },
|
||||
La { dest: RegRef, src: VarID },
|
||||
Ld { dest: RegRef, offset: i64, base: RegRef },
|
||||
Li {
|
||||
dest: RegRef,
|
||||
imm: i64,
|
||||
},
|
||||
Mv {
|
||||
dest: RegRef,
|
||||
src: RegRef,
|
||||
},
|
||||
La {
|
||||
dest: RegRef,
|
||||
src: VarInst,
|
||||
},
|
||||
Ld {
|
||||
dest: RegRef,
|
||||
offset: i64,
|
||||
base: RegRef,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RegRef {
|
||||
Var(VarID),
|
||||
Var(VarInst),
|
||||
Reg(Reg),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FilePos {
|
||||
pub line: usize,
|
||||
pub col: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FileSpan {
|
||||
pub start: FilePos,
|
||||
pub end: FilePos,
|
||||
}
|
||||
|
||||
impl FilePos {
|
||||
pub fn start() -> Self {
|
||||
Self { line: 0, col: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePos {
|
||||
pub fn to(self, end: FilePos) -> FileSpan {
|
||||
FileSpan { start: self, end }
|
||||
}
|
||||
pub fn char_span(self) -> FileSpan {
|
||||
FileSpan::at(self)
|
||||
}
|
||||
}
|
||||
|
||||
const BEFORE: usize = 1;
|
||||
const AFTER: usize = 0;
|
||||
|
||||
impl FileSpan {
|
||||
pub fn at(pos: FilePos) -> Self {
|
||||
Self {
|
||||
start: pos,
|
||||
end: pos,
|
||||
}
|
||||
}
|
||||
pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> {
|
||||
let start = self.start.line.saturating_sub(BEFORE);
|
||||
let num_before = self.start.line - start;
|
||||
let mut lines = file.lines().skip(start);
|
||||
let width = format!("{}", self.end.line + AFTER).len();
|
||||
let same_line = self.start.line == self.end.line;
|
||||
for i in 0..num_before {
|
||||
writeln!(writer, "{:>width$} | {}", start + i, lines.next().unwrap())?;
|
||||
}
|
||||
let line = lines.next().unwrap();
|
||||
writeln!(writer, "{:>width$} | {}", self.start.line, line)?;
|
||||
let len = if same_line {
|
||||
self.end.col - self.start.col + 1
|
||||
} else {
|
||||
line.len() - self.start.col
|
||||
};
|
||||
writeln!(
|
||||
writer,
|
||||
"{} | {}",
|
||||
" ".repeat(width),
|
||||
" ".repeat(self.start.col) + &"^".repeat(len)
|
||||
)?;
|
||||
if !same_line {
|
||||
for _ in 0..self.end.line - self.start.line - 1 {
|
||||
lines.next();
|
||||
}
|
||||
let line = lines.next().unwrap();
|
||||
writeln!(writer, "{:>width$} | {}", self.end.line, line)?;
|
||||
writeln!(
|
||||
writer,
|
||||
"{} | {}",
|
||||
" ".repeat(width),
|
||||
"^".repeat(self.end.col + 1)
|
||||
)?;
|
||||
}
|
||||
// for i in 0..AFTER {
|
||||
// if let Some(next) = lines.next() {
|
||||
// writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?;
|
||||
// }
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::ir::{FnID, SymbolSpace};
|
||||
use crate::ir::SymbolSpace;
|
||||
|
||||
use super::{IRLFunction, IRLInstruction, IRUInstruction, Len, Namespace, Symbol, VarID};
|
||||
use super::{IRLFunction, IRLInstruction, IRUInstruction, IRUProgram, Len, Symbol, Type, VarID};
|
||||
|
||||
pub struct IRLProgram {
|
||||
sym_space: SymbolSpace,
|
||||
@@ -12,110 +12,116 @@ pub struct IRLProgram {
|
||||
// NOTE: there are THREE places here where I specify size (8)
|
||||
|
||||
impl IRLProgram {
|
||||
pub fn create(ns: &Namespace) -> Option<Self> {
|
||||
pub fn create(p: &IRUProgram) -> Result<Self, String> {
|
||||
let mut start = None;
|
||||
for (i, f) in ns.iter_fns() {
|
||||
if f?.name == "start" {
|
||||
for (i, f) in p.iter_fns() {
|
||||
if f.name == "start" {
|
||||
start = Some(i);
|
||||
}
|
||||
}
|
||||
let start = start?;
|
||||
let start = start.ok_or("no start method found")?;
|
||||
let mut builder = SymbolSpace::with_entries(&[start]);
|
||||
let entry = builder.func(&start);
|
||||
while let Some((sym, i)) = builder.pop_fn() {
|
||||
let f = ns.fns[i.0].as_ref().unwrap();
|
||||
let f = p.fns[i.0].as_ref().unwrap();
|
||||
let mut instrs = Vec::new();
|
||||
let mut stack = HashMap::new();
|
||||
let mut makes_call = false;
|
||||
let mut alloc_stack = |i: &VarID| -> bool {
|
||||
let mut alloc_stack = |i: VarID| -> bool {
|
||||
let size = *stack
|
||||
.entry(*i)
|
||||
.or_insert(ns.size_of_var(i).expect("unsized type"));
|
||||
.entry(i)
|
||||
.or_insert(p.size_of_var(i).expect("unsized type"));
|
||||
size == 0
|
||||
};
|
||||
for i in &f.instructions {
|
||||
match i {
|
||||
match &i.i {
|
||||
IRUInstruction::Mv { dest, src } => {
|
||||
if alloc_stack(dest) {
|
||||
if alloc_stack(dest.id) {
|
||||
continue;
|
||||
}
|
||||
instrs.push(IRLInstruction::Mv {
|
||||
dest: *dest,
|
||||
src: *src,
|
||||
dest: dest.id,
|
||||
src: src.id,
|
||||
});
|
||||
}
|
||||
IRUInstruction::Ref { dest, src } => {
|
||||
if alloc_stack(dest) {
|
||||
if alloc_stack(dest.id) {
|
||||
continue;
|
||||
}
|
||||
instrs.push(IRLInstruction::Ref {
|
||||
dest: *dest,
|
||||
src: *src,
|
||||
dest: dest.id,
|
||||
src: src.id,
|
||||
});
|
||||
}
|
||||
IRUInstruction::LoadData { dest, src } => {
|
||||
if alloc_stack(dest) {
|
||||
if alloc_stack(dest.id) {
|
||||
continue;
|
||||
}
|
||||
let data = &ns.data[src.0];
|
||||
let data = &p.data[src.0];
|
||||
let sym = builder.ro_data(src, data);
|
||||
instrs.push(IRLInstruction::LoadData {
|
||||
dest: *dest,
|
||||
dest: dest.id,
|
||||
offset: 0,
|
||||
len: data.len() as Len,
|
||||
src: sym,
|
||||
});
|
||||
}
|
||||
IRUInstruction::LoadSlice { dest, src, len } => {
|
||||
if alloc_stack(dest) {
|
||||
IRUInstruction::LoadSlice { dest, src } => {
|
||||
if alloc_stack(dest.id) {
|
||||
continue;
|
||||
}
|
||||
let sym = builder.ro_data(src, &ns.data[src.0]);
|
||||
let data = &p.data[src.0];
|
||||
let def = p.get_data(*src);
|
||||
let Type::Array(ty, len) = &def.ty else {
|
||||
return Err(format!("tried to load {} as slice", p.type_name(&def.ty)));
|
||||
};
|
||||
let sym = builder.ro_data(src, data);
|
||||
instrs.push(IRLInstruction::LoadAddr {
|
||||
dest: *dest,
|
||||
dest: dest.id,
|
||||
offset: 0,
|
||||
src: sym,
|
||||
});
|
||||
|
||||
let sym = builder.anon_ro_data(&(*len as u64).to_le_bytes());
|
||||
instrs.push(IRLInstruction::LoadData {
|
||||
dest: *dest,
|
||||
dest: dest.id,
|
||||
offset: 8,
|
||||
len: 8,
|
||||
src: sym,
|
||||
});
|
||||
}
|
||||
IRUInstruction::LoadFn { dest, src } => {
|
||||
if alloc_stack(dest) {
|
||||
if alloc_stack(dest.id) {
|
||||
continue;
|
||||
}
|
||||
let sym = builder.func(src);
|
||||
instrs.push(IRLInstruction::LoadAddr {
|
||||
dest: *dest,
|
||||
dest: dest.id,
|
||||
offset: 0,
|
||||
src: sym,
|
||||
});
|
||||
}
|
||||
IRUInstruction::Call { dest, f, args } => {
|
||||
alloc_stack(dest);
|
||||
alloc_stack(dest.id);
|
||||
makes_call = true;
|
||||
let fid = &ns.fn_map[f];
|
||||
let fid = &p.fn_map[&f.id];
|
||||
let sym = builder.func(fid);
|
||||
instrs.push(IRLInstruction::Call {
|
||||
dest: *dest,
|
||||
dest: dest.id,
|
||||
f: sym,
|
||||
args: args
|
||||
.iter()
|
||||
.map(|a| (*a, ns.size_of_var(a).expect("unsized type")))
|
||||
.map(|a| (a.id, p.size_of_var(a.id).expect("unsized type")))
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
IRUInstruction::AsmBlock { instructions, args } => {
|
||||
instrs.push(IRLInstruction::AsmBlock {
|
||||
instructions: instructions.clone(),
|
||||
args: args.clone(),
|
||||
args: args.iter().cloned().map(|(r, v)| (r, v.id)).collect(),
|
||||
})
|
||||
}
|
||||
IRUInstruction::Ret { src } => instrs.push(IRLInstruction::Ret { src: *src }),
|
||||
IRUInstruction::Ret { src } => instrs.push(IRLInstruction::Ret { src: src.id }),
|
||||
};
|
||||
}
|
||||
builder.write_fn(
|
||||
@@ -127,7 +133,7 @@ impl IRLProgram {
|
||||
args: f
|
||||
.args
|
||||
.iter()
|
||||
.map(|a| (*a, ns.size_of_var(a).expect("unsized type")))
|
||||
.map(|a| (*a, p.size_of_var(*a).expect("unsized type")))
|
||||
.collect(),
|
||||
stack,
|
||||
},
|
||||
@@ -139,7 +145,7 @@ impl IRLProgram {
|
||||
// println!(" {:?}: {}", a, f.name);
|
||||
// }
|
||||
// println!("datas: {}", sym_space.ro_data().len());
|
||||
Some(Self { sym_space, entry })
|
||||
Ok(Self { sym_space, entry })
|
||||
}
|
||||
|
||||
pub fn entry(&self) -> Symbol {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
mod upper;
|
||||
mod file;
|
||||
mod lower;
|
||||
mod id;
|
||||
mod asm;
|
||||
@@ -7,5 +6,4 @@ pub mod arch;
|
||||
|
||||
pub use upper::*;
|
||||
pub use lower::*;
|
||||
pub use file::*;
|
||||
pub use id::*;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::{FileSpan, Type};
|
||||
use crate::common::FileSpan;
|
||||
|
||||
use super::Type;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -23,6 +25,12 @@ pub struct VarDef {
|
||||
pub origin: Origin,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DataDef {
|
||||
pub ty: Type,
|
||||
pub origin: Origin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Origin {
|
||||
Builtin,
|
||||
|
||||
19
src/ir/upper/error.rs
Normal file
19
src/ir/upper/error.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
||||
|
||||
use super::{IRUProgram, Type};
|
||||
|
||||
impl CompilerOutput {
|
||||
pub fn check_assign(&mut self, p: &IRUProgram, src: &Type, dest: &Type, span: FileSpan) {
|
||||
// TODO: spans
|
||||
if src != dest {
|
||||
self.err(CompilerMsg {
|
||||
msg: format!(
|
||||
"Cannot assign type '{}' to '{}'",
|
||||
p.type_name(src),
|
||||
p.type_name(dest)
|
||||
),
|
||||
spans: vec![span],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,51 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use super::{arch::riscv64::RV64Instruction, DataID, FnID, Len, VarID};
|
||||
use crate::{compiler::arch::riscv64::Reg, util::Padder};
|
||||
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, VarID};
|
||||
use crate::{common::FileSpan, compiler::arch::riscv64::Reg, util::Padder};
|
||||
|
||||
pub struct IRUFunction {
|
||||
pub name: String,
|
||||
pub args: Vec<VarID>,
|
||||
pub instructions: Vec<IRUInstruction>,
|
||||
pub instructions: Vec<IRUInstrInst>,
|
||||
}
|
||||
|
||||
pub enum IRUInstruction {
|
||||
Mv {
|
||||
dest: VarID,
|
||||
src: VarID,
|
||||
dest: VarInst,
|
||||
src: VarInst,
|
||||
},
|
||||
Ref {
|
||||
dest: VarID,
|
||||
src: VarID,
|
||||
dest: VarInst,
|
||||
src: VarInst,
|
||||
},
|
||||
LoadData {
|
||||
dest: VarID,
|
||||
dest: VarInst,
|
||||
src: DataID,
|
||||
},
|
||||
LoadSlice {
|
||||
dest: VarID,
|
||||
dest: VarInst,
|
||||
src: DataID,
|
||||
len: Len,
|
||||
},
|
||||
LoadFn {
|
||||
dest: VarID,
|
||||
dest: VarInst,
|
||||
src: FnID,
|
||||
},
|
||||
Call {
|
||||
dest: VarID,
|
||||
f: VarID,
|
||||
args: Vec<VarID>,
|
||||
dest: VarInst,
|
||||
f: VarInst,
|
||||
args: Vec<VarInst>,
|
||||
},
|
||||
AsmBlock {
|
||||
instructions: Vec<RV64Instruction>,
|
||||
args: Vec<(Reg, VarID)>,
|
||||
args: Vec<(Reg, VarInst)>,
|
||||
},
|
||||
Ret {
|
||||
src: VarID,
|
||||
src: VarInst,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct IRInstructions {
|
||||
vec: Vec<IRUInstruction>,
|
||||
vec: Vec<IRUInstrInst>,
|
||||
}
|
||||
|
||||
impl IRUFunction {
|
||||
@@ -63,8 +62,8 @@ impl IRInstructions {
|
||||
pub fn new() -> Self {
|
||||
Self { vec: Vec::new() }
|
||||
}
|
||||
pub fn push(&mut self, i: IRUInstruction) {
|
||||
self.vec.push(i);
|
||||
pub fn push(&mut self, i: IRUInstruction, span: FileSpan) {
|
||||
self.vec.push(IRUInstrInst { i, span });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +74,7 @@ impl std::fmt::Debug for IRUInstruction {
|
||||
Self::Ref { dest, src } => write!(f, "{dest:?} <- &{src:?}"),
|
||||
Self::LoadData { dest, src } => write!(f, "{dest:?} <- {src:?}"),
|
||||
Self::LoadFn { dest, src } => write!(f, "{dest:?} <- {src:?}"),
|
||||
Self::LoadSlice { dest, src, len } => write!(f, "{dest:?} <- &[{src:?}; {len}]"),
|
||||
Self::LoadSlice { dest, src } => write!(f, "{dest:?} <- &[{src:?}]"),
|
||||
Self::Call {
|
||||
dest,
|
||||
f: func,
|
||||
|
||||
27
src/ir/upper/inst.rs
Normal file
27
src/ir/upper/inst.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::{common::FileSpan, ir::VarID};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::IRUInstruction;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct VarInst {
|
||||
pub id: VarID,
|
||||
pub span: FileSpan,
|
||||
}
|
||||
|
||||
pub struct IRUInstrInst {
|
||||
pub i: IRUInstruction,
|
||||
pub span: FileSpan,
|
||||
}
|
||||
|
||||
impl Debug for VarInst {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for IRUInstrInst {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.i)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
mod def;
|
||||
mod func;
|
||||
mod ty;
|
||||
mod namespace;
|
||||
mod program;
|
||||
mod validate;
|
||||
mod error;
|
||||
mod inst;
|
||||
|
||||
use super::*;
|
||||
pub use def::*;
|
||||
pub use func::*;
|
||||
pub use ty::*;
|
||||
pub use namespace::*;
|
||||
pub use program::*;
|
||||
pub use inst::*;
|
||||
|
||||
@@ -4,12 +4,15 @@ use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::common::FileSpan;
|
||||
|
||||
pub struct Namespace {
|
||||
use super::{inst::VarInst, *};
|
||||
|
||||
pub struct IRUProgram {
|
||||
pub fn_defs: Vec<FnDef>,
|
||||
pub var_defs: Vec<VarDef>,
|
||||
pub type_defs: Vec<TypeDef>,
|
||||
pub data_defs: Vec<DataDef>,
|
||||
pub fns: Vec<Option<IRUFunction>>,
|
||||
pub data: Vec<Vec<u8>>,
|
||||
pub fn_map: HashMap<VarID, FnID>,
|
||||
@@ -17,12 +20,13 @@ pub struct Namespace {
|
||||
pub stack: Vec<HashMap<String, Idents>>,
|
||||
}
|
||||
|
||||
impl Namespace {
|
||||
impl IRUProgram {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fn_defs: Vec::new(),
|
||||
var_defs: Vec::new(),
|
||||
type_defs: Vec::new(),
|
||||
data_defs: Vec::new(),
|
||||
data: Vec::new(),
|
||||
fn_map: HashMap::new(),
|
||||
fns: Vec::new(),
|
||||
@@ -49,6 +53,9 @@ impl Namespace {
|
||||
pub fn get_fn(&self, id: FnID) -> &FnDef {
|
||||
&self.fn_defs[id.0]
|
||||
}
|
||||
pub fn get_data(&self, id: DataID) -> &DataDef {
|
||||
&self.data_defs[id.0]
|
||||
}
|
||||
pub fn get_fn_var(&self, id: VarID) -> Option<&FnDef> {
|
||||
Some(&self.fn_defs[self.fn_map.get(&id)?.0])
|
||||
}
|
||||
@@ -90,17 +97,20 @@ impl Namespace {
|
||||
Type::Unit => 0,
|
||||
})
|
||||
}
|
||||
pub fn size_of_var(&self, var: &VarID) -> Option<Size> {
|
||||
pub fn size_of_var(&self, var: VarID) -> Option<Size> {
|
||||
self.size_of_type(&self.var_defs[var.0].ty)
|
||||
}
|
||||
pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarID {
|
||||
pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarInst {
|
||||
let v = self.def_var(VarDef {
|
||||
name: format!("temp{}", self.temp),
|
||||
origin: super::Origin::File(origin),
|
||||
ty,
|
||||
});
|
||||
self.temp += 1;
|
||||
v
|
||||
VarInst {
|
||||
id: v,
|
||||
span: origin,
|
||||
}
|
||||
}
|
||||
pub fn def_fn(&mut self, def: FnDef) -> FnID {
|
||||
let i = self.fn_defs.len();
|
||||
@@ -128,8 +138,9 @@ impl Namespace {
|
||||
self.type_defs.push(def);
|
||||
id
|
||||
}
|
||||
pub fn def_data(&mut self, bytes: Vec<u8>) -> DataID {
|
||||
pub fn def_data(&mut self, def: DataDef, bytes: Vec<u8>) -> DataID {
|
||||
let i = self.data.len();
|
||||
self.data_defs.push(def);
|
||||
self.data.push(bytes);
|
||||
DataID(i)
|
||||
}
|
||||
@@ -187,18 +198,17 @@ impl Namespace {
|
||||
self.fns[id.0] = Some(f);
|
||||
}
|
||||
pub fn iter_vars(&self) -> impl Iterator<Item = (VarID, &VarDef)> {
|
||||
(0..self.var_defs.len())
|
||||
.map(|i| VarID(i))
|
||||
.zip(self.var_defs.iter())
|
||||
self.var_defs.iter().enumerate().map(|(i, v)| (VarID(i), v))
|
||||
}
|
||||
pub fn iter_fns(&self) -> impl Iterator<Item = (FnID, Option<&IRUFunction>)> {
|
||||
(0..self.fns.len())
|
||||
.map(|i| FnID(i))
|
||||
.zip(self.fns.iter().map(|f| f.as_ref()))
|
||||
pub fn iter_fns(&self) -> impl Iterator<Item = (FnID, &IRUFunction)> {
|
||||
self.fns
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, f)| Some((FnID(i), f.as_ref()?)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NamespaceGuard<'a>(&'a mut Namespace);
|
||||
pub struct NamespaceGuard<'a>(&'a mut IRUProgram);
|
||||
|
||||
impl Drop for NamespaceGuard<'_> {
|
||||
fn drop(&mut self) {
|
||||
@@ -207,7 +217,7 @@ impl Drop for NamespaceGuard<'_> {
|
||||
}
|
||||
|
||||
impl Deref for NamespaceGuard<'_> {
|
||||
type Target = Namespace;
|
||||
type Target = IRUProgram;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{Len, TypeID};
|
||||
use super::{IRUInstruction, IRUProgram, Len, TypeID};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Type {
|
||||
Concrete(TypeID),
|
||||
Bits(u32),
|
||||
@@ -25,3 +25,20 @@ impl Type {
|
||||
Self::Slice(Box::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_types(ns: &IRUProgram) {
|
||||
for (i, f) in ns.iter_fns() {
|
||||
for inst in &f.instructions {
|
||||
match &inst.i {
|
||||
IRUInstruction::Mv { dest, src } => todo!(),
|
||||
IRUInstruction::Ref { dest, src } => todo!(),
|
||||
IRUInstruction::LoadData { dest, src } => todo!(),
|
||||
IRUInstruction::LoadSlice { dest, src } => todo!(),
|
||||
IRUInstruction::LoadFn { dest, src } => todo!(),
|
||||
IRUInstruction::Call { dest, f, args } => todo!(),
|
||||
IRUInstruction::AsmBlock { instructions, args } => todo!(),
|
||||
IRUInstruction::Ret { src } => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
src/ir/upper/validate.rs
Normal file
52
src/ir/upper/validate.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// TODO: move this into ir, not parser
|
||||
use super::{IRUProgram, Type};
|
||||
use crate::common::CompilerOutput;
|
||||
|
||||
impl IRUProgram {
|
||||
pub fn validate(&self) -> CompilerOutput {
|
||||
let mut output = CompilerOutput::new();
|
||||
for f in self.fns.iter().flatten() {
|
||||
for i in &f.instructions {
|
||||
match &i.i {
|
||||
super::IRUInstruction::Mv { dest, src } => {
|
||||
let dest = self.get_var(dest.id);
|
||||
let src = self.get_var(src.id);
|
||||
output.check_assign(self, &src.ty, &dest.ty, i.span);
|
||||
}
|
||||
super::IRUInstruction::Ref { dest, src } => todo!(),
|
||||
super::IRUInstruction::LoadData { dest, src } => {
|
||||
let dest = self.get_var(dest.id);
|
||||
let src = self.get_data(*src);
|
||||
output.check_assign(self, &src.ty, &dest.ty, i.span);
|
||||
}
|
||||
super::IRUInstruction::LoadSlice { dest, src } => {
|
||||
let dest = self.get_var(dest.id);
|
||||
let src = self.get_data(*src);
|
||||
let Type::Array(srcty, ..) = &src.ty else {
|
||||
todo!()
|
||||
};
|
||||
output.check_assign(self, &Type::Slice(srcty.clone()), &dest.ty, i.span);
|
||||
}
|
||||
super::IRUInstruction::LoadFn { dest, src } => todo!(),
|
||||
super::IRUInstruction::Call { dest, f, args } => {
|
||||
let destty = &self.get_var(dest.id).ty;
|
||||
let f = self.get_var(f.id);
|
||||
let Type::Fn { args: argtys, ret } = &f.ty else {
|
||||
todo!()
|
||||
};
|
||||
output.check_assign(self, ret, destty, dest.span);
|
||||
for (argv, argt) in args.iter().zip(argtys) {
|
||||
let dest = self.get_var(argv.id);
|
||||
output.check_assign(self, argt, &dest.ty, argv.span);
|
||||
}
|
||||
}
|
||||
super::IRUInstruction::AsmBlock { instructions, args } => {
|
||||
// TODO
|
||||
}
|
||||
super::IRUInstruction::Ret { src } => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user