Skip to content

Commit 8ebf3c5

Browse files
committed
fix: resolve Type::Unresolved and Type::Any in struct initialization
- Add Type::Unresolved handler to ssa.rs convert_type() to look up types by name in TypeRegistry instead of defaulting to I64 - Add Type::Unresolved handler to lowering.rs convert_type() with proper Named type construction - Add Type::Any handler in ssa.rs for future type inference support - Fix TypedStatement::Let to use Type::Any when no type annotation is provided, allowing inference from initializer - Register struct/class types in type registry before lowering in zyn_grammar.rs lower_to_hir() function - Use program's type registry instead of creating empty one This enables struct initialization with type inference: const p = Point{ .x = 10, .y = 20 }; The variable 'p' now correctly gets the Point struct type instead of defaulting to I32.
1 parent 66de301 commit 8ebf3c5

4 files changed

Lines changed: 118 additions & 3 deletions

File tree

crates/compiler/src/lowering.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,12 +1264,23 @@ impl LoweringContext {
12641264
}
12651265

12661266
Type::Unresolved(name) => {
1267-
// Look up the type in TypeRegistry aliases
1267+
// Look up the type in TypeRegistry - first try aliases, then try named types
12681268
eprintln!("[DEBUG convert_type] Resolving unresolved type '{}'", name.resolve_global().unwrap_or_default());
12691269
if let Some(resolved_type) = self.type_registry.resolve_alias(*name) {
12701270
eprintln!("[DEBUG convert_type] Found alias for '{}': {:?}", name.resolve_global().unwrap_or_default(), resolved_type);
12711271
// Recursively convert the resolved type
12721272
self.convert_type(resolved_type)
1273+
} else if let Some(type_def) = self.type_registry.get_type_by_name(*name) {
1274+
// Found a named type (struct, enum, etc.) - convert it as Named type
1275+
eprintln!("[DEBUG convert_type] Found named type for '{}': {:?}", name.resolve_global().unwrap_or_default(), type_def.kind);
1276+
let named_type = Type::Named {
1277+
id: type_def.id,
1278+
type_args: vec![],
1279+
const_args: vec![],
1280+
variance: vec![],
1281+
nullability: zyntax_typed_ast::type_registry::NullabilityKind::NonNull,
1282+
};
1283+
self.convert_type(&named_type)
12731284
} else {
12741285
eprintln!("[WARN] Could not resolve type '{}', defaulting to I64", name.resolve_global().unwrap_or_default());
12751286
HirType::I64 // Fallback

crates/compiler/src/ssa.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,6 +3286,51 @@ impl SsaBuilder {
32863286
HirType::I64
32873287
}
32883288
},
3289+
Type::Unresolved(name) => {
3290+
// Look up the type in TypeRegistry by name and convert as Named type
3291+
if let Some(type_def) = self.type_registry.get_type_by_name(*name) {
3292+
use crate::hir::HirStructType;
3293+
use zyntax_typed_ast::type_registry::TypeKind;
3294+
3295+
eprintln!("[CONVERT TYPE SSA] Unresolved type '{}' → resolved to {:?}",
3296+
name.resolve_global().unwrap_or_default(),
3297+
type_def.kind);
3298+
3299+
// Abstract types are zero-cost wrappers with struct layout
3300+
if let TypeKind::Abstract { .. } = &type_def.kind {
3301+
let hir_fields: Vec<HirType> = type_def.fields.iter()
3302+
.map(|field| self.convert_type(&field.ty))
3303+
.collect();
3304+
3305+
return HirType::Struct(HirStructType {
3306+
name: Some(type_def.name),
3307+
fields: hir_fields,
3308+
packed: false,
3309+
});
3310+
}
3311+
3312+
// Regular types (structs, classes, enums) convert to struct types
3313+
let hir_fields: Vec<HirType> = type_def.fields.iter()
3314+
.map(|field| self.convert_type(&field.ty))
3315+
.collect();
3316+
3317+
HirType::Struct(HirStructType {
3318+
name: Some(type_def.name),
3319+
fields: hir_fields,
3320+
packed: false,
3321+
})
3322+
} else {
3323+
eprintln!("[WARN] Unresolved type '{}' not found in registry, defaulting to I64",
3324+
name.resolve_global().unwrap_or_default());
3325+
HirType::I64
3326+
}
3327+
},
3328+
Type::Any => {
3329+
// Type::Any means "infer from context" - we need to check the initializer's type
3330+
// For now, default to I64 but this should be improved
3331+
eprintln!("[WARN] Type::Any encountered in convert_type, defaulting to I64");
3332+
HirType::I64
3333+
},
32893334
_ => HirType::I64, // Default for complex types
32903335
}
32913336
}

