Implement generic type swapping
This commit is contained in:
parent
1e4667449a
commit
ffb3515aaa
@ -16,7 +16,7 @@ BINARY="$(echo $1 | cut -d'.' -f1)"".out"
|
|||||||
|
|
||||||
echo $1
|
echo $1
|
||||||
|
|
||||||
cargo run -p reid -- $@ && \
|
cargo run -p reid -- run $@ && \
|
||||||
./$BINARY ; echo "Return value: ""$?"
|
./$BINARY ; echo "Return value: ""$?"
|
||||||
|
|
||||||
## Command from: clang -v hello.o -o test
|
## Command from: clang -v hello.o -o test
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, ReturnType},
|
ast::{self, ReturnType, TypeKind},
|
||||||
mir::{
|
mir::{
|
||||||
self, CustomTypeKey, FunctionParam, ModuleMap, NamedVariableRef, ReturnKind, SourceModuleId, StmtKind,
|
self, CustomTypeKey, FunctionParam, ModuleMap, NamedVariableRef, ReturnKind, SourceModuleId, StmtKind,
|
||||||
StructField, StructType, WhileStatement,
|
StructField, StructType, WhileStatement,
|
||||||
@ -44,7 +44,11 @@ impl ast::Module {
|
|||||||
let def = mir::FunctionDefinition {
|
let def = mir::FunctionDefinition {
|
||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
documentation: signature.documentation.clone(),
|
documentation: signature.documentation.clone(),
|
||||||
generics: signature.generics.clone(),
|
generics: signature
|
||||||
|
.generics
|
||||||
|
.iter()
|
||||||
|
.map(|g| (g.clone(), mir::TypeKind::Vague(mir::VagueType::Unknown)))
|
||||||
|
.collect(),
|
||||||
linkage_name: None,
|
linkage_name: None,
|
||||||
is_pub: false,
|
is_pub: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
@ -176,11 +180,15 @@ impl ast::FunctionDefinition {
|
|||||||
ty: p.1 .0.into_mir(module_id),
|
ty: p.1 .0.into_mir(module_id),
|
||||||
meta: p.2.as_meta(module_id),
|
meta: p.2.as_meta(module_id),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
mir::FunctionDefinition {
|
mir::FunctionDefinition {
|
||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
documentation: signature.documentation.clone(),
|
documentation: signature.documentation.clone(),
|
||||||
// TODO generics parsing
|
generics: signature
|
||||||
generics: Vec::new(),
|
.generics
|
||||||
|
.iter()
|
||||||
|
.map(|g| (g.clone(), mir::TypeKind::Vague(mir::VagueType::Unknown)))
|
||||||
|
.collect(),
|
||||||
linkage_name: None,
|
linkage_name: None,
|
||||||
is_pub: *is_pub,
|
is_pub: *is_pub,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
|
@ -158,9 +158,14 @@ impl Display for FunctionDefinition {
|
|||||||
}
|
}
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}fn {}({}) -> {:#} ",
|
"{}fn {}<{}>({}) -> {:#} ",
|
||||||
if self.is_pub { "pub " } else { "" },
|
if self.is_pub { "pub " } else { "" },
|
||||||
self.name,
|
self.name,
|
||||||
|
self.generics
|
||||||
|
.iter()
|
||||||
|
.map(|(n, t)| format!("{n} = {:?}", t))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", "),
|
||||||
self.parameters
|
self.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.map(|FunctionParam { name, ty, .. }| format!("{}: {:#}", name, ty))
|
.map(|FunctionParam { name, ty, .. }| format!("{}: {:#}", name, ty))
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::mir::{
|
use crate::mir::{
|
||||||
self, FunctionCall, GlobalKind, GlobalValue, IfExpression, Literal, Module, SourceModuleId, TypeKind,
|
self, generics, CustomTypeKey, FunctionCall, FunctionDefinition, FunctionParam, GlobalKind, GlobalValue,
|
||||||
WhileStatement,
|
IfExpression, Literal, Module, SourceModuleId, TypeKind, WhileStatement,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::pass::{Pass, PassResult, PassState};
|
use super::pass::{Pass, PassResult, PassState};
|
||||||
@ -43,18 +43,18 @@ impl Pass for GenericsPass {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for module in &context.modules {
|
for module in &mut context.modules {
|
||||||
let mut calls = HashMap::new();
|
let mut calls = HashMap::new();
|
||||||
let mut assoc_calls = HashMap::new();
|
let mut assoc_calls = HashMap::new();
|
||||||
for function in &module.1.associated_functions {
|
for function in &mut module.1.associated_functions {
|
||||||
match &function.1.kind {
|
match &mut function.1.kind {
|
||||||
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
|
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
|
||||||
mir::FunctionDefinitionKind::Extern(_) => {}
|
mir::FunctionDefinitionKind::Extern(_) => {}
|
||||||
mir::FunctionDefinitionKind::Intrinsic(_) => {}
|
mir::FunctionDefinitionKind::Intrinsic(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for function in &module.1.functions {
|
for function in &mut module.1.functions {
|
||||||
match &function.kind {
|
match &mut function.kind {
|
||||||
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
|
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
|
||||||
mir::FunctionDefinitionKind::Extern(_) => {}
|
mir::FunctionDefinitionKind::Extern(_) => {}
|
||||||
mir::FunctionDefinitionKind::Intrinsic(_) => {}
|
mir::FunctionDefinitionKind::Intrinsic(_) => {}
|
||||||
@ -80,7 +80,6 @@ impl Pass for GenericsPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg!(&function_map);
|
|
||||||
|
|
||||||
self.function_map = function_map;
|
self.function_map = function_map;
|
||||||
|
|
||||||
@ -88,24 +87,61 @@ impl Pass for GenericsPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn module(&mut self, module: &mut mir::Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
|
fn module(&mut self, module: &mut mir::Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
|
for function in module.functions.drain(..).collect::<Vec<_>>() {
|
||||||
|
if let Some(source) = function.source {
|
||||||
|
let functions = self.function_map.get(&source).unwrap();
|
||||||
|
let calls = functions.calls.get(&function.name).unwrap();
|
||||||
|
|
||||||
|
if function.generics.len() > 0 {
|
||||||
|
for call in calls {
|
||||||
|
if let Some(clone) = function.try_clone() {
|
||||||
|
let generics = function
|
||||||
|
.generics
|
||||||
|
.iter()
|
||||||
|
.zip(call)
|
||||||
|
.map(|((n, _), t)| (n.clone(), t.clone()))
|
||||||
|
.collect();
|
||||||
|
module.functions.push(FunctionDefinition {
|
||||||
|
name: name_fmt(function.name.clone(), call.clone()),
|
||||||
|
return_type: function.return_type.replace_generic(&generics),
|
||||||
|
parameters: function
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.map(|p| FunctionParam {
|
||||||
|
ty: p.ty.replace_generic(&generics),
|
||||||
|
..p.clone()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
generics,
|
||||||
|
..clone
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.functions.push(function);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.functions.push(function);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Block {
|
impl mir::Block {
|
||||||
fn find_calls(&self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
||||||
for statement in &self.statements {
|
for statement in &mut self.statements {
|
||||||
statement.find_calls(calls, assoc_calls);
|
statement.find_calls(calls, assoc_calls);
|
||||||
}
|
}
|
||||||
if let Some((_, Some(e))) = &self.return_expression {
|
if let Some((_, Some(e))) = &mut self.return_expression {
|
||||||
e.find_calls(calls, assoc_calls);
|
e.find_calls(calls, assoc_calls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Statement {
|
impl mir::Statement {
|
||||||
fn find_calls(&self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
||||||
match &self.0 {
|
match &mut self.0 {
|
||||||
mir::StmtKind::Let(_, _, expression) => expression.find_calls(calls, assoc_calls),
|
mir::StmtKind::Let(_, _, expression) => expression.find_calls(calls, assoc_calls),
|
||||||
mir::StmtKind::Set(expression, expression1) => {
|
mir::StmtKind::Set(expression, expression1) => {
|
||||||
expression.find_calls(calls, assoc_calls);
|
expression.find_calls(calls, assoc_calls);
|
||||||
@ -122,8 +158,8 @@ impl mir::Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Expression {
|
impl mir::Expression {
|
||||||
fn find_calls(&self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
|
||||||
match &self.0 {
|
match &mut self.0 {
|
||||||
mir::ExprKind::Variable(_) => {}
|
mir::ExprKind::Variable(_) => {}
|
||||||
mir::ExprKind::Indexed(expression, _, expression1) => {
|
mir::ExprKind::Indexed(expression, _, expression1) => {
|
||||||
expression.find_calls(calls, assoc_calls);
|
expression.find_calls(calls, assoc_calls);
|
||||||
@ -142,7 +178,7 @@ impl mir::Expression {
|
|||||||
item.1.find_calls(calls, assoc_calls);
|
item.1.find_calls(calls, assoc_calls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Literal(_) => todo!(),
|
mir::ExprKind::Literal(_) => {}
|
||||||
mir::ExprKind::BinOp(_, lhs, rhs, _) => {
|
mir::ExprKind::BinOp(_, lhs, rhs, _) => {
|
||||||
lhs.find_calls(calls, assoc_calls);
|
lhs.find_calls(calls, assoc_calls);
|
||||||
rhs.find_calls(calls, assoc_calls);
|
rhs.find_calls(calls, assoc_calls);
|
||||||
@ -153,6 +189,7 @@ impl mir::Expression {
|
|||||||
} else {
|
} else {
|
||||||
calls.insert(function_call.name.clone(), vec![function_call.generics.clone()]);
|
calls.insert(function_call.name.clone(), vec![function_call.generics.clone()]);
|
||||||
}
|
}
|
||||||
|
function_call.name = name_fmt(function_call.name.clone(), function_call.generics.clone())
|
||||||
}
|
}
|
||||||
mir::ExprKind::AssociatedFunctionCall(ty, function_call) => {
|
mir::ExprKind::AssociatedFunctionCall(ty, function_call) => {
|
||||||
if let Some(calls) = assoc_calls.get_mut(&(ty.clone(), function_call.name.clone())) {
|
if let Some(calls) = assoc_calls.get_mut(&(ty.clone(), function_call.name.clone())) {
|
||||||
@ -163,11 +200,12 @@ impl mir::Expression {
|
|||||||
vec![function_call.generics.clone()],
|
vec![function_call.generics.clone()],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function_call.name = name_fmt(function_call.name.clone(), function_call.generics.clone())
|
||||||
}
|
}
|
||||||
mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => {
|
mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => {
|
||||||
cond.find_calls(calls, assoc_calls);
|
cond.find_calls(calls, assoc_calls);
|
||||||
then_e.find_calls(calls, assoc_calls);
|
then_e.find_calls(calls, assoc_calls);
|
||||||
if let Some(else_e) = else_e.as_ref() {
|
if let Some(else_e) = else_e.as_mut() {
|
||||||
else_e.find_calls(calls, assoc_calls);
|
else_e.find_calls(calls, assoc_calls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,3 +217,26 @@ impl mir::Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name_fmt(name: String, generics: Vec<TypeKind>) -> String {
|
||||||
|
format!(
|
||||||
|
"{}.{}",
|
||||||
|
name,
|
||||||
|
generics.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(".")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeKind {
|
||||||
|
fn replace_generic(&self, generics: &Vec<(String, TypeKind)>) -> TypeKind {
|
||||||
|
match self {
|
||||||
|
TypeKind::CustomType(CustomTypeKey(name, _)) => {
|
||||||
|
if let Some((_, inner)) = generics.iter().find(|(n, _)| n == name) {
|
||||||
|
inner.clone()
|
||||||
|
} else {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -324,7 +324,7 @@ pub struct FunctionDefinition {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub documentation: Option<String>,
|
pub documentation: Option<String>,
|
||||||
pub linkage_name: Option<String>,
|
pub linkage_name: Option<String>,
|
||||||
pub generics: Vec<String>,
|
pub generics: Vec<(String, TypeKind)>,
|
||||||
/// Whether this function is visible to outside modules
|
/// Whether this function is visible to outside modules
|
||||||
pub is_pub: bool,
|
pub is_pub: bool,
|
||||||
/// Whether this module is from an external module, and has been imported
|
/// Whether this module is from an external module, and has been imported
|
||||||
@ -336,6 +336,40 @@ pub struct FunctionDefinition {
|
|||||||
pub signature_meta: Metadata,
|
pub signature_meta: Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FunctionDefinition {
|
||||||
|
pub fn try_clone(&self) -> Option<FunctionDefinition> {
|
||||||
|
match &self.kind {
|
||||||
|
FunctionDefinitionKind::Local(block, metadata) => Some(FunctionDefinition {
|
||||||
|
name: self.name.clone(),
|
||||||
|
documentation: self.documentation.clone(),
|
||||||
|
linkage_name: self.linkage_name.clone(),
|
||||||
|
generics: self.generics.clone(),
|
||||||
|
is_pub: self.is_pub.clone(),
|
||||||
|
is_imported: self.is_imported.clone(),
|
||||||
|
return_type: self.return_type.clone(),
|
||||||
|
parameters: self.parameters.clone(),
|
||||||
|
kind: FunctionDefinitionKind::Local(block.clone(), metadata.clone()),
|
||||||
|
source: self.source.clone(),
|
||||||
|
signature_meta: self.signature_meta.clone(),
|
||||||
|
}),
|
||||||
|
FunctionDefinitionKind::Extern(e) => Some(FunctionDefinition {
|
||||||
|
name: self.name.clone(),
|
||||||
|
documentation: self.documentation.clone(),
|
||||||
|
linkage_name: self.linkage_name.clone(),
|
||||||
|
generics: self.generics.clone(),
|
||||||
|
is_pub: self.is_pub.clone(),
|
||||||
|
is_imported: self.is_imported.clone(),
|
||||||
|
return_type: self.return_type.clone(),
|
||||||
|
parameters: self.parameters.clone(),
|
||||||
|
kind: FunctionDefinitionKind::Extern(*e),
|
||||||
|
source: self.source.clone(),
|
||||||
|
signature_meta: self.signature_meta.clone(),
|
||||||
|
}),
|
||||||
|
FunctionDefinitionKind::Intrinsic(intrinsic_function) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct FunctionParam {
|
pub struct FunctionParam {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user