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