diff --git a/engine/baml-lib/baml-core/src/ir/repr.rs b/engine/baml-lib/baml-core/src/ir/repr.rs index d5f3795b6..d73670382 100644 --- a/engine/baml-lib/baml-core/src/ir/repr.rs +++ b/engine/baml-lib/baml-core/src/ir/repr.rs @@ -284,10 +284,13 @@ fn type_with_arity(t: FieldType, arity: &FieldArity) -> FieldType { impl WithRepr for ast::FieldType { fn repr(&self, db: &ParserDatabase) -> Result { Ok(match self { - ast::FieldType::Primitive(_, typeval, ..) => { + ast::FieldType::Primitive(arity, typeval, ..) => { let repr = FieldType::Primitive(typeval.clone()); - - repr + if arity.is_optional() { + FieldType::Optional(Box::new(repr)) + } else { + repr + } } ast::FieldType::Symbol(arity, idn, ..) => type_with_arity( match db.find_type(idn) { diff --git a/engine/baml-lib/baml-types/src/field_type/mod.rs b/engine/baml-lib/baml-types/src/field_type/mod.rs index a4dabd61b..124fb5a49 100644 --- a/engine/baml-lib/baml-types/src/field_type/mod.rs +++ b/engine/baml-lib/baml-types/src/field_type/mod.rs @@ -102,9 +102,19 @@ impl FieldType { pub fn is_optional(&self) -> bool { match self { FieldType::Optional(_) => true, - FieldType::Primitive(TypeValue::Null) => true, - FieldType::Union(types) => types.iter().any(FieldType::is_optional), - _ => false, + FieldType::Primitive(TypeValue::Null) => { + println!("found a null in is_optional"); + true + } + + FieldType::Union(types) => { + println!("found a union in is_optional"); + types.iter().any(FieldType::is_optional) + } + _ => { + // println!("non-optional in is_optional: {:#?}", self); + false + } } } } diff --git a/engine/baml-lib/jsonish/src/deserializer/coercer/ir_ref/coerce_class.rs b/engine/baml-lib/jsonish/src/deserializer/coercer/ir_ref/coerce_class.rs index 5364375f5..054b30aa9 100644 --- a/engine/baml-lib/jsonish/src/deserializer/coercer/ir_ref/coerce_class.rs +++ b/engine/baml-lib/jsonish/src/deserializer/coercer/ir_ref/coerce_class.rs @@ -29,6 +29,7 @@ impl TypeCoercer for Class { ); let (optional, required): (Vec<_>, Vec<_>) = self.fields.iter().partition(|f| f.1.is_optional()); + let mut optional_values = optional .iter() .map(|(f, ..)| (f.real_name().to_string(), None)) diff --git a/engine/baml-lib/parser-database/src/walkers/field.rs b/engine/baml-lib/parser-database/src/walkers/field.rs index 086004f7b..d4bb41c50 100644 --- a/engine/baml-lib/parser-database/src/walkers/field.rs +++ b/engine/baml-lib/parser-database/src/walkers/field.rs @@ -70,15 +70,13 @@ impl<'db> FieldWalker<'db> { /// The field's default attributes. pub fn get_default_attributes(&self) -> Option<&'db ToStringAttributes> { - println!("Field is triggered"); - let result = self .db .types .class_attributes .get(&self.id.0) .and_then(|f| f.field_serilizers.get(&self.id.1)); - println!("Result: {:?}", result); + result } } @@ -119,6 +117,7 @@ impl<'db> WithSerializeableContent for (&ParserDatabase, &FieldType) { "int" => "int", "float" => "float", "bool" => "bool", + // "null" => "null", _ => "unknown", }, "optional": arity.is_optional(), diff --git a/engine/baml-lib/parser-database/src/walkers/mod.rs b/engine/baml-lib/parser-database/src/walkers/mod.rs index bf707af7b..cf662117e 100644 --- a/engine/baml-lib/parser-database/src/walkers/mod.rs +++ b/engine/baml-lib/parser-database/src/walkers/mod.rs @@ -14,6 +14,7 @@ mod field; mod function; mod template_string; +use baml_types::TypeValue; pub use client::*; pub use configuration::*; use either::Either; @@ -245,12 +246,19 @@ impl<'db> crate::ParserDatabase { /// Convert a field type to a `Type`. pub fn to_jinja_type(&self, ft: &FieldType) -> internal_baml_jinja::Type { use internal_baml_jinja::Type; - match ft { - FieldType::Symbol(arity, idn, ..) => match self.find_type(idn) { - None => Type::Undefined, - Some(Either::Left(_)) => Type::ClassRef(idn.to_string()), - Some(Either::Right(_)) => Type::String, - }, + + let r = match ft { + FieldType::Symbol(arity, idn, ..) => { + let mut t = match self.find_type(idn) { + None => Type::Undefined, + Some(Either::Left(_)) => Type::ClassRef(idn.to_string()), + Some(Either::Right(_)) => Type::String, + }; + if arity.is_optional() { + t = Type::None | t; + } + t + } FieldType::List(inner, dims, ..) => { let mut t = self.to_jinja_type(inner); for _ in 0..*dims { @@ -277,18 +285,22 @@ impl<'db> crate::ParserDatabase { Box::new(self.to_jinja_type(&kv.1)), ), FieldType::Primitive(arity, t, ..) => { - let mut t = match t.to_string().as_str() { - "string" => Type::String, - "int" => Type::Int, - "float" => Type::Float, - "bool" => Type::Bool, - _ => Type::Unknown, + let mut t = match &t { + TypeValue::String => Type::String, + TypeValue::Int => Type::Int, + TypeValue::Float => Type::Float, + TypeValue::Bool => Type::Bool, + TypeValue::Null => Type::None, + TypeValue::Image => Type::Unknown, + TypeValue::Audio => Type::Unknown, }; - if arity.is_optional() { + if arity.is_optional() || matches!(t, Type::None) { t = Type::None | t; } t } - } + }; + + r } } diff --git a/engine/baml-lib/schema-ast/src/ast/field.rs b/engine/baml-lib/schema-ast/src/ast/field.rs index 489d71e1f..09a050be8 100644 --- a/engine/baml-lib/schema-ast/src/ast/field.rs +++ b/engine/baml-lib/schema-ast/src/ast/field.rs @@ -121,13 +121,6 @@ pub enum FieldType { Map(Box<(FieldType, FieldType)>, Span, Option>), } -fn arity_suffix(arity: &FieldArity) -> &'static str { - match arity { - FieldArity::Required => "", - FieldArity::Optional => "?", - } -} - impl FieldType { pub fn name(&self) -> String { match self { diff --git a/engine/baml-lib/schema-ast/src/parser/parse_field.rs b/engine/baml-lib/schema-ast/src/parser/parse_field.rs index 7c670f8ad..651b16151 100644 --- a/engine/baml-lib/schema-ast/src/parser/parse_field.rs +++ b/engine/baml-lib/schema-ast/src/parser/parse_field.rs @@ -165,10 +165,7 @@ fn parse_field_type_with_attr(pair: Pair<'_>, diagnostics: &mut Diagnostics) -> Some(ft) // Return the field type with attributes } - None => { - log::info!("field_type is None"); - None - } + None => None, } } fn combine_field_types(types: Vec) -> Option { diff --git a/engine/baml-lib/schema-ast/src/parser/parse_types.rs b/engine/baml-lib/schema-ast/src/parser/parse_types.rs index c02e7782f..9648ae91f 100644 --- a/engine/baml-lib/schema-ast/src/parser/parse_types.rs +++ b/engine/baml-lib/schema-ast/src/parser/parse_types.rs @@ -33,14 +33,12 @@ pub fn parse_field_type(pair: Pair<'_>, diagnostics: &mut Diagnostics) -> Option Some(ftype) => { if arity.is_optional() { match ftype.to_nullable() { - Ok(ftype) => return Some(ftype), - Err(e) => { - diagnostics.push_error(e); - return None; - } + Ok(ftype) => Some(ftype), + Err(_) => None, } + } else { + Some(ftype) } - Some(ftype) } None => { unreachable!("Ftype should always be defined") @@ -153,6 +151,12 @@ fn parse_base_type(pair: Pair<'_>, diagnostics: &mut Diagnostics) -> Option FieldType::Primitive( + FieldArity::Optional, + TypeValue::Null, + diagnostics.span(current.as_span()), + None, + ), _ => FieldType::Symbol( FieldArity::Required, Identifier::Local( diff --git a/integ-tests/baml_src/test-files/functions/input/named-args/single/named-audio.baml b/integ-tests/baml_src/test-files/functions/input/named-args/single/named-audio.baml index fe66094de..83f9d24aa 100644 --- a/integ-tests/baml_src/test-files/functions/input/named-args/single/named-audio.baml +++ b/integ-tests/baml_src/test-files/functions/input/named-args/single/named-audio.baml @@ -1,23 +1,54 @@ -function AudioInput(aud: audio) -> string{ - client Gemini - prompt #" - {{ _.role("user") }} +// function AudioInput(aud: audio) -> string{ +// client Gemini +// prompt #" +// {{ _.role("user") }} - Does this sound like a roar? Yes or no? One word no other characters. +// Does this sound like a roar? Yes or no? One word no other characters. - {{ aud }} - "# +// {{ aud }} +// "# +// } + + + +// test TestURLAudioInput{ +// functions [AudioInput] +// args { +// aud{ +// url https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg +// } +// } +// } + + +enum CatA { + A } +enum CatB { + C + D +} +class CatAPicker { + cat CatA +} -test TestURLAudioInput{ - functions [AudioInput] - args { - aud{ - url https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg - } - } +class CatBPicker { + cat CatB + item int } +enum CatC { + E + F + G + H + I +} +class CatCPicker { + cat CatC + item int | string | null + data int? +} \ No newline at end of file