prepare for modules

This commit is contained in:
2025-04-25 04:16:54 -04:00
parent 0ceb82445e
commit 4e7c201690
30 changed files with 369 additions and 333 deletions
+5 -5
View File
@@ -159,7 +159,7 @@ impl RV64Instruction {
"remu" => op(ctx, op32m::REMU, op32m::FUNCT7)?,
w => {
ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w));
ctx.err_at(inst.op.origin, format!("Unknown instruction '{}'", w));
return None;
}
})
@@ -169,7 +169,7 @@ impl RV64Instruction {
pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<VarInst> {
let PAsmArg::Ref(node) = node.inner.as_ref()? else {
ctx.err_at(
node.span,
node.origin,
"Expected variable / function reference".to_string(),
);
return None;
@@ -194,7 +194,7 @@ impl Reg {
let s = &**node.inner.as_ref()?;
let res = Reg::from_str(s);
if res.is_none() {
ctx.err_at(node.span, format!("Unknown reg name '{}'", s));
ctx.err_at(node.origin, format!("Unknown reg name '{}'", s));
}
res
}
@@ -202,14 +202,14 @@ impl Reg {
fn i32_from_arg(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<i32> {
let PAsmArg::Value(node) = node.inner.as_ref()? else {
ctx.err_at(node.span, "Expected an i32, found reference".to_string());
ctx.err_at(node.origin, "Expected an i32, found reference".to_string());
return None;
};
let word = node.inner.as_ref()?;
match word.parse::<i32>() {
Ok(x) => Some(x),
Err(_) => {
ctx.err_at(node.span, format!("Expected an i64, found {}", word));
ctx.err_at(node.origin, format!("Expected an i64, found {}", word));
None
}
}
+47 -8
View File
@@ -1,4 +1,7 @@
use crate::ir::{Type, UInstruction, VarInst};
use crate::{
ir::{Type, UInstruction, VarInst},
parser::{PConstStatement, PStatementLike},
};
use super::{FnLowerCtx, FnLowerable, PBlock, PStatement};
@@ -6,12 +9,48 @@ impl FnLowerable for PBlock {
type Output = VarInst;
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
ctx.program.push();
for statement in &self.statements {
statement.lower(ctx);
let mut last = None;
let mut statements = Vec::new();
let mut fn_nodes = Vec::new();
let mut struct_nodes = Vec::new();
// first sort statements
for s in &self.statements {
let Some(s) = s.as_ref() else {
continue;
};
match s {
PStatementLike::Statement(s) => statements.push(s),
PStatementLike::Const(pconst_statement) => match pconst_statement {
PConstStatement::Fn(f) => fn_nodes.push(f),
PConstStatement::Struct(s) => struct_nodes.push(s),
},
}
}
// then lower const things
let mut structs = Vec::new();
for s in &struct_nodes {
structs.push(s.lower_name(ctx.program));
}
for (s, id) in struct_nodes.iter().zip(structs) {
if let Some(id) = id {
s.lower(id, ctx.program, ctx.output);
}
}
let mut fns = Vec::new();
for f in &fn_nodes {
fns.push(f.lower_name(ctx.program));
}
for (f, id) in fn_nodes.iter().zip(fns) {
if let Some(id) = id {
f.lower(id, ctx.program, ctx.output)
}
}
// then lower statements
for s in statements {
last = s.lower(ctx);
}
let res = self.result.as_ref().and_then(|r| r.lower(ctx));
ctx.program.pop();
res
last
}
}
@@ -19,7 +58,7 @@ impl FnLowerable for PStatement {
type Output = VarInst;
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
match self {
super::PStatement::Let(def, e) => {
PStatement::Let(def, e) => {
let def = def.lower(ctx.program, ctx.output)?;
let res = e.lower(ctx);
if let Some(res) = res {
@@ -30,7 +69,7 @@ impl FnLowerable for PStatement {
}
None
}
super::PStatement::Return(e) => {
PStatement::Return(e) => {
if let Some(e) = e {
let src = e.lower(ctx)?;
ctx.push_at(UInstruction::Ret { src }, src.span);
@@ -40,7 +79,7 @@ impl FnLowerable for PStatement {
}
None
}
super::PStatement::Expr(e) => e.lower(ctx),
PStatement::Expr(e) => e.lower(ctx),
}
}
}
+2 -2
View File
@@ -15,8 +15,8 @@ impl Node<PVarDef> {
None => Type::Infer,
};
Some(VarInst {
id: program.def_searchable(name, Some(UVar { ty, parent: None }), self.span),
span: self.span,
id: program.def_searchable(name, Some(UVar { ty, parent: None }), self.origin),
span: self.origin,
})
}
}
+29 -32
View File
@@ -10,29 +10,29 @@ impl FnLowerable for PExpr {
Some(match self {
PExpr::Lit(l) => match l.as_ref()? {
super::PLiteral::String(s) => {
let dest = ctx.program.temp_var(l.span, Type::Bits(8).slice());
let dest = ctx.program.temp_var(l.origin, Type::Bits(8).slice());
let data = s.as_bytes().to_vec();
let src = ctx.program.def(
format!("string \"{}\"", s.replace("\n", "\\n")),
&format!("string \"{}\"", s.replace("\n", "\\n")),
Some(UData {
ty: Type::Bits(8).arr(data.len() as u32),
content: data,
}),
l.span,
l.origin,
);
ctx.push(UInstruction::LoadSlice { dest, src });
dest
}
super::PLiteral::Char(c) => {
let ty = Type::Bits(8);
let dest = ctx.program.temp_var(l.span, ty.clone());
let dest = ctx.program.temp_var(l.origin, ty.clone());
let src = ctx.program.def(
format!("char '{c}'"),
&format!("char '{c}'"),
Some(UData {
ty,
content: c.to_string().as_bytes().to_vec(),
}),
l.span,
l.origin,
);
ctx.push(UInstruction::LoadData { dest, src });
dest
@@ -40,24 +40,30 @@ impl FnLowerable for PExpr {
super::PLiteral::Number(n) => {
// TODO: temp
let ty = Type::Bits(64);
let dest = ctx.program.temp_var(l.span, Type::Bits(64));
let dest = ctx.program.temp_var(l.origin, Type::Bits(64));
let src = ctx.program.def(
format!("num {n:?}"),
&format!("num {n:?}"),
Some(UData {
ty,
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
}),
l.span
l.origin,
);
ctx.push(UInstruction::LoadData { dest, src });
dest
}
super::PLiteral::Unit => ctx.program.temp_var(l.span, Type::Unit),
super::PLiteral::Unit => ctx.program.temp_var(l.origin, Type::Unit),
},
PExpr::Ident(i) => ctx.get_var(i)?,
PExpr::BinaryOp(op, e1, e2) => {
let res1 = e1.lower(ctx)?;
if *op == PInfixOp::Access {
PExpr::BinaryOp(op, e1, e2) => match op {
PInfixOp::Add => todo!(),
PInfixOp::Sub => todo!(),
PInfixOp::Mul => todo!(),
PInfixOp::Div => todo!(),
PInfixOp::LessThan => todo!(),
PInfixOp::GreaterThan => todo!(),
PInfixOp::Member => {
let res1 = e1.lower(ctx)?;
let Some(box PExpr::Ident(ident)) = &e2.inner else {
ctx.err("Field accessors must be identifiers".to_string());
return None;
@@ -70,26 +76,17 @@ impl FnLowerable for PExpr {
field: fname,
},
)
} else {
let res2 = e2.lower(ctx)?;
match op {
PInfixOp::Add => todo!(),
PInfixOp::Sub => todo!(),
PInfixOp::Mul => todo!(),
PInfixOp::Div => todo!(),
PInfixOp::LessThan => todo!(),
PInfixOp::GreaterThan => todo!(),
PInfixOp::Access => todo!(),
PInfixOp::Assign => {
ctx.push(UInstruction::Mv {
dest: res1,
src: res2,
});
res1
}
}
}
}
PInfixOp::Assign => {
let res1 = e1.lower(ctx)?;
let res2 = e2.lower(ctx)?;
ctx.push(UInstruction::Mv {
dest: res1,
src: res2,
});
res1
}
},
PExpr::UnaryOp(op, e) => {
let res = e.lower(ctx)?;
match op {
+11 -11
View File
@@ -19,7 +19,7 @@ impl PFunction {
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
let header = self.header.as_ref()?;
let name = header.name.as_ref()?;
let id = p.def_searchable(name.to_string(), None, self.header.span);
let id = p.def_searchable(name.to_string(), None, self.header.origin);
Some(id)
}
pub fn lower(&self, id: FnID, p: &mut UProgram, output: &mut CompilerOutput) {
@@ -42,7 +42,7 @@ impl PFunction {
instructions: Vec::new(),
program: p,
output,
span: self.body.span,
origin: self.body.origin,
};
if let Some(src) = self.body.lower(&mut ctx) {
ctx.instructions.push(UInstrInst {
@@ -65,7 +65,7 @@ pub struct FnLowerCtx<'a> {
pub program: &'a mut UProgram,
pub instructions: Vec<UInstrInst>,
pub output: &'a mut CompilerOutput,
pub span: FileSpan,
pub origin: FileSpan,
}
impl FnLowerCtx<'_> {
@@ -73,7 +73,7 @@ impl FnLowerCtx<'_> {
let name = node.inner.as_ref()?;
let res = self.program.get_idents(name);
if res.is_none() {
self.err_at(node.span, format!("Identifier '{}' not found", name));
self.err_at(node.origin, format!("Identifier '{}' not found", name));
}
res
}
@@ -81,29 +81,29 @@ impl FnLowerCtx<'_> {
let ids = self.get_idents(node)?;
if ids.get::<UVar>().is_none() {
self.err_at(
node.span,
node.origin,
format!("Variable '{}' not found", node.inner.as_ref()?),
);
}
ids.get::<UVar>().map(|id| VarInst {
id,
span: node.span,
span: node.origin,
})
}
pub fn err(&mut self, msg: String) {
self.output.err(CompilerMsg::from_span(self.span, msg))
self.output.err(CompilerMsg::from_span(self.origin, msg))
}
pub fn err_at(&mut self, span: FileSpan, msg: String) {
self.output.err(CompilerMsg::from_span(span, msg))
}
pub fn temp(&mut self, ty: Type) -> VarInst {
self.program.temp_var(self.span, ty)
self.program.temp_var(self.origin, ty)
}
pub fn temp_subvar(&mut self, ty: Type, parent: FieldRef) -> VarInst {
self.program.temp_subvar(self.span, ty, parent)
self.program.temp_subvar(self.origin, ty, parent)
}
pub fn push(&mut self, i: UInstruction) {
self.push_at(i, self.span);
self.push_at(i, self.origin);
}
pub fn push_at(&mut self, i: UInstruction, span: FileSpan) {
self.instructions.push(UInstrInst { i, span });
@@ -113,7 +113,7 @@ impl FnLowerCtx<'_> {
program: self.program,
instructions: Vec::new(),
output: self.output,
span: self.span,
origin: self.origin,
}
}
}
+27 -4
View File
@@ -4,11 +4,34 @@ mod block;
mod def;
mod expr;
mod func;
mod module;
mod struc;
mod ty;
use super::*;
use crate::ir::{Type, UFunc, UProgram};
impl PModule {
pub fn lower(&self, name: String, p: &mut UProgram, output: &mut CompilerOutput) {
let id = p.def_searchable(name.clone(), None, self.block.origin);
p.push_name(&name);
let mut fctx = FnLowerCtx {
program: p,
instructions: Vec::new(),
output,
origin: self.block.origin,
};
self.block.lower(&mut fctx);
let f = UFunc {
args: Vec::new(),
instructions: fctx.instructions,
ret: Type::Unit,
};
let ty = f.ty(p);
p.write(id, f);
p.pop_name();
p.expect_mut(p.fn_var.var(id)).ty = ty;
}
}
pub use func::FnLowerCtx;
@@ -20,10 +43,10 @@ pub trait FnLowerable {
impl<T: FnLowerable> FnLowerable for Node<T> {
type Output = T::Output;
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
let old_span = ctx.span;
ctx.span = self.span;
let old_span = ctx.origin;
ctx.origin = self.origin;
let res = self.as_ref()?.lower(ctx);
ctx.span = old_span;
ctx.origin = old_span;
res
}
}
-26
View File
@@ -1,26 +0,0 @@
use crate::ir::UProgram;
use super::{CompilerOutput, PModule};
impl PModule {
pub fn lower(&self, p: &mut UProgram, output: &mut CompilerOutput) {
let mut structs = Vec::new();
for s in &self.structs {
structs.push(s.lower_name(p));
}
for (s, id) in self.structs.iter().zip(structs) {
if let Some(id) = id {
s.lower(id, p, output);
}
}
let mut fns = Vec::new();
for f in &self.functions {
fns.push(f.lower_name(p));
}
for (f, id) in self.functions.iter().zip(fns) {
if let Some(id) = id {
f.lower(id, p, output)
}
}
}
}
+2 -2
View File
@@ -85,10 +85,10 @@ impl Node<PStruct> {
pub fn lower_name(&self, p: &mut UProgram) -> Option<StructID> {
let s = self.as_ref()?;
let name = s.name.as_ref()?.to_string();
let id = p.def_searchable(name.to_string(), None, s.name.span);
let id = p.def_searchable(name.to_string(), None, s.name.origin);
Some(id)
}
pub fn lower(&self, id: StructID, p: &mut UProgram, output: &mut CompilerOutput) {
self.as_ref().map(|i| i.lower(id, p, output, self.span));
self.as_ref().map(|i| i.lower(id, p, output, self.origin));
}
}
+2 -2
View File
@@ -8,7 +8,7 @@ use super::{CompilerMsg, CompilerOutput, FileSpan, Node, PType};
impl Node<PType> {
pub fn lower(&self, namespace: &mut UProgram, output: &mut CompilerOutput) -> Type {
self.as_ref()
.map(|t| t.lower(namespace, output, self.span))
.map(|t| t.lower(namespace, output, self.origin))
.unwrap_or(Type::Error)
}
}
@@ -47,6 +47,6 @@ impl Node<PGenericDef> {
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
let s = self.as_ref()?;
let name = s.name.as_ref()?;
Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.span))
Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.origin))
}
}