prepare for modules
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user