trudging through the snow
This commit is contained in:
@@ -12,7 +12,7 @@ impl RV64Instruction {
|
||||
let args = &inst.args[..];
|
||||
let opstr = &**inst.op.inner.as_ref()?;
|
||||
// TODO: surely this can be abstracted...
|
||||
let opi = |ctx: &mut FnLowerCtx<'_>, op: Funct3| -> Option<Self> {
|
||||
let opi = |ctx: &mut FnLowerCtx<'_, '_, '_>, op: Funct3| -> Option<Self> {
|
||||
let [dest, src, imm] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -22,7 +22,7 @@ impl RV64Instruction {
|
||||
let imm = i32_from_arg(imm, ctx)?;
|
||||
Some(Self::OpImm { op, dest, src, imm })
|
||||
};
|
||||
let op = |ctx: &mut FnLowerCtx<'_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let op = |ctx: &mut FnLowerCtx<'_, '_, '_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let [dest, src1, src2] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -174,7 +174,7 @@ pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<UIdent>
|
||||
);
|
||||
return None;
|
||||
};
|
||||
ctx.var(node)
|
||||
ctx.ident(node)
|
||||
}
|
||||
|
||||
impl RegRef {
|
||||
@@ -184,7 +184,7 @@ impl RegRef {
|
||||
let reg = Reg::from_ident(node, ctx)?;
|
||||
Self::Reg(reg)
|
||||
}
|
||||
PAsmArg::Ref(node) => Self::Var(ctx.var(node)?),
|
||||
PAsmArg::Ref(node) => Self::Var(ctx.ident(node)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::{
|
||||
compiler::arch::riscv::Reg,
|
||||
ir::{
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, UIdent,
|
||||
IdentID,
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, IdentID, Type, UInstruction,
|
||||
},
|
||||
parser::PAsmBlockArg,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
ir::{Type, UInstruction, UVar, UIdent, IdentID},
|
||||
ir::{IdentID, Type, UIdent, UInstruction, UVar},
|
||||
parser::{PConstStatement, PStatementLike},
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ use super::{FnLowerCtx, FnLowerable, Import, PBlock, PStatement};
|
||||
impl FnLowerable for PBlock {
|
||||
type Output = IdentID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<IdentID> {
|
||||
ctx.ident_stack.push();
|
||||
let mut last = None;
|
||||
let mut statements = Vec::new();
|
||||
let mut fn_nodes = Vec::new();
|
||||
@@ -27,64 +28,58 @@ impl FnLowerable for PBlock {
|
||||
},
|
||||
}
|
||||
}
|
||||
ctx.b.push();
|
||||
// then lower imports
|
||||
for i_n in &import_nodes {
|
||||
if let Some(i) = i_n.as_ref() {
|
||||
let name = &i.0;
|
||||
let path = ctx.b.path_for(name);
|
||||
let path = ctx.path_for(name);
|
||||
let import = Import(path.clone());
|
||||
if ctx.imports.insert(import) {
|
||||
ctx.b.def_searchable::<UVar>(
|
||||
name,
|
||||
Some(UVar {
|
||||
ty: Type::Module(path),
|
||||
}),
|
||||
i_n.origin,
|
||||
);
|
||||
ctx.def_var(UVar {
|
||||
name: name.clone(),
|
||||
ty: Type::Module(path),
|
||||
origin: i_n.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// then lower const things
|
||||
let mut structs = Vec::new();
|
||||
for s in &struct_nodes {
|
||||
structs.push(s.lower_name(ctx.b));
|
||||
structs.push(s.lower(ctx.ctx));
|
||||
}
|
||||
for (s, id) in struct_nodes.iter().zip(structs) {
|
||||
if let Some(id) = id {
|
||||
s.lower(id, ctx.b, ctx.output);
|
||||
s.lower(ctx.ctx);
|
||||
}
|
||||
}
|
||||
let mut fns = Vec::new();
|
||||
for f in &fn_nodes {
|
||||
fns.push(f.lower_name(ctx.b));
|
||||
fns.push(f.lower(ctx.ctx));
|
||||
}
|
||||
for (f, id) in fn_nodes.iter().zip(fns) {
|
||||
if let Some(id) = id {
|
||||
f.lower(id, ctx.b, ctx.imports, ctx.output)
|
||||
f.lower(ctx.ctx);
|
||||
}
|
||||
}
|
||||
// then lower statements
|
||||
for s in statements {
|
||||
last = s.lower(ctx);
|
||||
}
|
||||
ctx.b.pop();
|
||||
ctx.ident_stack.pop();
|
||||
last
|
||||
}
|
||||
}
|
||||
|
||||
impl FnLowerable for PStatement {
|
||||
type Output = UIdent;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<UIdent> {
|
||||
type Output = IdentID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<IdentID> {
|
||||
match self {
|
||||
PStatement::Let(def, e) => {
|
||||
let def = def.lower(ctx.b, ctx.output)?;
|
||||
let def = def.lower(ctx.ctx)?;
|
||||
let res = e.lower(ctx);
|
||||
if let Some(res) = res {
|
||||
ctx.push(UInstruction::Mv {
|
||||
dst: def,
|
||||
src: res,
|
||||
});
|
||||
ctx.push(UInstruction::Mv { dst: def, src: res });
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
use crate::ir::{UProgram, UVar, VarID, UIdent};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{CompilerOutput, Node, PVarDef};
|
||||
use crate::ir::{UVar, VarID};
|
||||
|
||||
use super::{ModuleLowerCtx, Node, PVarDef};
|
||||
|
||||
impl Node<PVarDef> {
|
||||
pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option<VarID> {
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx) -> Option<VarID> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref().map_or("{error}", |v| v);
|
||||
let name = s.name.as_ref().map_or("{error}", |v| v).to_string();
|
||||
let ty = match &s.ty {
|
||||
Some(ty) => ty.lower(program, output),
|
||||
None => program.infer(self.origin),
|
||||
Some(ty) => ty.lower(ctx),
|
||||
None => ctx.infer(),
|
||||
};
|
||||
Some(UIdent {
|
||||
id: program.def_searchable(name, Some(UVar { ty }), self.origin),
|
||||
Some(ctx.def_var(UVar {
|
||||
name,
|
||||
ty,
|
||||
origin: self.origin,
|
||||
})
|
||||
parent: None,
|
||||
children: HashMap::new(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
+73
-25
@@ -1,6 +1,6 @@
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, PostfixOp};
|
||||
use crate::{
|
||||
ir::{Type, UData, UInstruction, UIdent, IdentID},
|
||||
ir::{IdentID, IdentStatus, MemRes, Member, MemberID, MemberIdent, Type, UData, UInstruction},
|
||||
parser::InfixOp,
|
||||
};
|
||||
|
||||
@@ -9,22 +9,49 @@ impl FnLowerable for PExpr {
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<IdentID> {
|
||||
let mut e = self;
|
||||
let mut path = Vec::new();
|
||||
while let PExpr::Member(node, ident) = e {
|
||||
e = if let Some(t) = node.as_ref() {
|
||||
path.push(ident);
|
||||
&**t
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let mut gargs = None;
|
||||
loop {
|
||||
match e {
|
||||
PExpr::Member(node, ty, ident) => {
|
||||
e = if let Some(t) = node.as_ref() {
|
||||
ctx.origin = node.origin;
|
||||
path.push((ty, ident, gargs.unwrap_or_default()));
|
||||
&**t
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
PExpr::Generic(node, nodes) => match gargs {
|
||||
None => gargs = Some(nodes.iter().map(|t| t.lower(ctx)).collect::<Vec<_>>()),
|
||||
Some(_) => {
|
||||
// this should cover the more specific area of ::<...>
|
||||
// but too lazy rn
|
||||
ctx.err("Cannot specify generics here".to_string());
|
||||
return None;
|
||||
}
|
||||
},
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
while let PExpr::Member(node, ty, ident) = e {}
|
||||
if path.len() > 0 {
|
||||
// UIdent {
|
||||
// origin: ctx.origin,
|
||||
// status: IdentStatus::Unres { base: (), path: () },
|
||||
// }
|
||||
}
|
||||
let origin = ctx.origin;
|
||||
Some(match e {
|
||||
PExpr::Lit(l) => match l {
|
||||
super::PLiteral::String(s) => {
|
||||
let dst = ctx.temp_var(ctx.origin, Type::Bits(8).slice(ctx.p));
|
||||
let sty = Type::Bits(8).slice(ctx.p);
|
||||
let dst = ctx.temp_var(origin, sty);
|
||||
let data = s.as_bytes().to_vec();
|
||||
let dty = Type::Bits(8).arr(ctx.ctx.p, data.len() as u32);
|
||||
let dty = ctx.def_ty(dty);
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||
ty: ctx.def_ty(Type::Bits(8).arr(ctx.b.p, data.len() as u32)),
|
||||
ty: dty,
|
||||
content: data,
|
||||
});
|
||||
ctx.push(UInstruction::LoadSlice { dst, src });
|
||||
@@ -32,7 +59,7 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
super::PLiteral::Char(c) => {
|
||||
let ty = ctx.def_ty(Type::Bits(8));
|
||||
let dst = ctx.temp_var(ctx.origin, ty.clone());
|
||||
let dst = ctx.temp_var(origin, ty.clone());
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("char '{c}'"),
|
||||
ty,
|
||||
@@ -44,7 +71,7 @@ impl FnLowerable for PExpr {
|
||||
super::PLiteral::Number(n) => {
|
||||
// TODO: temp
|
||||
let ty = ctx.def_ty(Type::Bits(64));
|
||||
let dst = ctx.temp_var(ctx.origin, ty.clone());
|
||||
let dst = ctx.temp_var(origin, ty.clone());
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("num {n:?}"),
|
||||
ty,
|
||||
@@ -53,9 +80,9 @@ impl FnLowerable for PExpr {
|
||||
ctx.push(UInstruction::LoadData { dst, src });
|
||||
dst
|
||||
}
|
||||
super::PLiteral::Unit => ctx.temp_var(ctx.origin, Type::Unit),
|
||||
super::PLiteral::Unit => ctx.temp_var(origin, Type::Unit),
|
||||
},
|
||||
PExpr::Ident(i) => ctx.var(i),
|
||||
PExpr::Ident(i) => ctx.ident(i),
|
||||
PExpr::BinaryOp(op, e1, e2) => match op {
|
||||
InfixOp::Add => todo!(),
|
||||
InfixOp::Sub => todo!(),
|
||||
@@ -77,7 +104,7 @@ impl FnLowerable for PExpr {
|
||||
let res = e.lower(ctx)?;
|
||||
match op {
|
||||
PostfixOp::Ref => {
|
||||
let ty = Type::Ref(ctx.b.infer());
|
||||
let ty = Type::Ref(ctx.ctx.infer());
|
||||
let dest = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Ref {
|
||||
dst: dest,
|
||||
@@ -86,7 +113,7 @@ impl FnLowerable for PExpr {
|
||||
dest
|
||||
}
|
||||
PostfixOp::Deref => {
|
||||
let ty = Type::Deref(ctx.b.infer());
|
||||
let ty = Type::Deref(ctx.ctx.infer());
|
||||
let dst = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Deref { dst, src: res });
|
||||
dst
|
||||
@@ -121,20 +148,20 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
PExpr::If(cond, body) => {
|
||||
let cond = cond.lower(ctx)?;
|
||||
ctx.var_stack.push();
|
||||
ctx.ident_stack.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.var_stack.pop();
|
||||
ctx.ident_stack.pop();
|
||||
ctx.push(UInstruction::If { cond, body });
|
||||
return None;
|
||||
}
|
||||
PExpr::Loop(body) => {
|
||||
ctx.var_stack.push();
|
||||
ctx.ident_stack.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.var_stack.pop();
|
||||
ctx.ident_stack.pop();
|
||||
ctx.push(UInstruction::Loop { body });
|
||||
return None;
|
||||
}
|
||||
@@ -146,13 +173,34 @@ impl FnLowerable for PExpr {
|
||||
ctx.push(UInstruction::Continue);
|
||||
return None;
|
||||
}
|
||||
PExpr::Member(e, name) => {
|
||||
ctx.err("Can't access a member here".to_string());
|
||||
PExpr::Member(e, ty, name) => {
|
||||
let id = e.lower(ctx)?;
|
||||
let name_str = name.as_ref()?.0;
|
||||
let cur = &mut ctx.p.idents[id];
|
||||
match cur.status {
|
||||
IdentStatus::Res(res) => {
|
||||
cur.status = IdentStatus::Unres {
|
||||
base: MemRes {
|
||||
mem: Member {
|
||||
id: MemberID
|
||||
},
|
||||
origin: (),
|
||||
gargs: (),
|
||||
},
|
||||
path: (),
|
||||
}
|
||||
}
|
||||
IdentStatus::Unres { base, path } => path.push(MemberIdent {
|
||||
ty: *ty,
|
||||
name: name_str,
|
||||
origin: name.origin,
|
||||
gargs: Vec::new(),
|
||||
}),
|
||||
IdentStatus::Failed(res_err) => return None,
|
||||
IdentStatus::Cooked => return None,
|
||||
}
|
||||
return None;
|
||||
}
|
||||
PExpr::Field(e, name) => {
|
||||
todo!()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+82
-66
@@ -1,74 +1,68 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
|
||||
use super::{CompilerMsg, FileSpan, ModuleLowerCtx, Node, PFunction, Typable};
|
||||
use crate::{
|
||||
ir::{
|
||||
FnID, GenericID, ModPath, Origin, Typable, Type, UFunc, UInstrInst, UInstruction,
|
||||
UModuleBuilder, VarID, UIdent, IdentID, IdentStatus,
|
||||
FnID, IdentID, IdentStatus, MemRes, Member, MemberID, MemberIdent, MemberPath, MemberTy,
|
||||
Origin, Res, Type, UFunc, UIdent, UInstrInst, UInstruction,
|
||||
},
|
||||
parser,
|
||||
util::NameStack,
|
||||
};
|
||||
|
||||
impl Node<PFunction> {
|
||||
pub fn lower(
|
||||
&self,
|
||||
b: &mut UModuleBuilder,
|
||||
imports: &mut Imports,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<FnID> {
|
||||
self.as_ref()
|
||||
.map(|s| s.lower(b, imports, output, self.origin))
|
||||
.flatten()
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx) -> Option<FnID> {
|
||||
self.as_ref().map(|s| s.lower(ctx, self.origin)).flatten()
|
||||
}
|
||||
}
|
||||
|
||||
impl PFunction {
|
||||
pub fn lower(
|
||||
&self,
|
||||
b: &mut UModuleBuilder,
|
||||
imports: &mut Imports,
|
||||
output: &mut CompilerOutput,
|
||||
origin: Origin,
|
||||
) -> Option<FnID> {
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx, origin: Origin) -> Option<FnID> {
|
||||
let header = self.header.as_ref()?;
|
||||
let name = header.name.as_ref()?.0.clone();
|
||||
let (generics, args, ret) = if let Some(header) = self.header.as_ref() {
|
||||
(
|
||||
header.gargs.iter().flat_map(|a| a.lower(b)).collect(),
|
||||
header
|
||||
.gargs
|
||||
.iter()
|
||||
.flat_map(|a| a.lower(ctx).map(|g| (g.0, g.1, a.origin)))
|
||||
.collect(),
|
||||
header
|
||||
.args
|
||||
.iter()
|
||||
.flat_map(|a| Some(a.lower(b, output)?))
|
||||
.flat_map(|a| Some(a.lower(ctx)?))
|
||||
.collect(),
|
||||
match &header.ret {
|
||||
Some(ty) => ty.lower(b, output),
|
||||
None => b.def_ty(Type::Unit),
|
||||
Some(ty) => ty.lower(ctx),
|
||||
None => ctx.def_ty(Type::Unit),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(Vec::new(), Vec::new(), b.tc.error)
|
||||
(Vec::new(), Vec::new(), ctx.tc.error)
|
||||
};
|
||||
let gargs = generics.iter().map(|g| g.1).collect();
|
||||
let generics = generics.into_iter().collect();
|
||||
let generics = generics
|
||||
.into_iter()
|
||||
.map(|g| {
|
||||
(
|
||||
g.0,
|
||||
ctx.def_ident(UIdent {
|
||||
status: IdentStatus::Res(Res::Generic(g.1)),
|
||||
origin: g.2,
|
||||
}),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
ctx.ident_stack.extend(generics.into_iter());
|
||||
let instructions = {
|
||||
let mut var_stack = NameStack::new();
|
||||
let mut ctx = FnLowerCtx {
|
||||
let mut fctx = FnLowerCtx {
|
||||
instructions: Vec::new(),
|
||||
var_stack: &mut var_stack,
|
||||
b,
|
||||
output,
|
||||
ctx,
|
||||
origin: self.body.origin,
|
||||
generics: &generics,
|
||||
imports,
|
||||
};
|
||||
let res = self.body.lower(&mut ctx);
|
||||
let mut instructions = ctx.instructions;
|
||||
let res = self.body.lower(&mut fctx);
|
||||
let mut instructions = fctx.instructions;
|
||||
if let Some(src) = res {
|
||||
let origin = b.idents[src].origin;
|
||||
let origin = ctx.idents[src].origin;
|
||||
instructions.push(UInstrInst {
|
||||
origin,
|
||||
i: UInstruction::Ret { src },
|
||||
@@ -84,35 +78,37 @@ impl PFunction {
|
||||
ret,
|
||||
instructions,
|
||||
};
|
||||
Some(b.def_fn(f))
|
||||
Some(ctx.def_fn(f))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnLowerCtx<'a, 'b> {
|
||||
pub b: &'a mut UModuleBuilder<'b>,
|
||||
pub ctx: &'a mut ModuleLowerCtx<'b>,
|
||||
pub instructions: Vec<UInstrInst>,
|
||||
pub output: &'a mut CompilerOutput,
|
||||
pub origin: FileSpan,
|
||||
pub imports: &'a mut Imports,
|
||||
pub var_stack: &'a mut NameStack<VarID>,
|
||||
pub generics: &'a HashMap<String, GenericID>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
pub fn var(&mut self, node: &Node<parser::PIdent>) -> IdentID {
|
||||
pub fn ident(&mut self, node: &Node<parser::PIdent>) -> IdentID {
|
||||
let inst = UIdent {
|
||||
status: if let Some(n) = node.as_ref() {
|
||||
if let Some(&var) = self.var_stack.search(&n.0) {
|
||||
IdentStatus::Var(var)
|
||||
if let Some(&res) = self.ident_stack.search(&n.0) {
|
||||
return res;
|
||||
} else {
|
||||
IdentStatus::Unres {
|
||||
path: ModPath {
|
||||
id: self.b.module,
|
||||
path: Vec::new(),
|
||||
path: vec![MemberIdent {
|
||||
ty: MemberTy::Member,
|
||||
name: n.0.clone(),
|
||||
origin: node.origin,
|
||||
gargs: Vec::new(),
|
||||
}],
|
||||
base: MemRes {
|
||||
mem: Member {
|
||||
id: MemberID::Module(self.module),
|
||||
},
|
||||
origin: self.origin,
|
||||
gargs: Vec::new(),
|
||||
},
|
||||
name: n.0.clone(),
|
||||
gargs: Vec::new(),
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -120,16 +116,17 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
},
|
||||
origin: node.origin,
|
||||
};
|
||||
self.def_var_inst(inst)
|
||||
self.def_ident(inst)
|
||||
}
|
||||
pub fn err(&mut self, msg: String) {
|
||||
self.output.err(CompilerMsg::new(msg, self.origin))
|
||||
let origin = self.origin;
|
||||
self.output.err(CompilerMsg::new(msg, origin))
|
||||
}
|
||||
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
||||
self.output.err(CompilerMsg::new(msg, span))
|
||||
}
|
||||
pub fn temp<T: Typable>(&mut self, ty: T) -> IdentID {
|
||||
self.b.temp_var(self.origin, ty)
|
||||
self.ctx.temp_var(self.origin, ty)
|
||||
}
|
||||
pub fn push(&mut self, i: UInstruction) {
|
||||
self.push_at(i, self.origin);
|
||||
@@ -139,27 +136,46 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
}
|
||||
pub fn branch<'c>(&'c mut self) -> FnLowerCtx<'c, 'b> {
|
||||
FnLowerCtx {
|
||||
b: self.b,
|
||||
ctx: self.ctx,
|
||||
instructions: Vec::new(),
|
||||
generics: self.generics,
|
||||
var_stack: self.var_stack,
|
||||
output: self.output,
|
||||
origin: self.origin,
|
||||
imports: self.imports,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> Deref for FnLowerCtx<'_, 'b> {
|
||||
type Target = UModuleBuilder<'b>;
|
||||
type Target = ModuleLowerCtx<'b>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.b
|
||||
self.ctx
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for FnLowerCtx<'_, '_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.b
|
||||
self.ctx
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FnLowerable {
|
||||
type Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output>;
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Node<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
let old_span = ctx.origin;
|
||||
ctx.origin = self.origin;
|
||||
let res = self.as_ref()?.lower(ctx);
|
||||
ctx.origin = old_span;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Box<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
self.as_ref().lower(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
+101
-35
@@ -4,65 +4,131 @@ mod block;
|
||||
mod def;
|
||||
mod expr;
|
||||
mod func;
|
||||
mod map;
|
||||
mod struc;
|
||||
mod ty;
|
||||
mod map;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::ir::{Type, UFunc, UModuleBuilder};
|
||||
use crate::{
|
||||
ir::{
|
||||
IdentID, IdentStatus, ModID, Origin, Res, Type, TypeID, UFunc, UIdent, UModule, UProgram,
|
||||
UVar,
|
||||
},
|
||||
util::NameStack,
|
||||
};
|
||||
pub use func::{FnLowerCtx, FnLowerable};
|
||||
|
||||
impl PModule {
|
||||
pub fn lower(
|
||||
&self,
|
||||
path: Vec<String>,
|
||||
p: &mut UModuleBuilder,
|
||||
p: &mut UProgram,
|
||||
imports: &mut Imports,
|
||||
output: &mut CompilerOutput,
|
||||
) {
|
||||
) -> ModID {
|
||||
let name = path.last().unwrap().clone();
|
||||
p.set_module(path);
|
||||
let fid = p.def_searchable(&name, None, self.block.origin);
|
||||
p.push_name(&name);
|
||||
let mut fctx = FnLowerCtx {
|
||||
b: p,
|
||||
let f = UFunc {
|
||||
name: name.clone(),
|
||||
args: Vec::new(),
|
||||
instructions: Vec::new(),
|
||||
gargs: Vec::new(),
|
||||
ret: p.def_ty(Type::Unit),
|
||||
origin: self.block.origin,
|
||||
};
|
||||
let fid = p.def_fn(f);
|
||||
let mid = p.def_module(UModule {
|
||||
name,
|
||||
members: HashMap::new(),
|
||||
parent: None,
|
||||
func: fid,
|
||||
});
|
||||
let mut ctx = ModuleLowerCtx {
|
||||
p,
|
||||
output,
|
||||
module: mid,
|
||||
temp: 0,
|
||||
ident_stack: NameStack::new(),
|
||||
};
|
||||
let mut fctx = FnLowerCtx {
|
||||
ctx: &mut ctx,
|
||||
instructions: Vec::new(),
|
||||
output,
|
||||
origin: self.block.origin,
|
||||
imports,
|
||||
};
|
||||
self.block.lower(&mut fctx);
|
||||
let f = UFunc {
|
||||
args: Vec::new(),
|
||||
instructions: fctx.instructions,
|
||||
ret: Type::Unit,
|
||||
p.fns[fid].instructions = fctx.instructions;
|
||||
mid
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleLowerCtx<'a> {
|
||||
pub p: &'a mut UProgram,
|
||||
pub output: &'a mut CompilerOutput,
|
||||
pub module: ModID,
|
||||
pub temp: usize,
|
||||
pub ident_stack: NameStack<IdentID>,
|
||||
}
|
||||
|
||||
impl<'a> ModuleLowerCtx<'a> {
|
||||
pub fn new(program: &'a mut UProgram, output: &'a mut CompilerOutput, id: ModID) -> Self {
|
||||
Self {
|
||||
p: program,
|
||||
output,
|
||||
module: id,
|
||||
temp: 0,
|
||||
ident_stack: NameStack::new(),
|
||||
}
|
||||
}
|
||||
pub fn temp_var(&mut self, origin: Origin, ty: impl Typable) -> IdentID {
|
||||
self.temp_var_inner(origin, ty)
|
||||
}
|
||||
fn temp_var_inner(&mut self, origin: Origin, ty: impl Typable) -> IdentID {
|
||||
let var = UVar {
|
||||
name: format!("temp{}", self.temp),
|
||||
ty: ty.ty(self),
|
||||
origin,
|
||||
parent: None,
|
||||
children: HashMap::new(),
|
||||
};
|
||||
p.write(fid, f);
|
||||
p.pop_name();
|
||||
let id = self.p.def_var(var);
|
||||
self.temp += 1;
|
||||
self.def_ident(UIdent {
|
||||
status: IdentStatus::Res(Res::Var(id)),
|
||||
origin,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub use func::FnLowerCtx;
|
||||
use import::Imports;
|
||||
|
||||
pub trait FnLowerable {
|
||||
type Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output>;
|
||||
pub trait Typable {
|
||||
fn ty(self, p: &mut UProgram) -> TypeID;
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Node<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
let old_span = ctx.origin;
|
||||
ctx.origin = self.origin;
|
||||
let res = self.as_ref()?.lower(ctx);
|
||||
ctx.origin = old_span;
|
||||
res
|
||||
impl Typable for Type {
|
||||
fn ty(self, p: &mut UProgram) -> TypeID {
|
||||
p.def_ty(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FnLowerable> FnLowerable for Box<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
self.as_ref().lower(ctx)
|
||||
impl Typable for TypeID {
|
||||
fn ty(self, p: &mut UProgram) -> TypeID {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ModuleLowerCtx<'_> {
|
||||
type Target = UProgram;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.p
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ModuleLowerCtx<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.p
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use crate::{
|
||||
common::{CompilerOutput, FileSpan},
|
||||
ir::{StructField, StructID, UModuleBuilder, UProgram, UStruct},
|
||||
parser::{Node, PStruct, PStructFields},
|
||||
common::FileSpan,
|
||||
ir::{StructField, StructID, UStruct},
|
||||
parser::{PStruct, PStructFields},
|
||||
};
|
||||
|
||||
use super::ModuleLowerCtx;
|
||||
|
||||
impl PStruct {
|
||||
pub fn lower(
|
||||
&self,
|
||||
id: StructID,
|
||||
b: &mut UModuleBuilder,
|
||||
output: &mut CompilerOutput,
|
||||
span: FileSpan,
|
||||
) -> Option<()> {
|
||||
let generics = self.generics.iter().flat_map(|a| a.lower(b)).collect();
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx, span: FileSpan) -> Option<StructID> {
|
||||
ctx.ident_stack.push();
|
||||
let gmap: Vec<_> = self.generics.iter().flat_map(|a| a.lower(ctx)).collect();
|
||||
let gargs = gmap.iter().map(|(_, id)| *id).collect();
|
||||
let fields = match &self.fields {
|
||||
PStructFields::Named(nodes) => nodes
|
||||
.iter()
|
||||
@@ -20,7 +18,7 @@ impl PStruct {
|
||||
let def = n.as_ref()?;
|
||||
let name = def.name.as_ref()?.to_string();
|
||||
let tynode = def.ty.as_ref()?;
|
||||
let ty = tynode.lower(b, output);
|
||||
let ty = tynode.lower(ctx);
|
||||
Some((name, ty))
|
||||
})
|
||||
.collect(),
|
||||
@@ -28,7 +26,7 @@ impl PStruct {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, n)| {
|
||||
let ty = n.as_ref()?.lower(b, output, span);
|
||||
let ty = n.as_ref()?.lower(ctx, span);
|
||||
Some((format!("{i}"), ty))
|
||||
})
|
||||
.collect(),
|
||||
@@ -38,21 +36,12 @@ impl PStruct {
|
||||
.map(|(name, ty)| (name, StructField { ty }))
|
||||
.collect();
|
||||
let name = self.name.as_ref()?.to_string();
|
||||
b.def_data(UStruct {
|
||||
ctx.ident_stack.pop();
|
||||
Some(ctx.def_struct(UStruct {
|
||||
name,
|
||||
gargs: generics,
|
||||
gargs,
|
||||
fields,
|
||||
origin: span,
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<PStruct> {
|
||||
pub fn lower(&self, id: StructID, p: &mut UProgram, output: &mut CompilerOutput) -> Option<()> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref()?;
|
||||
s.lower(id, p, output, self.origin);
|
||||
Some(())
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
+27
-27
@@ -1,76 +1,76 @@
|
||||
use crate::{
|
||||
ir::{GenericID, MemberID, ModPath, Type, TypeID, UGeneric, UModuleBuilder, UProgram},
|
||||
ir::{GenericID, MemberIdent, MemberPath, Type, TypeID, UGeneric, UProgram},
|
||||
parser::PGenericDef,
|
||||
};
|
||||
|
||||
use super::{CompilerOutput, FileSpan, Node, PType};
|
||||
use super::{FileSpan, ModuleLowerCtx, Node, PType};
|
||||
|
||||
impl Node<Box<PType>> {
|
||||
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx) -> TypeID {
|
||||
self.as_ref()
|
||||
.map(|t| t.lower(p, output, self.origin))
|
||||
.unwrap_or(p.error)
|
||||
.map(|t| t.lower(ctx, self.origin))
|
||||
.unwrap_or(ctx.tc.error)
|
||||
}
|
||||
}
|
||||
impl Node<PType> {
|
||||
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx) -> TypeID {
|
||||
self.as_ref()
|
||||
.map(|t| t.lower(p, output, self.origin))
|
||||
.unwrap_or(p.error)
|
||||
.map(|t| t.lower(ctx, self.origin))
|
||||
.unwrap_or(ctx.tc.error)
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {}
|
||||
|
||||
impl PType {
|
||||
pub fn lower(
|
||||
&self,
|
||||
p: &mut UModuleBuilder,
|
||||
output: &mut CompilerOutput,
|
||||
mut origin: FileSpan,
|
||||
) -> TypeID {
|
||||
pub fn lower(&self, ctx: &mut ModuleLowerCtx, mut origin: FileSpan) -> TypeID {
|
||||
let mut ty = self;
|
||||
let mut path = Vec::new();
|
||||
while let PType::Member(node, ident) = ty {
|
||||
ty = if let Some(t) = node.as_ref() {
|
||||
let Some(name) = ident.as_ref() else {
|
||||
return p.error;
|
||||
return ctx.tc.error;
|
||||
};
|
||||
origin = node.origin;
|
||||
path.push(MemberID {
|
||||
path.push(MemberIdent {
|
||||
name: name.0.clone(),
|
||||
origin: ident.origin,
|
||||
});
|
||||
&**t
|
||||
} else {
|
||||
return p.error;
|
||||
return ctx.tc.error;
|
||||
};
|
||||
}
|
||||
if !path.is_empty() {
|
||||
let PType::Ident(id) = ty else {
|
||||
return p.error;
|
||||
return ctx.tc.error;
|
||||
};
|
||||
path.push(MemberID {
|
||||
path.push(MemberIdent {
|
||||
name: id.0.clone(),
|
||||
origin,
|
||||
});
|
||||
let ty = Type::Unres(ModPath { id: p.module, path });
|
||||
return p.def_ty(ty);
|
||||
path.reverse();
|
||||
let ty = Type::Unres(MemberPath {
|
||||
id: ctx.module,
|
||||
path,
|
||||
});
|
||||
return ctx.def_ty(ty);
|
||||
}
|
||||
let ty = match ty {
|
||||
PType::Member(_, _) => unreachable!(),
|
||||
PType::Ident(node) => {
|
||||
path.push(MemberID {
|
||||
path.push(MemberIdent {
|
||||
name: node.0.clone(),
|
||||
origin,
|
||||
});
|
||||
path.reverse();
|
||||
Type::Unres(ModPath { id: p.module, path })
|
||||
Type::Unres(MemberPath {
|
||||
id: ctx.module,
|
||||
path,
|
||||
})
|
||||
}
|
||||
PType::Ref(node) => node.lower(p, output).rf(),
|
||||
PType::Ref(node) => node.lower(ctx).rf(),
|
||||
PType::Generic(node, nodes) => todo!(),
|
||||
};
|
||||
p.def_ty(ty)
|
||||
ctx.def_ty(ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-11
@@ -1,12 +1,12 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use crate::{common::FilePos, parser::NodeParsableWith};
|
||||
use crate::{common::FilePos, ir::MemberTy, parser::NodeParsableWith};
|
||||
|
||||
use super::{
|
||||
op::{InfixOp, PostfixOp},
|
||||
util::parse_list,
|
||||
CompilerMsg, Keyword, Node, PAsmBlock, PBlock, PIdent, PLiteral, PMap, Parsable, ParseResult,
|
||||
ParserCtx, Symbol,
|
||||
CompilerMsg, Keyword, Node, PAsmBlock, PBlock, PIdent, PLiteral, PMap, PType, Parsable,
|
||||
ParseResult, ParserCtx, Symbol,
|
||||
};
|
||||
|
||||
type BoxNode = Node<Box<PExpr>>;
|
||||
@@ -19,8 +19,8 @@ pub enum PExpr {
|
||||
Block(Node<PBlock>),
|
||||
Call(BoxNode, Vec<Node<PExpr>>),
|
||||
Group(BoxNode),
|
||||
Field(BoxNode, Node<PIdent>),
|
||||
Member(BoxNode, Node<PIdent>),
|
||||
Member(BoxNode, MemberTy, Node<PIdent>),
|
||||
Generic(BoxNode, Vec<Node<PType>>),
|
||||
AsmBlock(Node<PAsmBlock>),
|
||||
Construct(BoxNode, Node<PMap>),
|
||||
If(BoxNode, BoxNode),
|
||||
@@ -65,16 +65,25 @@ impl PExpr {
|
||||
e1 = Self::Call(Node::new(e1, span).bx(), args);
|
||||
continue;
|
||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||
ctx.next();
|
||||
let map = ctx.parse()?;
|
||||
e1 = Self::Construct(Node::new(e1, span).bx(), map);
|
||||
continue;
|
||||
} else if next.is_symbol(Symbol::Dot) {
|
||||
ctx.next();
|
||||
let field = ctx.parse()?;
|
||||
e1 = Self::Field(Node::new(e1, span).bx(), field);
|
||||
e1 = Self::Member(Node::new(e1, span).bx(), MemberTy::Field, field);
|
||||
continue;
|
||||
} else if next.is_symbol(Symbol::DoubleColon) {
|
||||
let field = ctx.parse()?;
|
||||
e1 = Self::Member(Node::new(e1, span).bx(), field);
|
||||
ctx.next();
|
||||
if ctx.peek().is_some_and(|i| i.is_symbol(Symbol::OpenAngle)) {
|
||||
ctx.next();
|
||||
let gargs = parse_list(ctx, Symbol::CloseAngle)?;
|
||||
e1 = Self::Generic(Node::new(e1, span).bx(), gargs);
|
||||
} else {
|
||||
let field = ctx.parse()?;
|
||||
e1 = Self::Member(Node::new(e1, span).bx(), MemberTy::Member, field);
|
||||
}
|
||||
continue;
|
||||
} else if let Some(op) = PostfixOp::from_token(next) {
|
||||
ctx.next();
|
||||
@@ -185,13 +194,13 @@ impl Debug for PExpr {
|
||||
PExpr::PostfixOp(e, op) => write!(f, "({:?}{})", e, op.str())?,
|
||||
PExpr::Group(inner) => inner.fmt(f)?,
|
||||
PExpr::AsmBlock(inner) => inner.fmt(f)?,
|
||||
PExpr::Construct(node, inner) => inner.fmt(f)?,
|
||||
PExpr::Construct(node, inner) => write!(f, "{:?}{:?}", node, inner)?,
|
||||
PExpr::If(cond, res) => write!(f, "if {cond:?} then {res:?}")?,
|
||||
PExpr::Loop(res) => write!(f, "loop -> {res:?}")?,
|
||||
PExpr::Break => write!(f, "break")?,
|
||||
PExpr::Continue => write!(f, "continue")?,
|
||||
PExpr::Field(e1, name) => write!(f, "{:?}.{:?}", e1, name)?,
|
||||
PExpr::Member(e1, name) => write!(f, "{:?}::{:?}", e1, name)?,
|
||||
PExpr::Member(e1, ty, name) => write!(f, "{:?}{}{:?}", e1, ty.sep(), name)?,
|
||||
PExpr::Generic(e1, gargs) => write!(f, "{:?}<{:?}>", e1, gargs)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user