moving to desktop

This commit is contained in:
2025-05-02 22:03:32 -04:00
parent 57c46b653e
commit 5f36be9de9
19 changed files with 197 additions and 236 deletions

View File

@@ -1,6 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset}; use crate::ir::{
AsmBlockArgType, FnID, Size, GenericTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset,
};
use super::{ use super::{
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID, IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID,
@@ -14,15 +16,11 @@ pub struct LProgram {
// NOTE: there are THREE places here where I specify size (8) // NOTE: there are THREE places here where I specify size (8)
impl LProgram { impl LProgram {
pub fn create(p: &UProgram) -> Result<Self, String> { pub fn create(p: &UProgram, start: FnID) -> Result<Self, String> {
let start = p
.names
.id::<UFunc>(&[], "crate")
.ok_or("no start method found")?;
let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]); let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]);
let entry = ssbuilder.func(&start); let entry = ssbuilder.func(&start);
while let Some((sym, i)) = ssbuilder.pop_fn() { while let Some((sym, i)) = ssbuilder.pop_fn() {
let f = p.fns[i.0].as_ref().unwrap(); let f = &p.fns[i];
let mut fbuilder = LFunctionBuilder::new(p, &mut ssbuilder); let mut fbuilder = LFunctionBuilder::new(p, &mut ssbuilder);
for i in &f.instructions { for i in &f.instructions {
fbuilder.insert_instr(i); fbuilder.insert_instr(i);
@@ -31,7 +29,7 @@ impl LProgram {
fbuilder.instrs.push(LInstruction::Ret { src: None }); fbuilder.instrs.push(LInstruction::Ret { src: None });
} }
let res = fbuilder.finish(f); let res = fbuilder.finish(f);
ssbuilder.write_fn(sym, res, Some(p.names.path(i).to_string())); ssbuilder.write_fn(sym, res, Some(f.name.clone()));
} }
let sym_space = ssbuilder.finish().expect("we failed the mission"); let sym_space = ssbuilder.finish().expect("we failed the mission");
Ok(Self { sym_space, entry }) Ok(Self { sym_space, entry })
@@ -376,7 +374,7 @@ impl LFunctionBuilderData<'_> {
pub fn addr_size(&self) -> Size { pub fn addr_size(&self) -> Size {
64 64
} }
pub fn struct_inst(&mut self, p: &UProgram, ty: &StructTy) -> &StructInst { pub fn struct_inst(&mut self, p: &UProgram, ty: &GenericTy) -> &StructInst {
// normally I'd let Some(..) here and return, but polonius does not exist :grief: // normally I'd let Some(..) here and return, but polonius does not exist :grief:
if self.struct_insts.get(ty).is_none() { if self.struct_insts.get(ty).is_none() {
let StructInst { id, args } = ty; let StructInst { id, args } = ty;

View File

@@ -1,22 +0,0 @@
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
use super::{UProgram, Type};
impl CompilerOutput {
pub fn check_assign(&mut self, p: &UProgram, src: &Type, dest: &Type, span: FileSpan) {
// TODO: spans
if src != dest {
if !src.is_resolved() || !dest.is_resolved() {
return;
}
self.err(CompilerMsg {
msg: format!(
"Cannot assign type '{}' to '{}'",
p.type_name(src),
p.type_name(dest)
),
spans: vec![span],
});
}
}
}

View File

@@ -1,26 +1,33 @@
use crate::ir::VarID; use crate::ir::VarID;
use std::fmt::Debug; use std::fmt::Debug;
use super::{Origin, UInstruction}; use super::{MemberID, ModPath, Origin, UInstruction};
#[derive(Clone, Copy)] #[derive(Clone)]
pub struct VarInst { pub struct VarInst {
pub id: VarID, pub status: VarStatus,
pub origin: Origin, pub origin: Origin,
} }
#[derive(Clone)]
pub enum VarStatus {
Res(VarID),
Unres { mid: ModPath, fields: Vec<MemberID> },
Partial { v: VarID, fields: Vec<MemberID> },
}
#[derive(Clone)]
pub struct VarParent {
id: VarID,
path: Vec<String>,
}
#[derive(Clone)] #[derive(Clone)]
pub struct UInstrInst { pub struct UInstrInst {
pub i: UInstruction, pub i: UInstruction,
pub origin: Origin, pub origin: Origin,
} }
impl Debug for VarInst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.id)
}
}
impl Debug for UInstrInst { impl Debug for UInstrInst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.i) write!(f, "{:?}", self.i)

View File

@@ -73,7 +73,8 @@ impl std::fmt::Debug for UInstruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::Mv { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, Self::Mv { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- &{src:?}")?, Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}&")?,
Self::Deref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}^")?,
Self::LoadData { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, Self::LoadData { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
Self::LoadFn { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, Self::LoadFn { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
Self::LoadSlice { dst: dest, src } => write!(f, "{dest:?} <- &[{src:?}]")?, Self::LoadSlice { dst: dest, src } => write!(f, "{dest:?} <- &[{src:?}]")?,

View File

@@ -1,4 +1,4 @@
use super::{Type, UInstrInst, UInstruction, UProgram}; use super::{Type, UInstrInst, UInstruction};
use crate::{ use crate::{
common::FileSpan, common::FileSpan,
ir::{Len, ID}, ir::{Len, ID},
@@ -12,7 +12,7 @@ pub struct UFunc {
pub name: String, pub name: String,
pub origin: Origin, pub origin: Origin,
pub args: Vec<VarID>, pub args: Vec<VarID>,
pub argtys: Vec<TypeID>, pub gargs: Vec<TypeID>,
pub ret: TypeID, pub ret: TypeID,
pub instructions: Vec<UInstrInst>, pub instructions: Vec<UInstrInst>,
} }
@@ -41,13 +41,8 @@ pub struct UVar {
pub name: String, pub name: String,
pub origin: Origin, pub origin: Origin,
pub ty: TypeID, pub ty: TypeID,
pub res: UVarTy, pub parent: Option<VarID>,
} pub children: Vec<VarID>,
#[derive(Clone)]
pub struct VarParent {
id: VarID,
path: Vec<String>,
} }
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
@@ -62,25 +57,6 @@ pub struct ModPath {
pub path: Vec<MemberID>, pub path: Vec<MemberID>,
} }
#[derive(Clone)]
pub enum UVarTy {
Ptr(VarID),
/// fully resolved & typed
Res {
parent: Option<VarParent>,
},
/// module doesn't exist yet
Unres {
path: ModPath,
fields: Vec<MemberID>,
},
/// parent var exists but not typed enough for this field path
Partial {
v: VarID,
fields: Vec<MemberID>,
},
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub struct VarOffset { pub struct VarOffset {
pub id: VarID, pub id: VarID,
@@ -117,12 +93,6 @@ pub enum Member {
pub type Origin = FileSpan; pub type Origin = FileSpan;
impl UFunc { impl UFunc {
pub fn ty(&self, program: &UProgram) -> Type {
Type::Fn {
args: self.argtys.clone(),
ret: Box::new(self.ret.clone()),
}
}
pub fn flat_iter(&self) -> impl Iterator<Item = &UInstrInst> { pub fn flat_iter(&self) -> impl Iterator<Item = &UInstrInst> {
InstrIter::new(self.instructions.iter()) InstrIter::new(self.instructions.iter())
} }

View File

@@ -1,5 +1,4 @@
mod assoc; mod assoc;
mod error;
mod inst; mod inst;
mod instr; mod instr;
mod kind; mod kind;
@@ -11,7 +10,6 @@ mod resolve;
use super::*; use super::*;
use assoc::*; use assoc::*;
pub use assoc::Idents;
pub use inst::*; pub use inst::*;
pub use instr::*; pub use instr::*;
pub use kind::*; pub use kind::*;

View File

@@ -12,6 +12,11 @@ pub struct UProgram {
pub generics: Vec<UGeneric>, pub generics: Vec<UGeneric>,
pub vars: Vec<UVar>, pub vars: Vec<UVar>,
pub types: Vec<Type>, pub types: Vec<Type>,
pub unres_vars: Vec<VarID>,
pub unres_tys: Vec<TypeID>,
pub unit: TypeID,
pub error: TypeID,
} }
pub struct UModuleBuilder<'a> { pub struct UModuleBuilder<'a> {
@@ -22,6 +27,9 @@ pub struct UModuleBuilder<'a> {
impl UProgram { impl UProgram {
pub fn new() -> Self { pub fn new() -> Self {
let mut types = Vec::new();
let unit = Self::push_id(&mut types, Type::Unit);
let error = Self::push_id(&mut types, Type::Error);
Self { Self {
fns: Vec::new(), fns: Vec::new(),
vars: Vec::new(), vars: Vec::new(),
@@ -30,24 +38,36 @@ impl UProgram {
generics: Vec::new(), generics: Vec::new(),
data: Vec::new(), data: Vec::new(),
modules: Vec::new(), modules: Vec::new(),
unres_vars: Vec::new(),
unres_tys: Vec::new(),
error,
unit,
} }
} }
pub fn instantiate_type(&mut self, ty: Type) { pub fn inst_type(&mut self, ty: TypeID, gs: Vec<TypeID>) -> TypeID {
self.def_ty(match ty { let ty = match &self.types[ty] {
Type::Ref(node) => Type::Ref(node.lower()), Type::Ref(id) => Type::Ref(self.inst_type(*id, gs)),
Type::Generic(node, nodes) => todo!(), Type::Generic(id) => return gs[id.0],
Type::Ident(node) => todo!(), Type::Bits(b) => Type::Bits(*b),
}); Type::Struct(struct_ty) => Type::Struct(struct_ty.clone()),
Type::Fn() => todo!(),
Type::Deref(id) => todo!(),
Type::Slice(id) => todo!(),
Type::Array(id, _) => todo!(),
Type::Unit => todo!(),
Type::Unres(mod_path) => todo!(),
Type::Infer => todo!(),
Type::Error => todo!(),
};
self.def_ty(ty)
} }
pub fn infer(&mut self) -> TypeID { pub fn infer(&mut self) -> TypeID {
self.def_ty(Type::Infer) self.def_ty(Type::Infer)
} }
pub fn error(&mut self) -> TypeID { pub fn set_type(id: TypeID, ty: Type) {}
self.def_ty(Type::Error)
}
pub fn def_var(&mut self, v: UVar) -> VarID { pub fn def_var(&mut self, v: UVar) -> VarID {
Self::push_id(&mut self.vars, v) Self::push_id(&mut self.vars, v)

View File

@@ -1,4 +1,4 @@
use super::{Origin, StructTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar}; use super::{Origin, GenericTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar};
use crate::common::{CompilerMsg, CompilerOutput}; use crate::common::{CompilerMsg, CompilerOutput};
use std::{collections::HashMap, ops::BitOrAssign}; use std::{collections::HashMap, ops::BitOrAssign};
@@ -65,10 +65,6 @@ impl UProgram {
format!("Type of {:?} cannot be inferred", var.name), format!("Type of {:?} cannot be inferred", var.name),
var.origin, var.origin,
)), )),
Type::Placeholder => output.err(CompilerMsg::new(
format!("Var {:?} still placeholder!", var.name),
var.origin,
)),
Type::Unres(_) => output.err(CompilerMsg::new( Type::Unres(_) => output.err(CompilerMsg::new(
format!("Var {:?} type still unresolved!", var.name), format!("Var {:?} type still unresolved!", var.name),
var.origin, var.origin,
@@ -91,11 +87,12 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
let mut uf = InstrRes::Finished; let mut uf = InstrRes::Finished;
match &i { match &i {
UInstruction::Call { dst, f, args } => { UInstruction::Call { dst, f, args } => {
let fty = data.vars[f.id].ty; let ftyid = data.vars[f.id].ty;
let Type::Fn { args: fargs, ret } = &data.types[fty] else { let fty = &data.types[ftyid];
let Type::Fn { args: fargs, ret } = fty else {
data.errs.push(ResErr::NotCallable { data.errs.push(ResErr::NotCallable {
origin: f.origin, origin: f.origin,
ty: fty, ty: ftyid,
}); });
return InstrRes::Finished; return InstrRes::Finished;
}; };
@@ -131,7 +128,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
let dest_ty = get(vars, dst.id)?; let dest_ty = get(vars, dst.id)?;
let Type::Struct(sty) = dest_ty else {}; let Type::Struct(sty) = dest_ty else {};
let id = sty.id; let id = sty.id;
let Some(struc) = self.get(id) else {}; let Some(struc) = get(id) else {};
let mut new = HashMap::new(); let mut new = HashMap::new();
for (name, field) in &struc.fields { for (name, field) in &struc.fields {
let Some(src) = fields.get(name) else { let Some(src) = fields.get(name) else {
@@ -155,7 +152,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
args[i] = ty; args[i] = ty;
} }
} }
set(vars, dst.id, Type::Struct(StructTy { id, args })); set(vars, dst.id, Type::Struct(GenericTy { id, args }));
} }
UInstruction::If { cond, body } => { UInstruction::If { cond, body } => {
for i in body { for i in body {

View File

@@ -1,4 +1,5 @@
use super::{FnID, GenericID, Len, ModPath, StructID, TypeID, UVar, VarID, VarInst}; use super::{GenericID, Len, ModPath, TypeID, UFunc, UProgram, UStruct, UVar, VarID, VarInst};
use crate::ir::ID;
#[derive(Debug, Clone, Hash, Eq, PartialEq)] #[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct FieldRef { pub struct FieldRef {
@@ -7,16 +8,16 @@ pub struct FieldRef {
} }
#[derive(Clone, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
pub struct StructTy { pub struct GenericTy<T> {
pub id: StructID, pub id: ID<T>,
pub args: Vec<TypeID>, pub args: Vec<TypeID>,
} }
#[derive(Clone)] #[derive(Clone)]
pub enum Type { pub enum Type {
Bits(u32), Bits(u32),
Struct(StructTy), Struct(GenericTy<UStruct>),
Fn(FnID), Fn(GenericTy<UFunc>),
Ref(TypeID), Ref(TypeID),
Deref(TypeID), Deref(TypeID),
Slice(TypeID), Slice(TypeID),
@@ -27,7 +28,21 @@ pub enum Type {
Generic(GenericID), Generic(GenericID),
Infer, Infer,
Error, Error,
Placeholder, }
impl Type {
pub fn rf(self, p: &mut UProgram) -> Self {
p.def_ty(self).rf()
}
pub fn derf(self, p: &mut UProgram) -> Self {
p.def_ty(self).derf()
}
pub fn arr(self, p: &mut UProgram, len: Len) -> Self {
p.def_ty(self).arr(len)
}
pub fn slice(self, p: &mut UProgram) -> Self {
p.def_ty(self).slice()
}
} }
impl TypeID { impl TypeID {
@@ -46,9 +61,6 @@ impl TypeID {
} }
impl Type { impl Type {
pub fn is_resolved(&self) -> bool {
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
}
pub fn bx(self) -> Box<Self> { pub fn bx(self) -> Box<Self> {
Box::new(self) Box::new(self)
} }

View File

@@ -174,7 +174,7 @@ pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<VarInst>
); );
return None; return None;
}; };
ctx.get_var(node) ctx.var(node)
} }
impl RegRef { impl RegRef {
@@ -184,7 +184,7 @@ impl RegRef {
let reg = Reg::from_ident(node, ctx)?; let reg = Reg::from_ident(node, ctx)?;
Self::Reg(reg) Self::Reg(reg)
} }
PAsmArg::Ref(node) => Self::Var(ctx.get_var(node)?), PAsmArg::Ref(node) => Self::Var(ctx.var(node)?),
}) })
} }
} }

View File

@@ -1,9 +1,9 @@
use crate::ir::{UProgram, UVar, VarInst}; use crate::ir::{UProgram, UVar, VarID, VarInst};
use super::{CompilerOutput, Node, PVarDef}; use super::{CompilerOutput, Node, PVarDef};
impl Node<PVarDef> { impl Node<PVarDef> {
pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option<VarInst> { pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option<VarID> {
let s = self.as_ref()?; 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);
let ty = match &s.ty { let ty = match &s.ty {

View File

@@ -20,11 +20,11 @@ impl FnLowerable for PExpr {
Some(match e { Some(match e {
PExpr::Lit(l) => match l { PExpr::Lit(l) => match l {
super::PLiteral::String(s) => { super::PLiteral::String(s) => {
let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice()); let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice(ctx.b.p));
let data = s.as_bytes().to_vec(); let data = s.as_bytes().to_vec();
let src = ctx.b.def_data(UData { let src = ctx.b.def_data(UData {
name: format!("string \"{}\"", s.replace("\n", "\\n")), name: format!("string \"{}\"", s.replace("\n", "\\n")),
ty: Type::Bits(8).arr(data.len() as u32), ty: Type::Bits(8).arr(ctx.b.p, data.len() as u32),
content: data, content: data,
}); });
ctx.push(UInstruction::LoadSlice { dst: dest, src }); ctx.push(UInstruction::LoadSlice { dst: dest, src });
@@ -55,7 +55,7 @@ impl FnLowerable for PExpr {
} }
super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit), super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit),
}, },
PExpr::Ident(i) => ctx.get_var(i), PExpr::Ident(i) => ctx.var(i),
PExpr::BinaryOp(op, e1, e2) => match op { PExpr::BinaryOp(op, e1, e2) => match op {
InfixOp::Add => todo!(), InfixOp::Add => todo!(),
InfixOp::Sub => todo!(), InfixOp::Sub => todo!(),
@@ -77,13 +77,13 @@ impl FnLowerable for PExpr {
let res = e.lower(ctx)?; let res = e.lower(ctx)?;
match op { match op {
PostfixOp::Ref => { PostfixOp::Ref => {
let ty = ctx.b.vars[res.id].ty.rf(); let ty = Type::Ref(ctx.b.infer());
let dest = ctx.temp(ty); let dest = ctx.temp(ty);
ctx.push(UInstruction::Ref { dst: dest, src: res }); ctx.push(UInstruction::Ref { dst: dest, src: res });
dest dest
} }
PostfixOp::Deref => { PostfixOp::Deref => {
let ty = ctx.b.vars[res.id].ty.derf(); let ty = Type::Deref(ctx.b.infer());
let dest = ctx.temp(ty); let dest = ctx.temp(ty);
ctx.push(UInstruction::Deref { dst: dest, src: res }); ctx.push(UInstruction::Deref { dst: dest, src: res });
dest dest
@@ -100,9 +100,9 @@ impl FnLowerable for PExpr {
let arg = arg.lower(ctx)?; let arg = arg.lower(ctx)?;
nargs.push(arg); nargs.push(arg);
} }
let dest = ctx.temp(Type::Placeholder); let dest = ctx.temp(Type::Infer);
ctx.push(UInstruction::Call { ctx.push(UInstruction::Call {
dst: dest, dst: VarInst { status: , origin: () },
f: fe, f: fe,
args: nargs, args: nargs,
}); });

View File

@@ -3,120 +3,111 @@ use std::collections::HashMap;
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction}; use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
use crate::{ use crate::{
ir::{ ir::{
FnID, Idents, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UProgram, FnID, Origin, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UVar, VarID,
UVar, VarID, VarInst, VarInst, VarStatus,
}, },
parser, parser, util::NameStack,
}; };
impl Node<PFunction> { impl Node<PFunction> {
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
self.as_ref()?.lower_name(p)
}
pub fn lower( pub fn lower(
&self, &self,
id: FnID, b: &mut UModuleBuilder,
p: &mut UProgram,
imports: &mut Imports, imports: &mut Imports,
output: &mut CompilerOutput, output: &mut CompilerOutput,
) { ) -> Option<FnID> {
if let Some(s) = self.as_ref() { self.as_ref()
s.lower(id, p, imports, output) .map(|s| s.lower(b, imports, output, self.origin))
} .flatten()
} }
} }
impl PFunction { 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, None, self.header.origin);
Some(id)
}
pub fn lower( pub fn lower(
&self, &self,
id: FnID, b: &mut UModuleBuilder,
p: &mut UProgram,
imports: &mut Imports, imports: &mut Imports,
output: &mut CompilerOutput, output: &mut CompilerOutput,
) { origin: Origin,
let name = p.names.name(id).to_string(); ) -> Option<FnID> {
p.push_name(&name); let header = self.header.as_ref()?;
let (args, ret) = if let Some(header) = self.header.as_ref() { let name = header.name.as_ref()?.0.clone();
let (generic_args, args, ret) = if let Some(header) = self.header.as_ref() {
( (
header
.gargs
.iter()
.map(|a| Some(a.lower(b, output)))
.collect(),
header header
.args .args
.iter() .iter()
.flat_map(|a| Some(a.lower(p, output)?.id)) .flat_map(|a| Some(a.lower(b, output)?))
.collect(), .collect(),
match &header.ret { match &header.ret {
Some(ty) => ty.lower(p, output), Some(ty) => ty.lower(b, output),
None => Type::Unit, None => b.def_ty(Type::Unit),
}, },
) )
} else { } else {
(Vec::new(), Type::Error) (Vec::new(), Vec::new(), b.error)
}; };
let instructions = {
let mut var_stack = Vec::new();
let mut ctx = FnLowerCtx { let mut ctx = FnLowerCtx {
instructions: Vec::new(), instructions: Vec::new(),
b: p, var_stack: &mut var_stack,
b,
output, output,
origin: self.body.origin, origin: self.body.origin,
imports, imports,
}; };
if let Some(src) = self.body.lower(&mut ctx) { if let Some(src) = self.body.lower(&mut ctx) {
ctx.instructions.push(UInstrInst { ctx.instructions.push(UInstrInst {
i: UInstruction::Ret { src },
origin: src.origin, origin: src.origin,
i: UInstruction::Ret { src },
}); });
} }
let instructions = ctx.instructions; ctx.instructions
};
let gargs = args.iter().map(|a| b.vars[a].ty).collect();
let f = UFunc { let f = UFunc {
origin,
gargs,
name,
args, args,
ret, ret,
instructions, instructions,
}; };
p.pop_name(); Some(b.def_fn(f))
p.write(id, f)
} }
} }
pub struct FnLowerCtx<'a> { pub struct FnLowerCtx<'a, 'b> {
pub b: &'a mut UModuleBuilder<'a>, pub b: &'a mut UModuleBuilder<'b>,
pub instructions: Vec<UInstrInst>, pub instructions: Vec<UInstrInst>,
pub output: &'a mut CompilerOutput, pub output: &'a mut CompilerOutput,
pub origin: FileSpan, pub origin: FileSpan,
pub imports: &'a mut Imports, pub imports: &'a mut Imports,
pub var_stack: Vec<HashMap<String, VarID>>, pub var_stack: &'a mut NameStack<VarID>,
} }
impl FnLowerCtx<'_> { impl<'a, 'b> FnLowerCtx<'a, 'b> {
pub fn get_idents(&mut self, node: &Node<parser::PIdent>) -> Option<Idents> { pub fn var(&mut self, node: &Node<parser::PIdent>) -> VarInst {
let name = node.inner.as_ref()?; if let Some(n) = node.as_ref() {
let res = self.b.get_idents(name); if let Some(&var) = self.var_stack.search(&n.0) {
if res.is_none() { return VarInst {
self.err_at(node.origin, format!("Identifier '{}' not found", name)); status: VarStatus::Res(var),
}
res
}
pub fn get_var(&mut self, node: &Node<parser::PIdent>) -> VarInst {
let ids = self.get_idents(node)?;
if ids.get::<UVar>().is_none() {
self.err_at(
node.origin,
format!("Variable '{}' not found", node.inner.as_ref()?),
);
}
ids.get::<UVar>().map(|id| VarInst {
id,
origin: node.origin, origin: node.origin,
}) }
}
}
} }
pub fn err(&mut self, msg: String) { pub fn err(&mut self, msg: String) {
self.output.err(CompilerMsg::new(self.origin, msg)) self.output.err(CompilerMsg::new(msg, self.origin))
} }
pub fn err_at(&mut self, span: FileSpan, msg: String) { pub fn err_at(&mut self, span: FileSpan, msg: String) {
self.output.err(CompilerMsg::new(span, msg)) self.output.err(CompilerMsg::new(msg, span))
} }
pub fn temp<T: Typable>(&mut self, ty: Type) -> VarInst { pub fn temp<T: Typable>(&mut self, ty: Type) -> VarInst {
self.b.temp_var(self.origin, ty) self.b.temp_var(self.origin, ty)
@@ -125,27 +116,13 @@ impl FnLowerCtx<'_> {
self.push_at(i, self.origin); self.push_at(i, self.origin);
} }
pub fn push_at(&mut self, i: UInstruction, span: FileSpan) { pub fn push_at(&mut self, i: UInstruction, span: FileSpan) {
match i {
UInstruction::Mv { dst: dest, src } => todo!(),
UInstruction::Ref { dst: dest, src } => todo!(),
UInstruction::LoadData { dst: dest, src } => todo!(),
UInstruction::LoadSlice { dst: dest, src } => todo!(),
UInstruction::LoadFn { dst: dest, src } => todo!(),
UInstruction::Call { dst: dest, f, args } => todo!(),
UInstruction::AsmBlock { instructions, args } => todo!(),
UInstruction::Ret { src } => todo!(),
UInstruction::Construct { dst: dest, fields } => todo!(),
UInstruction::If { cond, body } => todo!(),
UInstruction::Loop { body } => todo!(),
UInstruction::Break => todo!(),
UInstruction::Continue => todo!(),
}
self.instructions.push(UInstrInst { i, origin: span }); self.instructions.push(UInstrInst { i, origin: span });
} }
pub fn branch<'a>(&'a mut self) -> FnLowerCtx<'a> { pub fn branch(&'a mut self) -> FnLowerCtx<'a, 'b> {
FnLowerCtx { FnLowerCtx {
b: self.b, b: self.b,
instructions: Vec::new(), instructions: Vec::new(),
var_stack: self.var_stack,
output: self.output, output: self.output,
origin: self.origin, origin: self.origin,
imports: self.imports, imports: self.imports,

View File

@@ -8,13 +8,13 @@ mod struc;
mod ty; mod ty;
use super::*; use super::*;
use crate::ir::{Type, UFunc, UProgram}; use crate::ir::{Type, UFunc, UModuleBuilder};
impl PModule { impl PModule {
pub fn lower( pub fn lower(
&self, &self,
path: Vec<String>, path: Vec<String>,
p: &mut UProgram, p: &mut UModuleBuilder,
imports: &mut Imports, imports: &mut Imports,
output: &mut CompilerOutput, output: &mut CompilerOutput,
) { ) {

View File

@@ -9,14 +9,14 @@ impl Node<Box<PType>> {
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID { pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
self.as_ref() self.as_ref()
.map(|t| t.lower(p, output, self.origin)) .map(|t| t.lower(p, output, self.origin))
.unwrap_or(p.error()) .unwrap_or(p.error)
} }
} }
impl Node<PType> { impl Node<PType> {
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID { pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
self.as_ref() self.as_ref()
.map(|t| t.lower(p, output, self.origin)) .map(|t| t.lower(p, output, self.origin))
.unwrap_or(p.error()) .unwrap_or(p.error)
} }
} }
@@ -34,7 +34,7 @@ impl PType {
while let PType::Member(node, ident) = ty { while let PType::Member(node, ident) = ty {
ty = if let Some(t) = node.as_ref() { ty = if let Some(t) = node.as_ref() {
let Some(name) = ident.as_ref() else { let Some(name) = ident.as_ref() else {
return p.error(); return p.error;
}; };
origin = node.origin; origin = node.origin;
path.push(MemberID { path.push(MemberID {
@@ -43,18 +43,19 @@ impl PType {
}); });
&**t &**t
} else { } else {
return p.error(); return p.error;
}; };
} }
if !path.is_empty() { if !path.is_empty() {
let PType::Ident(id) = ty else { let PType::Ident(id) = ty else {
return p.error(); return p.error;
}; };
path.push(MemberID { path.push(MemberID {
name: id.0.clone(), name: id.0.clone(),
origin, origin,
}); });
return p.def_ty(Type::Unres(ModPath { m: p.module, path })); let ty = Type::Unres(ModPath { m: p.module, path });
return p.def_ty(ty);
} }
let ty = match ty { let ty = match ty {
PType::Member(_, _) => unreachable!(), PType::Member(_, _) => unreachable!(),
@@ -70,31 +71,6 @@ impl PType {
PType::Generic(node, nodes) => todo!(), PType::Generic(node, nodes) => todo!(),
}; };
p.def_ty(ty) p.def_ty(ty)
// let Some(name) = self.name.as_ref() else {
// return p.error();
// };
// let ids = p.get_idents(name);
// // TODO: should generics always take precedence?
// if let Some(id) = ids.and_then(|ids| ids.get::<Type>()) {
// Type::Generic { id }
// } else if let Some(id) = ids.and_then(|ids| ids.get::<UStruct>()) {
// let args = self.args.iter().map(|n| n.lower(p, output)).collect();
// Type::Struct(StructInst { id, args })
// } else if let Ok(num) = name.parse::<u32>() {
// Type::Bits(num)
// } else {
// match name.as_str() {
// "slice" => {
// let inner = self.args[0].lower(p, output);
// Type::Slice(Box::new(inner))
// }
// "_" => Type::Infer,
// _ => {
// output.err(CompilerMsg::from_span(span, "Type not found".to_string()));
// Type::Error
// }
// }
// }
} }
} }

View File

@@ -1,12 +1,13 @@
use super::{ use super::{
util::parse_list, PBlock, PIdent, Node, Parsable, ParseResult, ParserCtx, util::parse_list, Node, PBlock, PIdent, PType, PVarDef, Parsable, ParseResult, ParserCtx,
Symbol, PType, PVarDef, Symbol,
}; };
use std::fmt::Debug; use std::fmt::Debug;
pub struct PFunctionHeader { pub struct PFunctionHeader {
pub name: Node<PIdent>, pub name: Node<PIdent>,
pub args: Vec<Node<PVarDef>>, pub args: Vec<Node<PVarDef>>,
pub gargs: Vec<Node<PType>>,
pub ret: Option<Node<PType>>, pub ret: Option<Node<PType>>,
} }
@@ -18,6 +19,12 @@ pub struct PFunction {
impl Parsable for PFunctionHeader { impl Parsable for PFunctionHeader {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> { fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let name = ctx.parse()?; let name = ctx.parse()?;
let generic_args = if ctx.expect_peek()?.is_symbol(Symbol::OpenAngle) {
ctx.next();
parse_list(ctx, Symbol::CloseAngle)?
} else {
Vec::new()
};
ctx.expect_sym(Symbol::OpenParen)?; ctx.expect_sym(Symbol::OpenParen)?;
// let sel = ctx.maybe_parse(); // let sel = ctx.maybe_parse();
// if sel.is_some() { // if sel.is_some() {
@@ -39,6 +46,7 @@ impl Parsable for PFunctionHeader {
ParseResult::Ok(Self { ParseResult::Ok(Self {
name, name,
args, args,
gargs: generic_args,
ret, ret,
}) })
} }

View File

@@ -40,7 +40,7 @@ impl Parsable for PType {
} }
break; break;
} }
ParseResult::Wrap(cur) ParseResult::Node(cur)
} }
} }

View File

@@ -1,7 +1,9 @@
mod padder; mod padder;
mod bits; mod bits;
mod label; mod label;
mod name_stack;
pub use padder::*; pub use padder::*;
pub use bits::*; pub use bits::*;
pub use label::*; pub use label::*;
pub use name_stack::*;

17
src/util/name_stack.rs Normal file
View File

@@ -0,0 +1,17 @@
use std::collections::HashMap;
pub struct NameStack<T>(Vec<HashMap<String, T>>);
impl<T> NameStack<T> {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn search(&self, name: &str) -> Option<&T> {
for level in self.0.iter().rev() {
if let Some(v) = level.get(name) {
return Some(v);
}
}
None
}
}