monomorphization
This commit is contained in:
parent
32b53ea975
commit
22e2a45401
5 changed files with 1376 additions and 4 deletions
|
|
@ -4,3 +4,4 @@ pub mod ast;
|
|||
pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod typechecker;
|
||||
pub mod monomorphize;
|
||||
|
|
|
|||
103
src/main.rs
103
src/main.rs
|
|
@ -1,6 +1,9 @@
|
|||
use logos::Logos;
|
||||
use std::fs;
|
||||
use suicmez::{lexer::Token, parser::Parser, typechecker::TypeChecker};
|
||||
use suicmez::{
|
||||
lexer::Token, parser::Parser, typechecker::TypeChecker,
|
||||
monomorphize::{Monomorphizer, check_no_typevars},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
// Check if a file was provided as argument
|
||||
|
|
@ -84,5 +87,103 @@ fn run_file(filename: &str) -> Result<(), String> {
|
|||
typed_nodes.len()
|
||||
);
|
||||
|
||||
// Debug: show typed nodes
|
||||
println!("\nTyped AST nodes before monomorphization:");
|
||||
for (i, node) in typed_nodes.iter().enumerate() {
|
||||
let node_type = match &node.kind {
|
||||
suicmez::ast::TypedASTNodeKind::Function(f) => {
|
||||
format!("Function({})", f.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Struct(s) => {
|
||||
format!("Struct({}) with {} params", s.name, s.parameters.len())
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Enum(e) => {
|
||||
format!("Enum({}) with {} params", e.name, e.parameters.len())
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Impl(imp) => {
|
||||
format!("Impl({})", imp.target)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Trait(t) => {
|
||||
format!("Trait({})", t.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Extern(e) => {
|
||||
format!("Extern({})", e.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Load(l) => {
|
||||
format!("Load({})", l.alias)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Use(u) => {
|
||||
format!("Use({})", u)
|
||||
}
|
||||
};
|
||||
println!(" [{}] {}", i, node_type);
|
||||
}
|
||||
|
||||
// Monomorphize the AST
|
||||
let monomorphizer = Monomorphizer::new();
|
||||
let mono_nodes = monomorphizer.monomorphize_program(&typed_nodes).map_err(|e| {
|
||||
format!(
|
||||
"Monomorphization error: {}{}",
|
||||
e.message,
|
||||
if let Some(span) = &e.span {
|
||||
format!(" at {}:{}", span.file, span.start)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
)
|
||||
})?;
|
||||
|
||||
println!(
|
||||
"Monomorphization passed! {} nodes after specialization.",
|
||||
mono_nodes.len()
|
||||
);
|
||||
|
||||
// Print detailed info about each node
|
||||
println!("\nMonomorphized AST nodes:");
|
||||
for (i, node) in mono_nodes.iter().enumerate() {
|
||||
let node_type = match &node.kind {
|
||||
suicmez::ast::TypedASTNodeKind::Function(f) => {
|
||||
format!("Function({})", f.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Struct(s) => {
|
||||
format!("Struct({}) with {} params", s.name, s.parameters.len())
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Enum(e) => {
|
||||
format!("Enum({}) with {} params", e.name, e.parameters.len())
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Impl(imp) => {
|
||||
format!("Impl({})", imp.target)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Trait(t) => {
|
||||
format!("Trait({})", t.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Extern(e) => {
|
||||
format!("Extern({})", e.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Load(l) => {
|
||||
format!("Load({})", l.alias)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Use(u) => {
|
||||
format!("Use({})", u)
|
||||
}
|
||||
};
|
||||
println!(" [{}] {}", i, node_type);
|
||||
}
|
||||
|
||||
// Check that no type variables remain
|
||||
check_no_typevars(&mono_nodes).map_err(|e| {
|
||||
format!(
|
||||
"Type variable check failed: {}{}",
|
||||
e.message,
|
||||
if let Some(span) = &e.span {
|
||||
format!(" at {}:{}", span.file, span.start)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
)
|
||||
})?;
|
||||
|
||||
println!("Type variable check passed! No type variables remain in AST.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
1197
src/monomorphize.rs
Normal file
1197
src/monomorphize.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -319,9 +319,54 @@ impl TypeChecker {
|
|||
ty,
|
||||
});
|
||||
}
|
||||
ASTNodeKind::Struct(_) => Type::Unit,
|
||||
ASTNodeKind::Enum(_) => Type::Unit,
|
||||
ASTNodeKind::Trait(_) => Type::Unit,
|
||||
ASTNodeKind::Struct(s) => {
|
||||
// Return the typed struct
|
||||
return Ok(TypedASTNode {
|
||||
kind: TypedASTNodeKind::Struct(TypedStruct {
|
||||
name: s.name.clone(),
|
||||
parameters: s.parameters.clone(),
|
||||
fields: s.fields.iter().map(|f| TypedField {
|
||||
name: f.name.clone(),
|
||||
field_type: f.field_type.clone(),
|
||||
span: f.span.clone(),
|
||||
}).collect(),
|
||||
}),
|
||||
span: node.span.clone(),
|
||||
attributes: node.attributes.clone(),
|
||||
ty: Type::Unit,
|
||||
});
|
||||
}
|
||||
ASTNodeKind::Enum(e) => {
|
||||
// Return the typed enum
|
||||
return Ok(TypedASTNode {
|
||||
kind: TypedASTNodeKind::Enum(TypedEnum {
|
||||
name: e.name.clone(),
|
||||
parameters: e.parameters.clone(),
|
||||
variants: e.variants.iter().map(|v| TypedVariant {
|
||||
name: v.name.clone(),
|
||||
fields: v.fields.clone(),
|
||||
span: v.span.clone(),
|
||||
}).collect(),
|
||||
}),
|
||||
span: node.span.clone(),
|
||||
attributes: node.attributes.clone(),
|
||||
ty: Type::Unit,
|
||||
});
|
||||
}
|
||||
ASTNodeKind::Trait(t) => {
|
||||
// Return the typed trait
|
||||
return Ok(TypedASTNode {
|
||||
kind: TypedASTNodeKind::Trait(TypedTrait {
|
||||
name: t.name.clone(),
|
||||
methods: t.methods.clone(),
|
||||
parameters: t.parameters.clone(),
|
||||
associated_types: t.associated_types.clone(),
|
||||
}),
|
||||
span: node.span.clone(),
|
||||
attributes: node.attributes.clone(),
|
||||
ty: Type::Unit,
|
||||
});
|
||||
}
|
||||
ASTNodeKind::Impl(impl_def) => {
|
||||
let mut typed_methods = Vec::new();
|
||||
for method in &impl_def.methods {
|
||||
|
|
|
|||
28
tests/generics_comprehensive.sui
Normal file
28
tests/generics_comprehensive.sui
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Generic struct specialization test
|
||||
struct Box<T>
|
||||
value: T
|
||||
end
|
||||
|
||||
# Generic enum specialization test
|
||||
enum Option<T>
|
||||
Some(T),
|
||||
None,
|
||||
end
|
||||
|
||||
# Generic function specialization test
|
||||
fn unwrap<T>(opt: Option<T>) -> T
|
||||
match opt
|
||||
Option::None() => -1,
|
||||
Option::Some(v) => v,
|
||||
end
|
||||
|
||||
# Generic struct with generic enum test
|
||||
fn test_containers() -> int do
|
||||
let box_int = Box { value: 42 };
|
||||
let box_string = Box { value: "Fermented" };
|
||||
let some_int = Option::Some(10);
|
||||
let some_bool = Option::Some(true);
|
||||
let unwrapped = unwrap(some_int);
|
||||
let unwraped_bool = unwrap(some_bool);
|
||||
box_int.value + unwrapped
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue