Skip to content

Commit 160bf8f

Browse files
committed
baml-language: implement new PPIR
baml-language: ppir fixes
1 parent 0d2d607 commit 160bf8f

63 files changed

Lines changed: 8258 additions & 271 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

baml_language/crates/baml_compiler2_ppir/src/expand.rs

Lines changed: 483 additions & 0 deletions
Large diffs are not rendered by default.

baml_language/crates/baml_compiler2_ppir/src/lib.rs

Lines changed: 389 additions & 24 deletions
Large diffs are not rendered by default.

baml_language/crates/baml_compiler2_ppir/src/ty.rs

Lines changed: 200 additions & 181 deletions
Large diffs are not rendered by default.

baml_language/crates/baml_compiler2_tir/src/inference.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ pub fn infer_scope_types<'db>(
256256
&mut diags,
257257
)
258258
})
259-
.unwrap_or(Ty::Unknown { attr: TyAttr::default() });
259+
.unwrap_or(Ty::Unknown {
260+
attr: TyAttr::default(),
261+
});
260262

261263
// Report unresolved type diagnostics for return type
262264
if !diags.is_empty() {
@@ -300,12 +302,15 @@ pub fn infer_scope_types<'db>(
300302
let mut ns_path = pkg_info.namespace_path.clone();
301303
ns_path.push(cn.clone());
302304
pkg_items.lookup_type(&ns_path).map(|def| {
303-
Ty::Class(crate::lower_type_expr::qualify_def(
304-
db, def, cn,
305-
), TyAttr::default())
305+
Ty::Class(
306+
crate::lower_type_expr::qualify_def(db, def, cn),
307+
TyAttr::default(),
308+
)
306309
})
307310
})
308-
.unwrap_or(Ty::Unknown { attr: TyAttr::default() })
311+
.unwrap_or(Ty::Unknown {
312+
attr: TyAttr::default(),
313+
})
309314
} else {
310315
let mut param_diags = Vec::new();
311316
let ty = crate::lower_type_expr::lower_type_expr_in_ns(
@@ -461,7 +466,14 @@ fn collect_class_fields<'db>(
461466
let resolved = resolve_class_fields(db, *loc);
462467
let qualified =
463468
crate::lower_type_expr::qualify_def(db, Definition::Class(*loc), name);
464-
classes.insert(qualified, resolved.fields.clone());
469+
classes.insert(
470+
qualified,
471+
resolved
472+
.fields
473+
.iter()
474+
.map(|(n, t, _)| (n.clone(), t.clone()))
475+
.collect(),
476+
);
465477
}
466478
}
467479
}
@@ -473,7 +485,8 @@ fn collect_class_fields<'db>(
473485
/// Resolved class fields — `TypeExpr` resolved to `Ty` for each field.
474486
#[derive(Debug, Clone, PartialEq, Eq)]
475487
pub struct ResolvedClassFields {
476-
pub fields: Vec<(Name, Ty)>,
488+
/// (field name, resolved type, SAP attribute names)
489+
pub fields: Vec<(Name, Ty, Vec<Name>)>,
477490
/// Type lowering diagnostics: (error, span of the type annotation).
478491
pub diagnostics: Vec<(crate::infer_context::TirTypeError, text_size::TextRange)>,
479492
}
@@ -562,8 +575,15 @@ pub fn resolve_class_fields<'db>(
562575
}
563576
ty
564577
})
565-
.unwrap_or(Ty::Unknown { attr: TyAttr::default() });
566-
(f.name.clone(), ty)
578+
.unwrap_or(Ty::Unknown {
579+
attr: TyAttr::default(),
580+
});
581+
let sap_attrs: Vec<Name> = f
582+
.type_expr
583+
.as_ref()
584+
.map(|te| te.expr.attrs().iter().map(|a| a.name.clone()).collect())
585+
.unwrap_or_default();
586+
(f.name.clone(), ty, sap_attrs)
567587
})
568588
.collect();
569589

@@ -607,7 +627,9 @@ pub fn resolve_type_alias<'db>(
607627
}
608628
ty
609629
})
610-
.unwrap_or(Ty::Unknown { attr: TyAttr::default() });
630+
.unwrap_or(Ty::Unknown {
631+
attr: TyAttr::default(),
632+
});
611633

612634
Arc::new(ResolvedTypeAlias {
613635
ty,

baml_language/crates/baml_lsp2_actions/src/completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ fn completions_for_ty_members(db: &dyn Db, ty: &Ty) -> Vec<Completion> {
475475

476476
// Fields from resolved class fields.
477477
let resolved = baml_compiler2_tir::inference::resolve_class_fields(db, class_loc);
478-
for (field_name, field_ty) in &resolved.fields {
478+
for (field_name, field_ty, _sap_attrs) in &resolved.fields {
479479
items.push(
480480
Completion::new(field_name.as_str(), CompletionKind::Field)
481481
.with_detail(utils::display_ty(field_ty))

baml_language/crates/baml_lsp2_actions/src/type_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ fn type_info_for_definition(db: &dyn Db, def: Definition<'_>) -> TypeInfo {
221221
let fields = resolved
222222
.fields
223223
.iter()
224-
.map(|(field_name, ty)| (field_name.as_str().to_string(), utils::display_ty(ty)))
224+
.map(|(field_name, ty, _)| (field_name.as_str().to_string(), utils::display_ty(ty)))
225225
.collect();
226226

227227
TypeInfo::Class {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Config {
2+
id int @stream.must_exist
3+
name string @stream.done
4+
data AttrFoo @stream.must_exist @stream.done
5+
}
6+
7+
class AttrFoo {
8+
x int
9+
}
10+
11+
class WithBlockAttrs {
12+
a int
13+
b string
14+
@@stream.done
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Foo {
2+
a int
3+
b string
4+
c float
5+
d bool
6+
}
7+
8+
class Bar {
9+
ref Foo
10+
items int[]
11+
nested Foo[]
12+
mapping map<string, int>
13+
opt int?
14+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
enum Color {
2+
Red
3+
Green
4+
Blue
5+
}
6+
7+
class Inner {
8+
value int
9+
}
10+
11+
type StringAlias = string
12+
13+
class Complex {
14+
color Color
15+
literal 5
16+
str_literal "hello"
17+
union_field int | string[]
18+
alias_field StringAlias
19+
nested_list Inner[][]
20+
optional_class Inner?
21+
union_with_null int | null | string
22+
}
23+
24+
type AliasToClass = Inner
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class SelfRef {
2+
name string
3+
children SelfRef[]
4+
}
5+
6+
class AllMustExist {
7+
a int @stream.must_exist
8+
b string @stream.must_exist
9+
c float @stream.must_exist
10+
}
11+
12+
class AllDone {
13+
a int @stream.done
14+
b string @stream.done
15+
c EdgeFoo @stream.done
16+
}
17+
18+
class EdgeFoo {
19+
x int
20+
}
21+
22+
class NeverFields {
23+
lit_int 42
24+
lit_str "fixed"
25+
lit_bool true
26+
}
27+
28+
// GAP 5: @@stream.must_exist on a class makes pending_default return Never.
29+
// In a union where all variants are pending=Never, the union itself gets
30+
// @sap.pending_never instead of prepending null.
31+
//
32+
// Without the fix: pending_default(MustExistClass) = Null, so the union
33+
// gets PrependNull → `null | MustExistClass$stream | 5 @sap.parse_without_null`.
34+
// With the fix: pending_default(MustExistClass) = Never (due to @@stream.must_exist),
35+
// literal 5 is also Never, so union gets InherentlyNever → `@sap.pending_never`.
36+
class MustExistClass {
37+
v int
38+
@@stream.must_exist
39+
}
40+
41+
class UnionWithMustExist {
42+
// Both variants are pending=Never: MustExistClass via @@stream.must_exist,
43+
// literal 5 inherently. Union should get @sap.pending_never, not null prepended.
44+
mixed MustExistClass | 5
45+
}

0 commit comments

Comments
 (0)