going insane (not working yet)
This commit is contained in:
+101
-108
@@ -1,16 +1,30 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID};
|
||||
use super::{assoc::NamePath, GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID};
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct MemberRef {
|
||||
pub parent: VarID,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||
pub struct StructTy {
|
||||
pub id: StructID,
|
||||
pub args: Vec<Type>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Type {
|
||||
Bits(u32),
|
||||
Struct { id: StructID, args: Vec<Type> },
|
||||
Struct(StructTy),
|
||||
Generic { id: GenericID },
|
||||
Fn { args: Vec<Type>, ret: Box<Type> },
|
||||
Ref(Box<Type>),
|
||||
Slice(Box<Type>),
|
||||
Array(Box<Type>, Len),
|
||||
Member(MemberRef),
|
||||
Module(NamePath),
|
||||
Infer,
|
||||
Error,
|
||||
Placeholder,
|
||||
@@ -43,37 +57,16 @@ impl UProgram {
|
||||
}
|
||||
for (i, f) in self.iter_fns() {
|
||||
let mut redo_iter = Vec::new();
|
||||
let mut ph_vars = Vec::new();
|
||||
let mut redo_new = Vec::new();
|
||||
for i in f.flat_iter() {
|
||||
if let Err(id) = self.resolve_instr_types(&mut vars, &i.i) {
|
||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
||||
redo_iter.push(i);
|
||||
ph_vars.push(id);
|
||||
}
|
||||
}
|
||||
while !redo_iter.is_empty() {
|
||||
let mut new_ph = Vec::new();
|
||||
for id in &ph_vars {
|
||||
let i = id.0;
|
||||
let Some(var) = &vars[i] else {
|
||||
continue;
|
||||
};
|
||||
if var.ty == Type::Placeholder
|
||||
&& let Some(parent) = var.parent.as_ref()
|
||||
{
|
||||
let pty = &vars[parent.var.0].as_ref().unwrap().ty;
|
||||
if let Some(ft) = self.field_type(pty, &parent.field) {
|
||||
vars[i].as_mut().unwrap().ty = ft.clone();
|
||||
} else {
|
||||
new_ph.push(parent.var);
|
||||
}
|
||||
}
|
||||
}
|
||||
ph_vars = new_ph;
|
||||
for &i in &redo_iter {
|
||||
if let Err(id) = self.resolve_instr_types(&mut vars, &i.i) {
|
||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
||||
redo_new.push(i);
|
||||
ph_vars.push(id);
|
||||
}
|
||||
}
|
||||
std::mem::swap(&mut redo_iter, &mut redo_new);
|
||||
@@ -83,11 +76,7 @@ impl UProgram {
|
||||
self.vars = vars;
|
||||
}
|
||||
|
||||
pub fn resolve_instr_types(
|
||||
&self,
|
||||
vars: &mut [Option<UVar>],
|
||||
i: &UInstruction,
|
||||
) -> Result<(), VarID> {
|
||||
pub fn resolve_instr_types(&self, vars: &mut [Option<UVar>], i: &UInstruction) -> Option<()> {
|
||||
'outer: {
|
||||
match &i {
|
||||
UInstruction::Call { dest, f, args } => {
|
||||
@@ -96,7 +85,7 @@ impl UProgram {
|
||||
for (src, &dest) in args.iter().zip(&fun.args) {
|
||||
let dest_ty = get(vars, dest)?;
|
||||
let src_ty = get(vars, src.id)?;
|
||||
if let Some(ty) = match_types(dest_ty, src_ty) {
|
||||
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
||||
set(vars, dest, ty.clone());
|
||||
set(vars, src.id, ty);
|
||||
}
|
||||
@@ -105,7 +94,7 @@ impl UProgram {
|
||||
UInstruction::Mv { dest, src } => {
|
||||
let dest_ty = get(vars, dest.id)?;
|
||||
let src_ty = get(vars, src.id)?;
|
||||
if let Some(ty) = match_types(dest_ty, src_ty) {
|
||||
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
||||
set(vars, dest.id, ty.clone());
|
||||
set(vars, src.id, ty);
|
||||
}
|
||||
@@ -116,7 +105,7 @@ impl UProgram {
|
||||
let Type::Ref(dest_ty) = dest_ty else {
|
||||
break 'outer;
|
||||
};
|
||||
if let Some(ty) = match_types(dest_ty, src_ty) {
|
||||
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
||||
set(vars, dest.id, ty.clone().rf());
|
||||
set(vars, src.id, ty);
|
||||
}
|
||||
@@ -136,10 +125,10 @@ impl UProgram {
|
||||
UInstruction::Ret { .. } => {}
|
||||
UInstruction::Construct { dest, fields } => {
|
||||
let dest_ty = get(vars, dest.id)?;
|
||||
let Type::Struct { id, args } = dest_ty else {
|
||||
let Type::Struct(sty) = dest_ty else {
|
||||
break 'outer;
|
||||
};
|
||||
let id = *id;
|
||||
let id = sty.id;
|
||||
let Some(struc) = self.get(id) else {
|
||||
break 'outer;
|
||||
};
|
||||
@@ -149,7 +138,7 @@ impl UProgram {
|
||||
continue;
|
||||
};
|
||||
let src_ty = get(vars, src.id)?;
|
||||
if let Some(ty) = match_types(&field.ty, src_ty) {
|
||||
if let Some(ty) = self.match_types(&field.ty, src_ty) {
|
||||
if let Type::Generic { id } = field.ty {
|
||||
new.insert(id, ty.clone());
|
||||
}
|
||||
@@ -166,7 +155,7 @@ impl UProgram {
|
||||
args[i] = ty;
|
||||
}
|
||||
}
|
||||
set(vars, dest.id, Type::Struct { id, args });
|
||||
set(vars, dest.id, Type::Struct(StructTy { id, args }));
|
||||
}
|
||||
UInstruction::If { cond, body: _ } => {}
|
||||
UInstruction::Loop { body: _ } => {}
|
||||
@@ -174,18 +163,88 @@ impl UProgram {
|
||||
UInstruction::Continue => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn match_types(&self, dest: &Type, src: &Type) -> Option<Type> {
|
||||
if dest == src {
|
||||
return None;
|
||||
}
|
||||
match (dest, src) {
|
||||
(Type::Error, _) | (_, Type::Error) => None,
|
||||
(Type::Placeholder, _) | (_, Type::Placeholder) => None,
|
||||
(Type::Infer, x) | (x, Type::Infer) => Some(x.clone()),
|
||||
// TODO: handle constraints?
|
||||
(Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()),
|
||||
(Type::Struct(dest), Type::Struct(src)) => {
|
||||
if dest.id != src.id {
|
||||
return None;
|
||||
}
|
||||
let mut args = Vec::new();
|
||||
let mut changed = false;
|
||||
for (darg, sarg) in dest.args.iter().zip(&src.args) {
|
||||
if let Some(ty) = self.match_types(darg, sarg) {
|
||||
args.push(ty);
|
||||
changed = true;
|
||||
} else if darg != sarg {
|
||||
return None;
|
||||
} else {
|
||||
args.push(darg.clone());
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
Some(Type::Struct(StructTy { id: dest.id, args }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(
|
||||
Type::Fn {
|
||||
args: dest_args,
|
||||
ret: dest_ret,
|
||||
},
|
||||
Type::Fn {
|
||||
args: src_args,
|
||||
ret: src_ret,
|
||||
},
|
||||
) => {
|
||||
// TODO
|
||||
None
|
||||
}
|
||||
(Type::Ref(dest), Type::Ref(src)) => Some(self.match_types(dest, src)?.rf()),
|
||||
(Type::Slice(dest), Type::Slice(src)) => Some(self.match_types(dest, src)?.slice()),
|
||||
(Type::Array(dest, dlen), Type::Array(src, slen)) => {
|
||||
if dlen != slen {
|
||||
return None;
|
||||
}
|
||||
Some(self.match_types(dest, src)?.arr(*dlen))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(vars: &[Option<UVar>], id: VarID) -> Result<&Type, VarID> {
|
||||
let var = vars[id.0]
|
||||
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 Err(id);
|
||||
return None;
|
||||
}
|
||||
Ok(&var.ty)
|
||||
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) {
|
||||
@@ -194,69 +253,3 @@ pub fn set(vars: &mut [Option<UVar>], id: VarID, ty: Type) {
|
||||
.expect("PARTIAL BORROWING WOULD BE REALLY COOL")
|
||||
.ty = ty;
|
||||
}
|
||||
|
||||
pub fn match_types(dest: &Type, src: &Type) -> Option<Type> {
|
||||
if dest == src {
|
||||
return None;
|
||||
}
|
||||
match (dest, src) {
|
||||
(Type::Error, _) | (_, Type::Error) => None,
|
||||
(Type::Placeholder, _) | (_, Type::Placeholder) => None,
|
||||
(Type::Infer, x) | (x, Type::Infer) => Some(x.clone()),
|
||||
// TODO: handle constraints?
|
||||
(Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()),
|
||||
(
|
||||
Type::Struct {
|
||||
id: dest_id,
|
||||
args: dest_args,
|
||||
},
|
||||
Type::Struct {
|
||||
id: src_id,
|
||||
args: src_args,
|
||||
},
|
||||
) => {
|
||||
if dest_id != src_id {
|
||||
return None;
|
||||
}
|
||||
let mut args = Vec::new();
|
||||
let mut changed = false;
|
||||
for (darg, sarg) in dest_args.iter().zip(src_args) {
|
||||
if let Some(ty) = match_types(darg, sarg) {
|
||||
args.push(ty);
|
||||
changed = true;
|
||||
} else if darg != sarg {
|
||||
return None;
|
||||
} else {
|
||||
args.push(darg.clone());
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
Some(Type::Struct { id: *dest_id, args })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(
|
||||
Type::Fn {
|
||||
args: dest_args,
|
||||
ret: dest_ret,
|
||||
},
|
||||
Type::Fn {
|
||||
args: src_args,
|
||||
ret: src_ret,
|
||||
},
|
||||
) => {
|
||||
// TODO
|
||||
None
|
||||
}
|
||||
(Type::Ref(dest), Type::Ref(src)) => Some(match_types(dest, src)?.rf()),
|
||||
(Type::Slice(dest), Type::Slice(src)) => Some(match_types(dest, src)?.slice()),
|
||||
(Type::Array(dest, dlen), Type::Array(src, slen)) => {
|
||||
if dlen != slen {
|
||||
return None;
|
||||
}
|
||||
Some(match_types(dest, src)?.arr(*dlen))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user