getting closer
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
use crate::{compiler::arch::riscv::*, ir::VarInst};
|
||||
use crate::{compiler::arch::riscv::*, ir::UIdent};
|
||||
|
||||
pub type RV64Instruction = LinkerInstruction<RegRef, VarInst>;
|
||||
pub type RV64Instruction = LinkerInstruction<RegRef, UIdent>;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RegRef {
|
||||
Var(VarInst),
|
||||
Var(UIdent),
|
||||
Reg(Reg),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset};
|
||||
StructTy
|
||||
use crate::ir::{AsmBlockArgType, Size, LStructInst, SymbolSpace, Type, UFunc, UInstrInst, VarOffset};
|
||||
LStructInst
|
||||
use super::{
|
||||
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID,
|
||||
};
|
||||
@@ -42,14 +42,14 @@ impl LProgram {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StructInst {
|
||||
pub struct LStructInst {
|
||||
offsets: Vec<Len>,
|
||||
types: Vec<Type>,
|
||||
order: HashMap<String, usize>,
|
||||
size: Size,
|
||||
}
|
||||
|
||||
impl StructInst {
|
||||
impl LStructInst {
|
||||
pub fn offset(&self, name: &str) -> Option<Len> {
|
||||
Some(self.offsets[*self.order.get(name)?])
|
||||
}
|
||||
@@ -82,7 +82,7 @@ pub struct LFunctionBuilderData<'a> {
|
||||
instrs: Vec<LInstruction>,
|
||||
stack: HashMap<VarID, Size>,
|
||||
subvar_map: HashMap<VarID, VarOffset>,
|
||||
struct_insts: HashMap<StructInst, StructInst>,
|
||||
struct_insts: HashMap<LStructInst, LStructInst>,
|
||||
makes_call: bool,
|
||||
loopp: Option<LoopCtx>,
|
||||
}
|
||||
@@ -376,10 +376,10 @@ impl LFunctionBuilderData<'_> {
|
||||
pub fn addr_size(&self) -> Size {
|
||||
64StructTy
|
||||
}
|
||||
pub fn struct_inst(&mut self, p: &UProgram, ty: &StructTy) -> &StructInst {
|
||||
pub fn struct_inst(&mut self, p: &UProgram, ty: &LStructInst) -> &LStructInst {
|
||||
// normally I'd let Some(..) here and return, but polonius does not exist :grief:
|
||||
if self.struct_insts.get(ty).is_none() {
|
||||
let StructInst { id, args } = ty;
|
||||
let LStructInst { id, args } = ty;
|
||||
let struc = p.expect(*id);
|
||||
let mut types = Vec::new();
|
||||
let mut sizes = struc
|
||||
@@ -412,7 +412,7 @@ impl LFunctionBuilderData<'_> {
|
||||
}
|
||||
self.struct_insts.insert(
|
||||
ty.clone(),
|
||||
StructInst {
|
||||
LStructInst {
|
||||
offsets,
|
||||
order,
|
||||
types,
|
||||
@@ -423,7 +423,7 @@ impl LFunctionBuilderData<'_> {
|
||||
self.struct_insts.get(ty).unwrap()
|
||||
}
|
||||
|
||||
pub fn field_offset(&mut self, p: &UProgram, sty: &StructInst, field: &str) -> Option<Len> {
|
||||
pub fn field_offset(&mut self, p: &UProgram, sty: &LStructInst, field: &str) -> Option<Len> {
|
||||
let inst = self.struct_inst(p, sty);
|
||||
Some(inst.offset(field)?)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
ir::ID,
|
||||
};
|
||||
|
||||
use super::{KindTy, Origin, StructID, TypeID, UProgram};
|
||||
use super::{KindTy, Origin, Res, StructID, TypeID, UProgram};
|
||||
|
||||
pub fn report_errs(p: &UProgram, output: &mut CompilerOutput, errs: Vec<ResErr>) {
|
||||
for err in errs {
|
||||
@@ -82,18 +82,18 @@ pub fn report_errs(p: &UProgram, output: &mut CompilerOutput, errs: Vec<ResErr>)
|
||||
origin,
|
||||
found,
|
||||
expected,
|
||||
id,
|
||||
} => output.err(CompilerMsg::new(
|
||||
{
|
||||
let name = match found {
|
||||
KindTy::Type => &p.type_name(ID::new(id)),
|
||||
KindTy::Var => &p.vars[id].name,
|
||||
KindTy::Struct => &p.structs[id].name,
|
||||
let name = match &found {
|
||||
Res::Fn(fty) => &p.fns[fty.id].name,
|
||||
Res::Type(id) => &p.type_name(id),
|
||||
Res::Var(id) => &p.vars[id].name,
|
||||
Res::Struct(sty) => &p.structs[sty.id].name,
|
||||
};
|
||||
format!(
|
||||
"Expected {}, found {} '{}'",
|
||||
expected.str(),
|
||||
found.str(),
|
||||
found.kind_str(),
|
||||
name
|
||||
)
|
||||
},
|
||||
@@ -106,12 +106,20 @@ pub fn report_errs(p: &UProgram, output: &mut CompilerOutput, errs: Vec<ResErr>)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ResErr {
|
||||
UnknownModule {
|
||||
origin: Origin,
|
||||
name: String,
|
||||
},
|
||||
UnknownMember {
|
||||
origin: Origin,
|
||||
name: String,
|
||||
},
|
||||
KindMismatch {
|
||||
origin: Origin,
|
||||
expected: KindTy,
|
||||
found: KindTy,
|
||||
id: usize,
|
||||
found: Res,
|
||||
},
|
||||
UnexpectedField {
|
||||
origin: Origin,
|
||||
@@ -158,6 +166,7 @@ pub enum ResErr {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ControlFlowOp {
|
||||
Break,
|
||||
Continue,
|
||||
@@ -172,6 +181,7 @@ impl ControlFlowOp {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeMismatch {
|
||||
pub dst: TypeID,
|
||||
pub src: TypeID,
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
use std::{collections::HashMap, fmt::Write};
|
||||
|
||||
use super::{arch::riscv64::RV64Instruction, DataID, FnID, Origin, UFunc, VarInst, VarInstID};
|
||||
use super::{arch::riscv64::RV64Instruction, DataID, FnID, Origin, UFunc, UIdent, IdentID};
|
||||
use crate::{compiler::arch::riscv::Reg, util::Padder};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum UInstruction {
|
||||
Mv {
|
||||
dst: VarInstID,
|
||||
src: VarInstID,
|
||||
dst: IdentID,
|
||||
src: IdentID,
|
||||
},
|
||||
Ref {
|
||||
dst: VarInstID,
|
||||
src: VarInstID,
|
||||
dst: IdentID,
|
||||
src: IdentID,
|
||||
},
|
||||
Deref {
|
||||
dst: VarInstID,
|
||||
src: VarInstID,
|
||||
dst: IdentID,
|
||||
src: IdentID,
|
||||
},
|
||||
LoadData {
|
||||
dst: VarInstID,
|
||||
dst: IdentID,
|
||||
src: DataID,
|
||||
},
|
||||
LoadSlice {
|
||||
dst: VarInstID,
|
||||
dst: IdentID,
|
||||
src: DataID,
|
||||
},
|
||||
LoadFn {
|
||||
dst: VarInstID,
|
||||
dst: IdentID,
|
||||
src: FnID,
|
||||
},
|
||||
Call {
|
||||
dst: VarInstID,
|
||||
f: VarInstID,
|
||||
args: Vec<VarInstID>,
|
||||
dst: IdentID,
|
||||
f: IdentID,
|
||||
args: Vec<IdentID>,
|
||||
},
|
||||
AsmBlock {
|
||||
instructions: Vec<RV64Instruction>,
|
||||
args: Vec<AsmBlockArg>,
|
||||
},
|
||||
Ret {
|
||||
src: VarInstID,
|
||||
src: IdentID,
|
||||
},
|
||||
Construct {
|
||||
dst: VarInstID,
|
||||
struc: VarInstID,
|
||||
fields: HashMap<String, VarInstID>,
|
||||
dst: IdentID,
|
||||
struc: IdentID,
|
||||
fields: HashMap<String, IdentID>,
|
||||
},
|
||||
If {
|
||||
cond: VarInstID,
|
||||
cond: IdentID,
|
||||
body: Vec<UInstrInst>,
|
||||
},
|
||||
Loop {
|
||||
@@ -71,7 +71,7 @@ impl std::fmt::Debug for UInstrInst {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AsmBlockArg {
|
||||
pub var: VarInstID,
|
||||
pub var: IdentID,
|
||||
pub reg: Reg,
|
||||
pub ty: AsmBlockArgType,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{Type, UInstrInst, UInstruction};
|
||||
use super::{FnInst, ResErr, StructInst, Type, UInstrInst, UInstruction};
|
||||
use crate::{
|
||||
common::FileSpan,
|
||||
ir::{Len, ID},
|
||||
@@ -7,57 +7,9 @@ use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
pub type NamePath = Vec<String>;
|
||||
|
||||
// "effective" (externally visible) kinds
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum KindTy {
|
||||
Type,
|
||||
Var,
|
||||
Struct,
|
||||
Fn,
|
||||
}
|
||||
|
||||
impl KindTy {
|
||||
pub fn str(&self) -> &'static str {
|
||||
match self {
|
||||
KindTy::Type => "type",
|
||||
KindTy::Var => "variable",
|
||||
KindTy::Fn => "function",
|
||||
KindTy::Struct => "struct",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Kind {
|
||||
fn ty() -> KindTy;
|
||||
}
|
||||
|
||||
impl Kind for UFunc {
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Fn
|
||||
}
|
||||
}
|
||||
|
||||
impl Kind for UVar {
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Var
|
||||
}
|
||||
}
|
||||
|
||||
impl Kind for UStruct {
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Struct
|
||||
}
|
||||
}
|
||||
|
||||
impl Kind for Type {
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Type
|
||||
}
|
||||
}
|
||||
|
||||
pub type FnID = ID<UFunc>;
|
||||
pub type VarID = ID<UVar>;
|
||||
pub type VarInstID = ID<VarInst>;
|
||||
pub type IdentID = ID<UIdent>;
|
||||
pub type TypeID = ID<Type>;
|
||||
pub type GenericID = ID<UGeneric>;
|
||||
pub type StructID = ID<UStruct>;
|
||||
@@ -99,31 +51,33 @@ pub struct UVar {
|
||||
pub origin: Origin,
|
||||
pub ty: TypeID,
|
||||
pub parent: Option<VarID>,
|
||||
pub children: Vec<VarID>,
|
||||
pub children: HashMap<String, VarID>,
|
||||
}
|
||||
|
||||
/// these are more like "expressions", need to find good name
|
||||
/// eg. a::b::c::<T,U>.d.e
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VarInst {
|
||||
pub status: VarStatus,
|
||||
pub struct UIdent {
|
||||
pub status: IdentStatus,
|
||||
pub origin: Origin,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum VarStatus {
|
||||
pub enum IdentStatus {
|
||||
Var(VarID),
|
||||
Struct(StructID, Vec<TypeID>),
|
||||
Struct(StructInst),
|
||||
Fn(FnInst),
|
||||
Type(TypeID),
|
||||
Unres {
|
||||
path: ModPath,
|
||||
name: String,
|
||||
mem: MemberID,
|
||||
gargs: Vec<TypeID>,
|
||||
fields: Vec<MemberID>,
|
||||
},
|
||||
Partial {
|
||||
v: VarID,
|
||||
PartialVar {
|
||||
id: VarID,
|
||||
fields: Vec<MemberID>,
|
||||
},
|
||||
Failed(ResErr),
|
||||
Cooked,
|
||||
}
|
||||
|
||||
@@ -209,13 +163,3 @@ impl<'a> Iterator for InstrIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl VarInst {
|
||||
pub fn id(&self) -> Option<VarID> {
|
||||
match &self.status {
|
||||
VarStatus::Var(id) => Some(*id),
|
||||
VarStatus::Unres { .. } => None,
|
||||
VarStatus::Partial { .. } => None,
|
||||
VarStatus::Cooked => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ pub use kind::*;
|
||||
pub use program::*;
|
||||
pub use ty::*;
|
||||
pub use error::*;
|
||||
pub use resolve::*;
|
||||
|
||||
@@ -11,7 +11,7 @@ pub struct UProgram {
|
||||
pub data: Vec<UData>,
|
||||
pub generics: Vec<UGeneric>,
|
||||
pub vars: Vec<UVar>,
|
||||
pub vars_insts: Vec<VarInst>,
|
||||
pub idents: Vec<UIdent>,
|
||||
pub types: Vec<Type>,
|
||||
|
||||
pub vfmap: HashMap<VarID, FnID>,
|
||||
@@ -39,7 +39,7 @@ impl UProgram {
|
||||
Self {
|
||||
fns: Vec::new(),
|
||||
vars: Vec::new(),
|
||||
vars_insts: Vec::new(),
|
||||
idents: Vec::new(),
|
||||
structs: Vec::new(),
|
||||
types: Vec::new(),
|
||||
generics: Vec::new(),
|
||||
@@ -66,8 +66,8 @@ impl UProgram {
|
||||
push_id(&mut self.types, t)
|
||||
}
|
||||
|
||||
pub fn def_var_inst(&mut self, i: VarInst) -> VarInstID {
|
||||
push_id(&mut self.vars_insts, i)
|
||||
pub fn def_var_inst(&mut self, i: UIdent) -> IdentID {
|
||||
push_id(&mut self.idents, i)
|
||||
}
|
||||
|
||||
pub fn def_generic(&mut self, g: UGeneric) -> GenericID {
|
||||
@@ -85,12 +85,12 @@ impl UProgram {
|
||||
pub fn type_name(&self, ty: impl Typed) -> String {
|
||||
match ty.ty(self) {
|
||||
Type::Struct(ty) => {
|
||||
format!("{}{}", self.structs[ty.id].name, self.gparams_str(&ty.args))
|
||||
format!("{}{}", self.structs[ty.id].name, self.gparams_str(&ty.gargs))
|
||||
}
|
||||
Type::FnRef(ty) => {
|
||||
format!(
|
||||
"fn{}({}) -> {}",
|
||||
&self.gparams_str(&ty.args),
|
||||
&self.gparams_str(&ty.gargs),
|
||||
&self.type_list_str(self.fns[ty.id].args.iter().map(|v| self.vars[v].ty)),
|
||||
&self.type_name(self.fns[ty.id].ret)
|
||||
)
|
||||
@@ -146,21 +146,21 @@ impl<'a> UModuleBuilder<'a> {
|
||||
temp: 0,
|
||||
}
|
||||
}
|
||||
pub fn temp_var(&mut self, origin: Origin, ty: impl Typable) -> VarInstID {
|
||||
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) -> VarInstID {
|
||||
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: Vec::new(),
|
||||
children: HashMap::new(),
|
||||
};
|
||||
let id = self.p.def_var(var);
|
||||
self.temp += 1;
|
||||
self.def_var_inst(VarInst {
|
||||
status: VarStatus::Var(id),
|
||||
self.def_var_inst(UIdent {
|
||||
status: IdentStatus::Var(id),
|
||||
origin,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use super::{
|
||||
report_errs, ControlFlowOp, DataID, Kind, MemberTy, Origin, ResErr, Type, TypeID, TypeMismatch, UData, UFunc, UGeneric, UInstrInst, UInstruction, UModule, UProgram, UStruct, UVar, VarID, VarInst, VarInstID, VarStatus
|
||||
inst_fn_ty, inst_struct_ty, report_errs, ControlFlowOp, DataID, FnInst, IdentID, IdentStatus,
|
||||
MemberTy, Origin, ResErr, StructInst, Type, TypeID, TypeMismatch, UData, UFunc, UGeneric,
|
||||
UIdent, UInstrInst, UInstruction, UModule, UProgram, UStruct, UVar, VarID,
|
||||
};
|
||||
use crate::{
|
||||
common::{CompilerMsg, CompilerOutput},
|
||||
ir::{inst_fn_var, inst_struct_ty, KindTy, ID},
|
||||
ir::{inst_fn_var, ID},
|
||||
};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
@@ -21,7 +23,7 @@ impl UProgram {
|
||||
changed: false,
|
||||
types: &mut self.types,
|
||||
s: Sources {
|
||||
insts: &mut self.vars_insts,
|
||||
idents: &mut self.idents,
|
||||
vars: &mut self.vars,
|
||||
fns: &self.fns,
|
||||
structs: &self.structs,
|
||||
@@ -44,15 +46,14 @@ impl UProgram {
|
||||
}
|
||||
// this currently works bc expressions create temporary variables
|
||||
// although you can't do things like loop {return 3} (need to analyze control flow)
|
||||
if !matches!(data.types[f.ret], Type::Unit) {
|
||||
if f.instructions
|
||||
if !matches!(data.types[f.ret], Type::Unit)
|
||||
&& f.instructions
|
||||
.last()
|
||||
.is_none_or(|i| !matches!(i.i, UInstruction::Ret { .. }))
|
||||
{
|
||||
data.errs.push(ResErr::NoReturn { fid });
|
||||
}
|
||||
}
|
||||
}
|
||||
while !data.unfinished.is_empty() && data.changed {
|
||||
data.changed = false;
|
||||
std::mem::swap(&mut data.unfinished, &mut unfinished);
|
||||
@@ -60,7 +61,23 @@ impl UProgram {
|
||||
resolve_instr(&mut data, ctx);
|
||||
}
|
||||
}
|
||||
let errs = data.errs;
|
||||
let mut errs = data.errs;
|
||||
for ident in &self.idents {
|
||||
match &ident.status {
|
||||
IdentStatus::Unres {
|
||||
path,
|
||||
mem,
|
||||
gargs,
|
||||
fields,
|
||||
} => errs.push(ResErr::UnknownModule {
|
||||
origin: path.path[0].origin,
|
||||
name: path.path[0].name.clone(),
|
||||
}),
|
||||
IdentStatus::PartialVar { id, fields } => todo!(),
|
||||
IdentStatus::Failed(err) => errs.push(err.clone()),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
report_errs(self, output, errs);
|
||||
for var in &self.vars {
|
||||
match &self.types[var.ty] {
|
||||
@@ -93,13 +110,8 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
|
||||
let mut res = InstrRes::Finished;
|
||||
match &ctx.i.i {
|
||||
UInstruction::Call { dst, f, args } => {
|
||||
let fty = data.res_id(f, ctx)?;
|
||||
let Type::FnRef(ftyy) = data.types[fty].clone() else {
|
||||
let origin = f.origin(data);
|
||||
data.errs.push(ResErr::NotCallable { origin, ty: fty });
|
||||
return None;
|
||||
};
|
||||
let f = &data.s.fns[ftyy.id];
|
||||
let fi = data.res_id::<UFunc>(f, ctx)?;
|
||||
let f = &data.s.fns[fi.id];
|
||||
for (src, dest) in args.iter().zip(&f.args) {
|
||||
res |= data.match_types(dest, src, src);
|
||||
}
|
||||
@@ -109,14 +121,14 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
|
||||
res |= data.match_types(dst, src, src);
|
||||
}
|
||||
UInstruction::Ref { dst, src } => {
|
||||
let dstid = data.res_id(dst, ctx)?;
|
||||
let dstid = data.res_ty_id::<UVar>(dst, ctx)?;
|
||||
let Type::Ref(dest_ty) = data.types[dstid] else {
|
||||
compiler_error()
|
||||
};
|
||||
res |= data.match_types(dest_ty, src, src);
|
||||
}
|
||||
UInstruction::Deref { dst, src } => {
|
||||
let srcid = data.res_id(src, ctx)?;
|
||||
let srcid = data.res_ty_id::<UVar>(src, ctx)?;
|
||||
let Type::Ref(src_ty) = data.types[srcid] else {
|
||||
let origin = src.origin(data);
|
||||
data.errs.push(ResErr::CannotDeref { origin, ty: srcid });
|
||||
@@ -148,11 +160,8 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
|
||||
res |= data.match_types(ctx.ret, src, src);
|
||||
}
|
||||
UInstruction::Construct { dst, struc, fields } => {
|
||||
let id = data.res_id(dst, ctx, KindTy::Struct)?;
|
||||
let Type::Struct(sty) = &data.types[id] else {
|
||||
return None;
|
||||
};
|
||||
let sid = sty.id;
|
||||
let si = data.res_id::<UStruct>(dst, ctx)?;
|
||||
let sid = si.id;
|
||||
let st = &data.s.structs[sid];
|
||||
let mut used = HashSet::new();
|
||||
for (name, field) in &st.fields {
|
||||
@@ -180,7 +189,7 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
|
||||
}
|
||||
}
|
||||
UInstruction::If { cond, body } => {
|
||||
if let Some(id) = data.res_id(cond, ctx, KindTy::Var) {
|
||||
if let Some(id) = data.res_ty_id::<UVar>(cond, ctx) {
|
||||
if !matches!(data.types[id], Type::Bits(64)) {
|
||||
let origin = cond.origin(data);
|
||||
data.errs.push(ResErr::CondType { origin, ty: id });
|
||||
@@ -262,7 +271,7 @@ pub fn match_types(data: &mut TypeResData, dst: impl TypeIDed, src: impl TypeIDe
|
||||
if dest.id != src.id {
|
||||
return error();
|
||||
}
|
||||
match_all(data, dest.args.iter().cloned(), src.args.iter().cloned())
|
||||
match_all(data, dest.gargs.iter().cloned(), src.gargs.iter().cloned())
|
||||
}
|
||||
// (
|
||||
// Type::Fn {
|
||||
@@ -327,7 +336,7 @@ fn match_all(
|
||||
}
|
||||
|
||||
struct Sources<'a> {
|
||||
insts: &'a mut [VarInst],
|
||||
idents: &'a mut [UIdent],
|
||||
vars: &'a mut Vec<UVar>,
|
||||
fns: &'a [UFunc],
|
||||
structs: &'a [UStruct],
|
||||
@@ -353,12 +362,12 @@ struct TypeResData<'a> {
|
||||
impl<'a> ResData<'a> {
|
||||
pub fn match_types(
|
||||
&mut self,
|
||||
dst: impl ResID<Type>,
|
||||
src: impl ResID<Type>,
|
||||
dst: impl Resolvable<Type>,
|
||||
src: impl Resolvable<Type>,
|
||||
origin: impl HasOrigin,
|
||||
) -> InstrRes {
|
||||
let dst = dst.try_id(&mut self.s, self.types, &mut self.errs, KindTy::Type)?;
|
||||
let src = src.try_id(&mut self.s, self.types, &mut self.errs, KindTy::Type)?;
|
||||
let dst = dst.try_res(&mut self.s, self.types, &mut self.errs)?;
|
||||
let src = src.try_res(&mut self.s, self.types, &mut self.errs)?;
|
||||
let res = match_types(
|
||||
&mut TypeResData {
|
||||
changed: &mut self.changed,
|
||||
@@ -382,15 +391,24 @@ impl<'a> ResData<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn try_res_id<K>(&mut self, x: impl ResID) -> Result<ID<K>, InstrRes> {
|
||||
x.try_id(&mut self.s, &mut self.types, &mut self.errs)
|
||||
.map(|id| resolve_refs(self.types, id))
|
||||
pub fn try_res_id<K: ResKind>(&mut self, x: impl Resolvable<K>) -> Result<K::Res, InstrRes> {
|
||||
x.try_res(&mut self.s, &mut self.types, &mut self.errs)
|
||||
}
|
||||
pub fn res_id<'b: 'a, K>(
|
||||
pub fn res_ty_id<'b: 'a, K: ResKind>(
|
||||
&mut self,
|
||||
x: impl ResID<K>,
|
||||
x: impl Resolvable<K>,
|
||||
ctx: ResolveCtx<'b>,
|
||||
) -> Option<ID<K>> {
|
||||
) -> Option<TypeID>
|
||||
where
|
||||
K::Res: TypeIDed,
|
||||
{
|
||||
self.res_id::<K>(x, ctx).map(|i| i.type_id(&self.s))
|
||||
}
|
||||
pub fn res_id<'b: 'a, K: ResKind>(
|
||||
&mut self,
|
||||
x: impl Resolvable<K>,
|
||||
ctx: ResolveCtx<'b>,
|
||||
) -> Option<K::Res> {
|
||||
match self.try_res_id(x) {
|
||||
Ok(id) => return Some(id),
|
||||
Err(InstrRes::Unfinished) => self.unfinished.push(ctx),
|
||||
@@ -433,166 +451,293 @@ impl FromResidual<Option<Infallible>> for InstrRes {
|
||||
}
|
||||
}
|
||||
|
||||
trait ResID<K> {
|
||||
fn try_id(
|
||||
trait Resolvable<K: ResKind> {
|
||||
fn try_res(
|
||||
&self,
|
||||
s: &mut Sources,
|
||||
types: &mut Vec<Type>,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Result<ID<K>, InstrRes>;
|
||||
) -> Result<K::Res, InstrRes>;
|
||||
}
|
||||
|
||||
impl<T: TypeIDed> ResID<Type> for T {
|
||||
fn try_id(
|
||||
impl<T: TypeIDed> Resolvable<Type> for T {
|
||||
fn try_res(
|
||||
&self,
|
||||
s: &mut Sources,
|
||||
_: &mut Vec<Type>,
|
||||
errs: &mut Vec<ResErr>,
|
||||
kind: KindTy,
|
||||
) -> Result<TypeID, InstrRes> {
|
||||
Ok(self.type_id(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl VarInst {
|
||||
pub fn resolve(&mut self, s: &mut Sources) {
|
||||
match &self.status {
|
||||
VarStatus::Var(id) => self.status = VarStatus::Cooked,
|
||||
VarStatus::Struct(id, ids) => todo!(),
|
||||
VarStatus::Unres { path, name, gargs, fields } => todo!(),
|
||||
VarStatus::Partial { v, fields } => todo!(),
|
||||
VarStatus::Cooked => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Kind> ResID<K> for VarInstID {
|
||||
fn try_id(
|
||||
&self,
|
||||
s: &mut Sources,
|
||||
types: &mut Vec<Type>,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Result<ID<K>, InstrRes> {
|
||||
let kind = K::ty();
|
||||
let inst = &mut s.insts[self];
|
||||
let (id, fields) = match &mut inst.status {
|
||||
VarStatus::Var(id) => {
|
||||
return Ok(s.vars[id].ty)
|
||||
},
|
||||
VarStatus::Unres {
|
||||
impl IdentID {
|
||||
pub fn resolve(self, s: &mut Sources) -> Result<Res, InstrRes> {
|
||||
let ident = &mut s.idents[self];
|
||||
Ok(match &mut ident.status {
|
||||
IdentStatus::Var(id) => Res::Var(*id),
|
||||
IdentStatus::Struct(sty) => Res::Struct(sty.clone()),
|
||||
IdentStatus::Fn(fty) => Res::Fn(fty.clone()),
|
||||
IdentStatus::Type(ty) => Res::Type(*ty),
|
||||
IdentStatus::Unres {
|
||||
path,
|
||||
name,
|
||||
mem,
|
||||
gargs,
|
||||
fields,
|
||||
} => {
|
||||
let mut mid = path.id;
|
||||
let mut depth = 0;
|
||||
let mut count = 0;
|
||||
for mem in &path.path {
|
||||
let Some(&child) = s.modules[mid].children.get(&mem.name) else {
|
||||
break;
|
||||
};
|
||||
depth += 1;
|
||||
count += 1;
|
||||
mid = child;
|
||||
}
|
||||
path.path.drain(0..depth);
|
||||
path.path.drain(0..count);
|
||||
path.id = mid;
|
||||
if path.path.len() != 0 {
|
||||
return Err(InstrRes::Unfinished);
|
||||
}
|
||||
let Some(mem) = s.modules[mid].members.get(name) else {
|
||||
let Some(mem) = s.modules[mid].members.get(&mem.name) else {
|
||||
return Err(InstrRes::Unfinished);
|
||||
};
|
||||
let vid = match mem.id {
|
||||
match mem.id {
|
||||
MemberTy::Fn(id) => {
|
||||
if kind == KindTy::Fn {
|
||||
return Ok(id.0.into());
|
||||
}
|
||||
if !matches!(kind, KindTy::Var | KindTy::Fn) {
|
||||
errs.push(ResErr::KindMismatch {
|
||||
origin: inst.origin,
|
||||
expected: kind,
|
||||
found: KindTy::Fn,
|
||||
id: id.0,
|
||||
if fields.len() > 0 {
|
||||
ident.status = IdentStatus::Failed(ResErr::UnexpectedField {
|
||||
origin: ident.origin,
|
||||
});
|
||||
return Err(InstrRes::Finished);
|
||||
}
|
||||
inst_fn_var(
|
||||
let fty = FnInst {
|
||||
id,
|
||||
s.fns,
|
||||
gargs,
|
||||
inst.origin,
|
||||
s.vars,
|
||||
types,
|
||||
s.generics,
|
||||
errs,
|
||||
)
|
||||
gargs: gargs.clone(),
|
||||
};
|
||||
ident.status = IdentStatus::Fn(fty.clone());
|
||||
Res::Fn(fty)
|
||||
}
|
||||
MemberTy::Struct(id) => {
|
||||
if fields.len() > 0 {
|
||||
ident.status = IdentStatus::Failed(ResErr::UnexpectedField {
|
||||
origin: ident.origin,
|
||||
});
|
||||
return Err(InstrRes::Finished);
|
||||
}
|
||||
let sty = StructInst {
|
||||
id,
|
||||
gargs: gargs.clone(),
|
||||
};
|
||||
ident.status = IdentStatus::Struct(sty.clone());
|
||||
Res::Struct(sty)
|
||||
}
|
||||
MemberTy::Var(id) => {
|
||||
if !matches!(kind, KindTy::Var | KindTy::Any) {
|
||||
errs.push(ResErr::KindMismatch {
|
||||
origin: inst.origin,
|
||||
expected: kind,
|
||||
found: KindTy::Var,
|
||||
id: id.0,
|
||||
});
|
||||
return Err(InstrRes::Finished);
|
||||
}
|
||||
if !gargs.is_empty() {
|
||||
errs.push(ResErr::GenericCount {
|
||||
origin: inst.origin,
|
||||
ident.status = IdentStatus::Failed(ResErr::GenericCount {
|
||||
origin: ident.origin,
|
||||
expected: 0,
|
||||
found: gargs.len(),
|
||||
});
|
||||
}
|
||||
id
|
||||
}
|
||||
MemberTy::Struct(id) => {
|
||||
if !matches!(kind, KindTy::Struct | KindTy::Type | KindTy::Any) {
|
||||
errs.push(ResErr::KindMismatch {
|
||||
origin: inst.origin,
|
||||
expected: kind,
|
||||
found: KindTy::Struct,
|
||||
id: id.0,
|
||||
});
|
||||
return Err(InstrRes::Finished);
|
||||
}
|
||||
if fields.len() > 0 {
|
||||
errs.push(ResErr::UnexpectedField {
|
||||
origin: inst.origin,
|
||||
});
|
||||
return Err(InstrRes::Finished);
|
||||
}
|
||||
return Ok(inst_struct_ty(
|
||||
id, s.structs, gargs, types, s.generics, errs,
|
||||
));
|
||||
}
|
||||
};
|
||||
if fields.len() > 0 {
|
||||
inst.status = VarStatus::Partial{v: vid, fields}
|
||||
}
|
||||
}
|
||||
VarStatus::Partial { v, fields } => (*v, fields),
|
||||
VarStatus::Cooked => return Err(InstrRes::Finished),
|
||||
};
|
||||
// I feel like this clone is not necessary but idk how
|
||||
inst.status = VarStatus::Partial {
|
||||
v: id,
|
||||
ident.status = IdentStatus::PartialVar {
|
||||
id,
|
||||
fields: fields.clone(),
|
||||
};
|
||||
// let VarStatus::Partial { v, fields } = inst.status
|
||||
todo!()
|
||||
return self.resolve(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
IdentStatus::PartialVar { id, fields } => {
|
||||
let mut fiter = fields.iter();
|
||||
let mut next = fiter.next();
|
||||
let mut count = 0;
|
||||
while let Some(mem) = next
|
||||
&& let Some(&cid) = s.vars[*id].children.get(&mem.name)
|
||||
{
|
||||
*id = cid;
|
||||
next = fiter.next();
|
||||
count += 1;
|
||||
}
|
||||
fields.drain(0..count);
|
||||
if fields.len() != 0 {
|
||||
return Err(InstrRes::Unfinished);
|
||||
}
|
||||
let id = *id;
|
||||
ident.status = IdentStatus::Var(id);
|
||||
Res::Var(id)
|
||||
}
|
||||
IdentStatus::Cooked => return Err(InstrRes::Finished),
|
||||
IdentStatus::Failed(_) => return Err(InstrRes::Finished),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> ResID<K> for &VarInstID {
|
||||
fn try_id(
|
||||
impl<K: ResKind> Resolvable<K> for IdentID {
|
||||
fn try_res(
|
||||
&self,
|
||||
s: &mut Sources,
|
||||
types: &mut Vec<Type>,
|
||||
errs: &mut Vec<ResErr>,
|
||||
kind: KindTy,
|
||||
) -> Result<ID<K>, InstrRes> {
|
||||
(*self).try_id(s, types, errs, kind)
|
||||
) -> Result<K::Res, InstrRes> {
|
||||
let origin = s.idents[self].origin;
|
||||
let res = self.resolve(s)?;
|
||||
match K::from_res(res.clone(), types, s, origin, errs) {
|
||||
Some(res) => Ok(res),
|
||||
None => {
|
||||
errs.push(ResErr::KindMismatch {
|
||||
origin,
|
||||
expected: K::ty(),
|
||||
found: res,
|
||||
});
|
||||
Err(InstrRes::Finished)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "effective" (externally visible) kinds
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum KindTy {
|
||||
Type,
|
||||
Var,
|
||||
Struct,
|
||||
Fn,
|
||||
}
|
||||
|
||||
impl KindTy {
|
||||
pub fn str(&self) -> &'static str {
|
||||
match self {
|
||||
KindTy::Type => "type",
|
||||
KindTy::Var => "variable",
|
||||
KindTy::Fn => "function",
|
||||
KindTy::Struct => "struct",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Res {
|
||||
Var(VarID),
|
||||
Fn(FnInst),
|
||||
Struct(StructInst),
|
||||
Type(TypeID),
|
||||
}
|
||||
|
||||
impl Res {
|
||||
pub fn kind(&self) -> KindTy {
|
||||
match self {
|
||||
Res::Var(..) => KindTy::Var,
|
||||
Res::Fn(..) => KindTy::Fn,
|
||||
Res::Struct(..) => KindTy::Struct,
|
||||
Res::Type(..) => KindTy::Type,
|
||||
}
|
||||
}
|
||||
pub fn kind_str(&self) -> &'static str {
|
||||
self.kind().str()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ResKind {
|
||||
type Res;
|
||||
fn ty() -> KindTy;
|
||||
fn from_res(
|
||||
res: Res,
|
||||
types: &mut Vec<Type>,
|
||||
s: &mut Sources,
|
||||
origin: Origin,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Option<Self::Res>;
|
||||
}
|
||||
|
||||
impl ResKind for UFunc {
|
||||
type Res = FnInst;
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Fn
|
||||
}
|
||||
fn from_res(
|
||||
res: Res,
|
||||
_: &mut Vec<Type>,
|
||||
_: &mut Sources,
|
||||
_: Origin,
|
||||
_: &mut Vec<ResErr>,
|
||||
) -> Option<Self::Res> {
|
||||
match res {
|
||||
Res::Fn(fi) => Some(fi),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResKind for UVar {
|
||||
type Res = VarID;
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Var
|
||||
}
|
||||
fn from_res(
|
||||
res: Res,
|
||||
types: &mut Vec<Type>,
|
||||
s: &mut Sources,
|
||||
origin: Origin,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Option<Self::Res> {
|
||||
Some(match res {
|
||||
Res::Fn(fty) => inst_fn_var(&fty, s.fns, origin, s.vars, types, s.generics, errs),
|
||||
Res::Var(id) => id,
|
||||
Res::Struct(_) => return None,
|
||||
Res::Type(_) => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ResKind for UStruct {
|
||||
type Res = StructInst;
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Struct
|
||||
}
|
||||
fn from_res(
|
||||
res: Res,
|
||||
_: &mut Vec<Type>,
|
||||
_: &mut Sources,
|
||||
_: Origin,
|
||||
_: &mut Vec<ResErr>,
|
||||
) -> Option<Self::Res> {
|
||||
match res {
|
||||
Res::Struct(si) => Some(si),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResKind for Type {
|
||||
type Res = TypeID;
|
||||
fn ty() -> KindTy {
|
||||
KindTy::Type
|
||||
}
|
||||
fn from_res(
|
||||
res: Res,
|
||||
types: &mut Vec<Type>,
|
||||
s: &mut Sources,
|
||||
_: Origin,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Option<Self::Res> {
|
||||
Some(match res {
|
||||
Res::Fn(fty) => inst_fn_ty(&fty, s.fns, types, s.generics, errs),
|
||||
Res::Var(id) => id.type_id(s),
|
||||
Res::Struct(si) => inst_struct_ty(&si, s.structs, types, s.generics, errs),
|
||||
Res::Type(id) => id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: ResKind> Resolvable<K> for &IdentID {
|
||||
fn try_res(
|
||||
&self,
|
||||
s: &mut Sources,
|
||||
types: &mut Vec<Type>,
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> Result<K::Res, InstrRes> {
|
||||
Resolvable::<K>::try_res(*self, s, types, errs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,8 +782,8 @@ trait HasOrigin {
|
||||
fn origin(&self, data: &ResData) -> Origin;
|
||||
}
|
||||
|
||||
impl HasOrigin for &VarInstID {
|
||||
impl HasOrigin for &IdentID {
|
||||
fn origin(&self, data: &ResData) -> Origin {
|
||||
data.s.insts[*self].origin
|
||||
data.s.idents[*self].origin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{
|
||||
push_id, FnID, GenericID, Len, ModPath, Origin, ResErr, StructID, TypeCache, TypeID, UFunc,
|
||||
UGeneric, UProgram, UStruct, UVar, VarID,
|
||||
push_id, FnID, GenericID, Len, ModPath, Origin, ResErr, StructID, TypeID, UFunc, UGeneric,
|
||||
UProgram, UStruct, UVar, VarID,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
@@ -11,23 +11,23 @@ pub struct FieldRef {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub struct StructTy {
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct StructInst {
|
||||
pub id: StructID,
|
||||
pub args: Vec<TypeID>,
|
||||
pub gargs: Vec<TypeID>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub struct FnTy {
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct FnInst {
|
||||
pub id: FnID,
|
||||
pub args: Vec<TypeID>,
|
||||
pub gargs: Vec<TypeID>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Type {
|
||||
Bits(u32),
|
||||
Struct(StructTy),
|
||||
FnRef(FnTy),
|
||||
Struct(StructInst),
|
||||
FnRef(FnInst),
|
||||
// this can be added for constraints later (F: fn(...) -> ...)
|
||||
// Fn { args: Vec<TypeID>, ret: TypeID },
|
||||
Ref(TypeID),
|
||||
@@ -79,17 +79,16 @@ impl Type {
|
||||
}
|
||||
|
||||
pub fn inst_fn_var(
|
||||
id: FnID,
|
||||
fi: &FnInst,
|
||||
fns: &[UFunc],
|
||||
gargs: &[TypeID],
|
||||
origin: Origin,
|
||||
vars: &mut Vec<UVar>,
|
||||
types: &mut Vec<Type>,
|
||||
generics: &[UGeneric],
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> VarID {
|
||||
let ty = inst_fn_ty(id, fns, gargs, types, generics, errs);
|
||||
let name = fns[id].name.clone();
|
||||
let ty = inst_fn_ty(fi, fns, types, generics, errs);
|
||||
let name = fns[fi.id].name.clone();
|
||||
push_id(
|
||||
vars,
|
||||
UVar {
|
||||
@@ -97,39 +96,37 @@ pub fn inst_fn_var(
|
||||
origin,
|
||||
ty,
|
||||
parent: None,
|
||||
children: Vec::new(),
|
||||
children: HashMap::new(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn inst_fn_ty(
|
||||
id: FnID,
|
||||
fi: &FnInst,
|
||||
fns: &[UFunc],
|
||||
gargs: &[TypeID],
|
||||
types: &mut Vec<Type>,
|
||||
generics: &[UGeneric],
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> TypeID {
|
||||
let f = &fns[id];
|
||||
let ty = Type::FnRef(FnTy {
|
||||
id,
|
||||
args: inst_generics(&f.gargs, gargs, types, generics, errs),
|
||||
let f = &fns[fi.id];
|
||||
let ty = Type::FnRef(FnInst {
|
||||
id: fi.id,
|
||||
gargs: inst_generics(&f.gargs, &fi.gargs, types, generics, errs),
|
||||
});
|
||||
push_id(types, ty)
|
||||
}
|
||||
|
||||
pub fn inst_struct_var(
|
||||
id: StructID,
|
||||
si: &StructInst,
|
||||
structs: &[UStruct],
|
||||
gargs: &[TypeID],
|
||||
origin: Origin,
|
||||
vars: &mut Vec<UVar>,
|
||||
types: &mut Vec<Type>,
|
||||
generics: &[UGeneric],
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> VarID {
|
||||
let ty = inst_struct_ty(id, structs, gargs, types, generics, errs);
|
||||
let name = structs[id].name.clone();
|
||||
let ty = inst_struct_ty(si, structs, types, generics, errs);
|
||||
let name = structs[si.id].name.clone();
|
||||
push_id(
|
||||
vars,
|
||||
UVar {
|
||||
@@ -137,23 +134,22 @@ pub fn inst_struct_var(
|
||||
origin,
|
||||
ty,
|
||||
parent: None,
|
||||
children: Vec::new(),
|
||||
children: HashMap::new(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn inst_struct_ty(
|
||||
id: StructID,
|
||||
si: &StructInst,
|
||||
structs: &[UStruct],
|
||||
gargs: &[TypeID],
|
||||
types: &mut Vec<Type>,
|
||||
generics: &[UGeneric],
|
||||
errs: &mut Vec<ResErr>,
|
||||
) -> TypeID {
|
||||
let s = &structs[id];
|
||||
let ty = Type::Struct(StructTy {
|
||||
id,
|
||||
args: inst_generics(&s.gargs, gargs, types, generics, errs),
|
||||
let s = &structs[si.id];
|
||||
let ty = Type::Struct(StructInst {
|
||||
id: si.id,
|
||||
gargs: inst_generics(&s.gargs, &si.gargs, types, generics, errs),
|
||||
});
|
||||
push_id(types, ty)
|
||||
}
|
||||
@@ -204,18 +200,18 @@ pub fn inst_type_ins(
|
||||
) -> TypeID {
|
||||
let ty = match types[id].clone() {
|
||||
Type::Bits(_) => return id,
|
||||
Type::Struct(struct_ty) => Type::Struct(StructTy {
|
||||
Type::Struct(struct_ty) => Type::Struct(StructInst {
|
||||
id: struct_ty.id,
|
||||
args: struct_ty
|
||||
.args
|
||||
gargs: struct_ty
|
||||
.gargs
|
||||
.iter()
|
||||
.map(|id| inst_type(*id, types, gmap))
|
||||
.collect(),
|
||||
}),
|
||||
Type::FnRef(fn_ty) => Type::FnRef(FnTy {
|
||||
Type::FnRef(fn_ty) => Type::FnRef(FnInst {
|
||||
id: fn_ty.id,
|
||||
args: fn_ty
|
||||
.args
|
||||
gargs: fn_ty
|
||||
.gargs
|
||||
.iter()
|
||||
.map(|id| inst_type(*id, types, gmap))
|
||||
.collect(),
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
compiler::arch::riscv::*,
|
||||
ir::{
|
||||
arch::riscv64::{RV64Instruction, RegRef},
|
||||
VarInst,
|
||||
UIdent,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -166,7 +166,7 @@ impl RV64Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<UIdent> {
|
||||
let PAsmArg::Ref(node) = node.inner.as_ref()? else {
|
||||
ctx.err_at(
|
||||
node.origin,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::{
|
||||
compiler::arch::riscv::Reg,
|
||||
ir::{
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, VarInst,
|
||||
VarInstID,
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, UIdent,
|
||||
IdentID,
|
||||
},
|
||||
parser::PAsmBlockArg,
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable, PAsmBlock, PInstruction, PUAsmBlockArg};
|
||||
|
||||
type PLAsmBlockArg = PAsmBlockArg<Reg, VarInstID>;
|
||||
type PLAsmBlockArg = PAsmBlockArg<Reg, IdentID>;
|
||||
|
||||
impl FnLowerable for PInstruction {
|
||||
type Output = RV64Instruction;
|
||||
@@ -20,7 +20,7 @@ impl FnLowerable for PInstruction {
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlock {
|
||||
type Output = VarInstID;
|
||||
type Output = IdentID;
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::{
|
||||
ir::{Type, UInstruction, UVar, VarInst, VarInstID},
|
||||
ir::{Type, UInstruction, UVar, UIdent, IdentID},
|
||||
parser::{PConstStatement, PStatementLike},
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable, Import, PBlock, PStatement};
|
||||
|
||||
impl FnLowerable for PBlock {
|
||||
type Output = VarInstID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInstID> {
|
||||
type Output = IdentID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<IdentID> {
|
||||
let mut last = None;
|
||||
let mut statements = Vec::new();
|
||||
let mut fn_nodes = Vec::new();
|
||||
@@ -74,8 +74,8 @@ impl FnLowerable for PBlock {
|
||||
}
|
||||
|
||||
impl FnLowerable for PStatement {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
type Output = UIdent;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<UIdent> {
|
||||
match self {
|
||||
PStatement::Let(def, e) => {
|
||||
let def = def.lower(ctx.b, ctx.output)?;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::ir::{UProgram, UVar, VarID, VarInst};
|
||||
use crate::ir::{UProgram, UVar, VarID, UIdent};
|
||||
|
||||
use super::{CompilerOutput, Node, PVarDef};
|
||||
|
||||
@@ -10,7 +10,7 @@ impl Node<PVarDef> {
|
||||
Some(ty) => ty.lower(program, output),
|
||||
None => program.infer(self.origin),
|
||||
};
|
||||
Some(VarInst {
|
||||
Some(UIdent {
|
||||
id: program.def_searchable(name, Some(UVar { ty }), self.origin),
|
||||
origin: self.origin,
|
||||
})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, PostfixOp};
|
||||
use crate::{
|
||||
ir::{Type, UData, UInstruction, VarInst, VarInstID},
|
||||
ir::{Type, UData, UInstruction, UIdent, IdentID},
|
||||
parser::InfixOp,
|
||||
};
|
||||
|
||||
impl FnLowerable for PExpr {
|
||||
type Output = VarInstID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInstID> {
|
||||
type Output = IdentID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<IdentID> {
|
||||
let mut e = self;
|
||||
let mut path = Vec::new();
|
||||
while let PExpr::Member(node, ident) = e {
|
||||
|
||||
@@ -7,7 +7,7 @@ use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, P
|
||||
use crate::{
|
||||
ir::{
|
||||
FnID, GenericID, ModPath, Origin, Typable, Type, UFunc, UInstrInst, UInstruction,
|
||||
UModuleBuilder, VarID, VarInst, VarInstID, VarStatus,
|
||||
UModuleBuilder, VarID, UIdent, IdentID, IdentStatus,
|
||||
},
|
||||
parser,
|
||||
util::NameStack,
|
||||
@@ -68,7 +68,7 @@ impl PFunction {
|
||||
let res = self.body.lower(&mut ctx);
|
||||
let mut instructions = ctx.instructions;
|
||||
if let Some(src) = res {
|
||||
let origin = b.vars_insts[src].origin;
|
||||
let origin = b.idents[src].origin;
|
||||
instructions.push(UInstrInst {
|
||||
origin,
|
||||
i: UInstruction::Ret { src },
|
||||
@@ -99,13 +99,13 @@ pub struct FnLowerCtx<'a, 'b> {
|
||||
}
|
||||
|
||||
impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
pub fn var(&mut self, node: &Node<parser::PIdent>) -> VarInstID {
|
||||
let inst = VarInst {
|
||||
pub fn var(&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) {
|
||||
VarStatus::Var(var)
|
||||
IdentStatus::Var(var)
|
||||
} else {
|
||||
VarStatus::Unres {
|
||||
IdentStatus::Unres {
|
||||
path: ModPath {
|
||||
id: self.b.module,
|
||||
path: Vec::new(),
|
||||
@@ -116,7 +116,7 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VarStatus::Cooked
|
||||
IdentStatus::Cooked
|
||||
},
|
||||
origin: node.origin,
|
||||
};
|
||||
@@ -128,7 +128,7 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
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) -> VarInstID {
|
||||
pub fn temp<T: Typable>(&mut self, ty: T) -> IdentID {
|
||||
self.b.temp_var(self.origin, ty)
|
||||
}
|
||||
pub fn push(&mut self, i: UInstruction) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{ir::VarInstID, parser::PMap};
|
||||
use crate::{ir::IdentID, parser::PMap};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable};
|
||||
|
||||
impl FnLowerable for PMap {
|
||||
type Output = HashMap<String, VarInstID>;
|
||||
type Output = HashMap<String, IdentID>;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
Some(
|
||||
self.0
|
||||
|
||||
Reference in New Issue
Block a user