crates/zyn_peg/src/runtime2/interpreter.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@ impl<'g> GrammarInterpreter<'g> {
294294
let initializer = self.get_field_optional_expr("initializer", fields, state)?;
295295
let is_mutable = self.get_field_as_bool("is_mutable", fields, state).unwrap_or(false);
296296

297-
let ty = type_annotation.unwrap_or(Type::Primitive(PrimitiveType::I32));
297+
// Use Type::Any when no type annotation is provided - let the compiler infer from initializer
298+
let ty = type_annotation.unwrap_or(Type::Any);
298299
let mutability = if is_mutable { Mutability::Mutable } else { Mutability::Immutable };
299300

300301
TypedStatement::Let(TypedLet {
@@ -537,6 +538,8 @@ impl<'g> GrammarInterpreter<'g> {
537538
// Use Type::Any to signal that lowering should infer the type
538539
TypedExpression::Call(_) => Type::Any,
539540
TypedExpression::Variable(_) => Type::Any,
541+
// Struct literal gets its type from the struct name - use Unresolved for compiler to resolve
542+
TypedExpression::Struct(lit) => Type::Unresolved(lit.name),
540543
_ => Type::Primitive(PrimitiveType::Unit),
541544
};
542545

crates/zyntax_cli/src/formats/zyn_grammar.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,65 @@ fn lower_to_hir(
396396
mut program: TypedProgram,
397397
verbose: bool,
398398
) -> Result<HirModule, Box<dyn std::error::Error>> {
399+
use zyntax_typed_ast::{TypedDeclaration, type_registry::*};
400+
401+
// Register struct/class types in the type registry before lowering
402+
// This is needed because the Grammar2 parser creates TypedDeclaration::Class
403+
// but doesn't register them in the type registry
404+
for decl_node in &program.declarations {
405+
if let TypedDeclaration::Class(class) = &decl_node.node {
406+
// Check if type is already registered
407+
if program.type_registry.get_type_by_name(class.name).is_some() {
408+
if verbose {
409+
eprintln!("[DEBUG] Type '{}' already registered, skipping",
410+
class.name.resolve_global().unwrap_or_default());
411+
}
412+
continue;
413+
}
414+
415+
// Register the struct type
416+
let type_id = TypeId::next();
417+
let fields: Vec<FieldDef> = class.fields.iter().map(|f| {
418+
FieldDef {
419+
name: f.name,
420+
ty: f.ty.clone(),
421+
visibility: f.visibility,
422+
mutability: f.mutability,
423+
is_static: f.is_static,
424+
is_synthetic: false,
425+
span: f.span,
426+
getter: None,
427+
setter: None,
428+
}
429+
}).collect();
430+
431+
let type_def = TypeDefinition {
432+
id: type_id,
433+
name: class.name,
434+
kind: TypeKind::Struct {
435+
fields: fields.clone(),
436+
is_tuple: false,
437+
},
438+
type_params: vec![],
439+
constraints: vec![],
440+
fields,
441+
methods: vec![],
442+
constructors: vec![],
443+
metadata: Default::default(),
444+
span: class.span,
445+
};
446+
program.type_registry.register_type(type_def);
447+
if verbose {
448+
eprintln!("[DEBUG] Registered struct type '{}' with TypeId {:?}",
449+
class.name.resolve_global().unwrap_or_default(), type_id);
450+
}
451+
}
452+
}
453+
399454
let arena = AstArena::new();
400455
let module_name = InternedString::new_global("main");
401-
let type_registry = Arc::new(TypeRegistry::new());
456+
// Use the program's type registry which now has registered types
457+
let type_registry = Arc::new(program.type_registry.clone());
402458

403459
let mut lowering_ctx = LoweringContext::new(
404460
module_name,

0 commit comments

Comments
 (0)