Skip to content

Commit 259cedb

Browse files
committed
move code
1 parent 13e9058 commit 259cedb

File tree

3 files changed

+273
-265
lines changed

3 files changed

+273
-265
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub use decl_table::*;
3333
mod jit;
3434
pub use jit::*;
3535

36+
pub mod mangle;
37+
3638
mod monomorph;
3739
pub use monomorph::*;
3840

src/mangle.rs

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
use crate::*;
2+
3+
/// Generates a unique mangled name for a generic function or struct
4+
/// instantiated with concrete type arguments.
5+
///
6+
/// The mangling scheme uses a readable format that includes type information,
7+
/// making debugging easier while ensuring uniqueness.
8+
///
9+
/// # Examples
10+
/// - `id<i32>` becomes `id$i32`
11+
/// - `map<i32, bool>` becomes `map$i32$bool`
12+
/// - `GenericStruct<f32>` becomes `GenericStruct$f32`
13+
pub fn mangle_name(base: Name, type_args: &[TypeID]) -> Name {
14+
if type_args.is_empty() {
15+
return base;
16+
}
17+
18+
let mut mangled = String::from(&*base);
19+
20+
for ty in type_args {
21+
mangled.push('$');
22+
mangled.push_str(&type_to_string(*ty));
23+
}
24+
25+
Name::new(mangled)
26+
}
27+
28+
/// Converts a TypeID to a string representation for name mangling.
29+
/// Uses a compact, unambiguous format.
30+
fn type_to_string(ty: TypeID) -> String {
31+
match &*ty {
32+
Type::Void => "void".to_string(),
33+
Type::Bool => "bool".to_string(),
34+
Type::Int8 => "i8".to_string(),
35+
Type::UInt8 => "u8".to_string(),
36+
Type::Int32 => "i32".to_string(),
37+
Type::UInt32 => "u32".to_string(),
38+
Type::Float32 => "f32".to_string(),
39+
Type::Float64 => "f64".to_string(),
40+
41+
Type::Tuple(types) => {
42+
let type_strs: Vec<_> = types.iter()
43+
.map(|t| type_to_string(*t))
44+
.collect();
45+
format!("({})", type_strs.join(","))
46+
}
47+
48+
Type::Array(elem_ty, size) => {
49+
format!("[{};{}]", type_to_string(*elem_ty), size)
50+
}
51+
52+
Type::Func(from, to) => {
53+
format!("fn({})_{}", type_to_string(*from), type_to_string(*to))
54+
}
55+
56+
Type::Name(name, params) => {
57+
if params.is_empty() {
58+
format!("{}", name)
59+
} else {
60+
let param_strs: Vec<_> = params.iter()
61+
.map(|p| type_to_string(*p))
62+
.collect();
63+
format!("{}<{}>", name, param_strs.join(","))
64+
}
65+
}
66+
67+
Type::Var(name) => {
68+
format!("T{}", name)
69+
}
70+
71+
Type::Anon(idx) => {
72+
format!("#{}", idx)
73+
}
74+
}
75+
}
76+
77+
#[cfg(test)]
78+
mod tests {
79+
use super::*;
80+
81+
#[test]
82+
fn test_mangle_no_type_args() {
83+
let name = Name::new("foo".into());
84+
let mangled = mangle_name(name, &[]);
85+
assert_eq!(mangled, Name::new("foo".into()));
86+
}
87+
88+
#[test]
89+
fn test_mangle_single_primitive() {
90+
let name = Name::new("id".into());
91+
let type_args = vec![mk_type(Type::Int32)];
92+
let mangled = mangle_name(name, &type_args);
93+
assert_eq!(mangled, Name::new("id$i32".into()));
94+
}
95+
96+
#[test]
97+
fn test_mangle_multiple_primitives() {
98+
let name = Name::new("map".into());
99+
let type_args = vec![
100+
mk_type(Type::Int32),
101+
mk_type(Type::Bool),
102+
];
103+
let mangled = mangle_name(name, &type_args);
104+
assert_eq!(mangled, Name::new("map$i32$bool".into()));
105+
}
106+
107+
#[test]
108+
fn test_mangle_all_primitive_types() {
109+
let name = Name::new("fn".into());
110+
let types = vec![
111+
(Type::Void, "void"),
112+
(Type::Bool, "bool"),
113+
(Type::Int8, "i8"),
114+
(Type::UInt8, "u8"),
115+
(Type::Int32, "i32"),
116+
(Type::UInt32, "u32"),
117+
(Type::Float32, "f32"),
118+
(Type::Float64, "f64"),
119+
];
120+
121+
for (ty, expected_suffix) in types {
122+
let type_args = vec![mk_type(ty)];
123+
let mangled = mangle_name(name, &type_args);
124+
let expected = Name::new(format!("fn${}", expected_suffix));
125+
assert_eq!(mangled, expected);
126+
}
127+
}
128+
129+
#[test]
130+
fn test_mangle_array_type() {
131+
let name = Name::new("process".into());
132+
let type_args = vec![mk_type(Type::Array(mk_type(Type::Float32), 10))];
133+
let mangled = mangle_name(name, &type_args);
134+
assert_eq!(mangled, Name::new("process$[f32;10]".into()));
135+
}
136+
137+
#[test]
138+
fn test_mangle_tuple_type() {
139+
let name = Name::new("swap".into());
140+
let tuple_ty = mk_type(Type::Tuple(vec![
141+
mk_type(Type::Int32),
142+
mk_type(Type::Bool),
143+
]));
144+
let type_args = vec![tuple_ty];
145+
let mangled = mangle_name(name, &type_args);
146+
assert_eq!(mangled, Name::new("swap$(i32,bool)".into()));
147+
}
148+
149+
#[test]
150+
fn test_mangle_function_type() {
151+
let name = Name::new("apply".into());
152+
let func_ty = mk_type(Type::Func(
153+
mk_type(Type::Int32),
154+
mk_type(Type::Bool),
155+
));
156+
let type_args = vec![func_ty];
157+
let mangled = mangle_name(name, &type_args);
158+
assert_eq!(mangled, Name::new("apply$fn(i32)_bool".into()));
159+
}
160+
161+
#[test]
162+
fn test_mangle_named_type_no_params() {
163+
let name = Name::new("convert".into());
164+
let named_ty = mk_type(Type::Name(Name::new("MyStruct".into()), vec![]));
165+
let type_args = vec![named_ty];
166+
let mangled = mangle_name(name, &type_args);
167+
assert_eq!(mangled, Name::new("convert$MyStruct".into()));
168+
}
169+
170+
#[test]
171+
fn test_mangle_named_type_with_params() {
172+
let name = Name::new("process".into());
173+
let generic_struct = mk_type(Type::Name(
174+
Name::new("GenericStruct".into()),
175+
vec![mk_type(Type::Int32)],
176+
));
177+
let type_args = vec![generic_struct];
178+
let mangled = mangle_name(name, &type_args);
179+
assert_eq!(mangled, Name::new("process$GenericStruct<i32>".into()));
180+
}
181+
182+
#[test]
183+
fn test_mangle_nested_generic() {
184+
let name = Name::new("fn".into());
185+
// GenericStruct<GenericStruct<i32>>
186+
let inner = mk_type(Type::Name(
187+
Name::new("GenericStruct".into()),
188+
vec![mk_type(Type::Int32)],
189+
));
190+
let outer = mk_type(Type::Name(
191+
Name::new("GenericStruct".into()),
192+
vec![inner],
193+
));
194+
let type_args = vec![outer];
195+
let mangled = mangle_name(name, &type_args);
196+
assert_eq!(
197+
mangled,
198+
Name::new("fn$GenericStruct<GenericStruct<i32>>".into())
199+
);
200+
}
201+
202+
#[test]
203+
fn test_mangle_complex_combination() {
204+
let name = Name::new("complex".into());
205+
// Array of tuples containing a function
206+
let func_ty = mk_type(Type::Func(
207+
mk_type(Type::Int32),
208+
mk_type(Type::Bool),
209+
));
210+
let tuple_ty = mk_type(Type::Tuple(vec![
211+
func_ty,
212+
mk_type(Type::Float32),
213+
]));
214+
let array_ty = mk_type(Type::Array(tuple_ty, 5));
215+
let type_args = vec![array_ty];
216+
let mangled = mangle_name(name, &type_args);
217+
assert_eq!(
218+
mangled,
219+
Name::new("complex$[(fn(i32)_bool,f32);5]".into())
220+
);
221+
}
222+
223+
#[test]
224+
fn test_mangle_type_variable() {
225+
let name = Name::new("fn".into());
226+
let type_args = vec![typevar("T")];
227+
let mangled = mangle_name(name, &type_args);
228+
assert_eq!(mangled, Name::new("fn$TT".into()));
229+
}
230+
231+
#[test]
232+
fn test_mangle_anonymous_type_var() {
233+
let name = Name::new("fn".into());
234+
let type_args = vec![anon(42)];
235+
let mangled = mangle_name(name, &type_args);
236+
assert_eq!(mangled, Name::new("fn$#42".into()));
237+
}
238+
239+
#[test]
240+
fn test_mangle_uniqueness() {
241+
let name = Name::new("id".into());
242+
243+
// id<i32> and id<u32> should produce different mangled names
244+
let mangled1 = mangle_name(name, &[mk_type(Type::Int32)]);
245+
let mangled2 = mangle_name(name, &[mk_type(Type::UInt32)]);
246+
assert_ne!(mangled1, mangled2);
247+
248+
// id<i32, bool> and id<bool, i32> should be different
249+
let mangled3 = mangle_name(
250+
name,
251+
&[mk_type(Type::Int32), mk_type(Type::Bool)],
252+
);
253+
let mangled4 = mangle_name(
254+
name,
255+
&[mk_type(Type::Bool), mk_type(Type::Int32)],
256+
);
257+
assert_ne!(mangled3, mangled4);
258+
}
259+
260+
#[test]
261+
fn test_mangle_deterministic() {
262+
let name = Name::new("map".into());
263+
let type_args = vec![mk_type(Type::Int32), mk_type(Type::Float32)];
264+
265+
// Multiple calls with same inputs should produce same output
266+
let mangled1 = mangle_name(name, &type_args);
267+
let mangled2 = mangle_name(name, &type_args);
268+
assert_eq!(mangled1, mangled2);
269+
}
270+
}

0 commit comments

Comments
 (0)