trudging through the snow

This commit is contained in:
2025-05-06 23:27:30 -04:00
parent 9368d6dcd0
commit 0016ede873
29 changed files with 1375 additions and 1085 deletions
+4 -4
View File
@@ -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 -2
View File
@@ -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,
};
+17 -22
View File
@@ -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
}
+14 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
+15 -26
View File
@@ -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
View File
@@ -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
View File
@@ -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(())
}