uh oh, I need to actually switch to struct subvars and resolve pointer variables
This commit is contained in:
+28
-54
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use super::{assoc::NamePath, GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID};
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct MemberRef {
|
||||
pub struct FieldRef {
|
||||
pub parent: VarID,
|
||||
pub name: String,
|
||||
}
|
||||
@@ -18,54 +18,55 @@ pub struct StructTy {
|
||||
pub enum Type {
|
||||
Bits(u32),
|
||||
Struct(StructTy),
|
||||
// is this real? I don't know, it's kind of like infer
|
||||
Generic { id: GenericID },
|
||||
Fn { args: Vec<Type>, ret: Box<Type> },
|
||||
Ref(Box<Type>),
|
||||
Slice(Box<Type>),
|
||||
Array(Box<Type>, Len),
|
||||
Member(MemberRef),
|
||||
Unit,
|
||||
// fake types
|
||||
Field(FieldRef),
|
||||
Module(NamePath),
|
||||
Infer,
|
||||
Error,
|
||||
Placeholder,
|
||||
Unit,
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn is_resolved(&self) -> bool {
|
||||
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
|
||||
}
|
||||
pub fn rf(self) -> Self {
|
||||
Self::Ref(Box::new(self))
|
||||
Type::Ref(Box::new(self))
|
||||
}
|
||||
pub fn arr(self, len: Len) -> Self {
|
||||
Self::Array(Box::new(self), len)
|
||||
Type::Array(Box::new(self), len)
|
||||
}
|
||||
pub fn slice(self) -> Self {
|
||||
Self::Slice(Box::new(self))
|
||||
}
|
||||
pub fn is_real(&self) -> bool {
|
||||
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
|
||||
Type::Slice(Box::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl UProgram {
|
||||
pub fn resolve_types(&mut self) {
|
||||
// I LOVE RUST
|
||||
let mut vars = self.vars.clone();
|
||||
// set type of vars referring to functions
|
||||
for (i, f) in self.iter_fns() {
|
||||
let vi = self.fn_var.var(i);
|
||||
vars[vi.0].as_mut().expect("bruh").ty = f.ty(self);
|
||||
// PARTIAL BORROWING :SOB:
|
||||
let fns: Vec<_> = self.cloned_fns().collect();
|
||||
for (i, f) in &fns {
|
||||
let vi = self.fn_var.var(*i);
|
||||
self.expect_mut(vi).ty = f.ty(self);
|
||||
}
|
||||
for (i, f) in self.iter_fns() {
|
||||
for (i, f) in &fns {
|
||||
let mut redo_iter = Vec::new();
|
||||
let mut redo_new = Vec::new();
|
||||
for i in f.flat_iter() {
|
||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
||||
if self.resolve_instr_types(&i.i).is_none() {
|
||||
redo_iter.push(i);
|
||||
}
|
||||
}
|
||||
while !redo_iter.is_empty() {
|
||||
for &i in &redo_iter {
|
||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
||||
if self.resolve_instr_types(&i.i).is_none() {
|
||||
redo_new.push(i);
|
||||
}
|
||||
}
|
||||
@@ -73,19 +74,19 @@ impl UProgram {
|
||||
redo_new.clear();
|
||||
}
|
||||
}
|
||||
self.vars = vars;
|
||||
}
|
||||
|
||||
pub fn resolve_instr_types(&self, vars: &mut [Option<UVar>], i: &UInstruction) -> Option<()> {
|
||||
pub fn resolve_instr_types(&mut self, i: &UInstruction) -> Option<()> {
|
||||
'outer: {
|
||||
match &i {
|
||||
UInstruction::Call { dest, f, args } => {
|
||||
let fun = self.get_fn_var(f.id).expect("bruh");
|
||||
vars[dest.id.0].as_mut().expect("bruh").ty = fun.ret.clone();
|
||||
self.expect_mut(dest.id).ty = fun.ret.clone();
|
||||
for (src, &dest) in args.iter().zip(&fun.args) {
|
||||
let dest_ty = get(vars, dest)?;
|
||||
let src_ty = get(vars, src.id)?;
|
||||
let dest_ty = self.get_type(dest)?;
|
||||
let src_ty = self.get_type(src.id)?;
|
||||
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
||||
self.expect_mut(dest).ty = ty.clone();
|
||||
set(vars, dest, ty.clone());
|
||||
set(vars, src.id, ty);
|
||||
}
|
||||
@@ -166,13 +167,16 @@ impl UProgram {
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn match_types(&self, dest: &Type, src: &Type) -> Option<Type> {
|
||||
pub fn match_types<'a>(&'a self, mut dest: &'a Type, mut src: &'a Type) -> Option<Type> {
|
||||
dest = self.follow_type(dest)?;
|
||||
src = self.follow_type(src)?;
|
||||
if dest == src {
|
||||
return None;
|
||||
}
|
||||
match (dest, src) {
|
||||
(Type::Error, _) | (_, Type::Error) => None,
|
||||
(Type::Placeholder, _) | (_, Type::Placeholder) => None,
|
||||
(Type::Infer, Type::Infer) => None,
|
||||
(Type::Infer, x) | (x, Type::Infer) => Some(x.clone()),
|
||||
// TODO: handle constraints?
|
||||
(Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()),
|
||||
@@ -223,33 +227,3 @@ impl UProgram {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(vars: &[Option<UVar>], id: VarID) -> Option<&Type> {
|
||||
let mut var = vars[id.0]
|
||||
.as_ref()
|
||||
.expect("PARTIAL BORROWING WOULD BE REALLY COOL");
|
||||
if var.ty == Type::Placeholder {
|
||||
return None;
|
||||
}
|
||||
while let Type::Member(m) = &var.ty {
|
||||
var = vars[m.parent.0].as_ref().expect("xd");
|
||||
}
|
||||
// x.y().z == a.b.c()
|
||||
// 0 ------- member(1, z)
|
||||
// 1 ----- call(2)
|
||||
// 2 --- member(3, y)
|
||||
// 3 - x
|
||||
//
|
||||
// 0 ------- call(1)
|
||||
// 1 ----- member(c, 2)
|
||||
// 2 --- member(b, 3)
|
||||
// 3 - a
|
||||
Some(&var.ty)
|
||||
}
|
||||
|
||||
pub fn set(vars: &mut [Option<UVar>], id: VarID, ty: Type) {
|
||||
vars[id.0]
|
||||
.as_mut()
|
||||
.expect("PARTIAL BORROWING WOULD BE REALLY COOL")
|
||||
.ty = ty;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user