1use crate::adapter::cst::MaterialiseError;
47use crate::adapter::java::{declared_path, java_member_type, type_tag, unsigned_holder};
48use crate::default_common::{discriminator_default_value, resolve_alias, selected_case};
49use crate::encode::EncodeError;
50use crate::fixed_literal::{fixed_text, zero_decimal};
51use zerodds_ast::{
52 Ast, ConstExpr, Literal as AstLiteral, MemberNode, PrimitiveKind, TypeKind, TypeNode,
53};
54use zerodds_ast_core::Id;
55use zerodds_lang_cst::common::{Doc, Ident, Literal, Path};
56use zerodds_lang_cst::java;
57
58#[must_use]
65pub fn defaulter_name(ast: &Ast, id: Id<TypeNode>) -> String {
66 match ast.type_(id).map(|node| node.kind.clone()) {
67 Ok(TypeKind::Primitive(kind)) => {
68 format!("zd_def_p_{}", kind.as_str().replace(' ', "_"))
69 }
70 _ => format!(
71 "zd_def_{}",
72 type_tag(ast, id, 0).unwrap_or_else(|_| format!("unresolved_type_{}", id.slot()))
73 ),
74 }
75}
76
77#[must_use]
85pub fn defaulter_from_decoder(decoder: &str) -> String {
86 match decoder.strip_prefix("zd_dec_") {
87 Some(rest) => format!("zd_def_{rest}"),
88 None => format!("zd_def_{decoder}"),
89 }
90}
91
92pub fn default_into(ast: &Ast, id: Id<TypeNode>, place: java::Expr) -> java::Statement {
97 assign(place, call(&defaulter_name(ast, id), Vec::new()))
98}
99
100pub fn member_default(
113 ast: &Ast,
114 node: &MemberNode,
115 type_: Id<TypeNode>,
116 place: java::Expr,
117) -> Result<Vec<java::Statement>, EncodeError> {
118 let Some(expr) = node.facets.xtypes.as_ref().and_then(|x| x.default_value) else {
119 return Ok(vec![default_into(ast, type_, place)]);
120 };
121 let value = explicit(ast, expr, type_, &node.name)?;
122 Ok(vec![assign(place, value)])
123}
124
125pub fn java_defaulters_called_by(
139 ast: &Ast,
140 members: &[java::Member],
141) -> Result<Vec<java::Member>, EncodeError> {
142 let index: Vec<(String, Id<TypeNode>)> = ast
143 .types()
144 .map(|(id, _)| (defaulter_name(ast, id), id))
145 .collect();
146 let mut called: Vec<String> = Vec::new();
147 for member in members {
148 calls_in_member(member, &mut called);
149 }
150 let mut wanted: Vec<Id<TypeNode>> = Vec::new();
151 let mut have: Vec<String> = Vec::new();
152 for _ in 0..=index.len() {
156 let mut grew = false;
157 for name in &called {
158 if have.contains(name) {
159 continue;
160 }
161 have.push(name.clone());
162 if let Some(id) = index.iter().find(|(n, _)| n == name).map(|(_, id)| *id) {
168 wanted.push(id);
169 grew = true;
170 }
171 }
172 let produced = java_defaulters_over(ast, &wanted)?;
173 if !grew {
174 return Ok(produced);
175 }
176 for member in &produced {
177 calls_in_member(member, &mut called);
178 }
179 }
180 java_defaulters_over(ast, &wanted)
181}
182
183pub fn java_defaulters_over(
188 ast: &Ast,
189 types: &[Id<TypeNode>],
190) -> Result<Vec<java::Member>, EncodeError> {
191 let mut out = Vec::new();
192 let mut emitted: Vec<String> = Vec::new();
193 for id in types.iter().copied() {
194 let name = defaulter_name(ast, id);
195 if emitted.contains(&name) {
196 continue;
197 }
198 let Some(body) = body_of(ast, id, &name)? else {
199 continue;
200 };
201 emitted.push(name.clone());
202 out.push(java::Member::Method(java::Method {
203 doc: Doc::line(
204 "Table 9 of DDS-XTypes 1.3: what this type is where the stream did not \
205 carry it.",
206 ),
207 annotations: Vec::new(),
208 modifiers: vec![java::Modifier::Static],
212 generics: Vec::new(),
213 returns: value_type(ast, id),
214 name: Ident::new(&name),
215 params: Vec::new(),
216 throws: Vec::new(),
217 body: Some(java::Block { statements: body }),
218 }));
219 }
220 Ok(out)
221}
222
223fn value_type(ast: &Ast, id: Id<TypeNode>) -> java::Type {
225 java_member_type(ast, id, "default").unwrap_or_else(|_| {
226 java::Type::named(Path::new(
227 &[format!("UnresolvedType{}", id.slot()).as_str()],
228 ))
229 })
230}
231
232#[allow(clippy::too_many_lines)]
235fn body_of(
236 ast: &Ast,
237 id: Id<TypeNode>,
238 own_name: &str,
239) -> Result<Option<Vec<java::Statement>>, EncodeError> {
240 let refuse = |kind: &'static str| EncodeError::NoWriter {
241 member: own_name.to_string(),
242 kind,
243 };
244 let Ok(node) = ast.type_(id) else {
252 return Err(refuse("a type the model does not hold"));
253 };
254 let statements = match &node.kind {
255 TypeKind::Primitive(kind) => vec![give_back(primitive_default(*kind))],
256
257 TypeKind::String { .. } => vec![give_back(text(""))],
260
261 TypeKind::Fixed { scale, .. } => {
265 vec![give_back(big_decimal(&zero_decimal(*scale)))]
266 }
267
268 TypeKind::Alias { aliased } => {
269 let Some(target) = aliased.resolved() else {
270 return Err(refuse("typedef with an unresolved target"));
271 };
272 vec![give_back(call(&defaulter_name(ast, target), Vec::new()))]
273 }
274
275 TypeKind::Enumeration { .. } => {
278 let Some(enumerator) = crate::emit::default_enumerator_name(ast, id) else {
279 return Err(refuse(
280 "enumeration with no enumerator to take as its default",
281 ));
282 };
283 vec![give_back(enumerator_constant(ast, id, &enumerator))]
284 }
285
286 TypeKind::Bitmask { .. } => {
290 let holder = unsigned_holder(ast.effective_bit_bound(id));
291 vec![give_back(zero_of(&holder))]
292 }
293
294 TypeKind::Bitset { .. } => {
295 let mut statements = vec![new_local(value_type(ast, id))];
296 for field in &ast.all_bitfields_of(id) {
297 let Ok(field_node) = ast.bitfield(*field) else {
298 continue;
299 };
300 if let Some(field_name) = field_node.name.as_ref() {
302 statements.push(assign(
303 member("v", &java::escape_keyword(field_name)),
304 zero_of(&unsigned_holder(field_node.bits)),
305 ));
306 }
307 }
308 statements.push(give_back(name("v")));
309 statements
310 }
311
312 TypeKind::Sequence { .. } | TypeKind::Map { .. } => match value_type(ast, id) {
317 java::Type::Named { path, args }
320 if args.is_empty()
321 && path.segments().last().is_some_and(|last| {
322 last.as_str().starts_with(crate::adapter::java::MAP_PREFIX)
323 }) =>
324 {
325 vec![give_back(java::Expr::New {
326 type_: Box::new(java::Type::named(path)),
327 args: Vec::new(),
328 })]
329 }
330 java::Type::Array(element) => vec![give_back(new_array(
331 element,
332 vec![java::Expr::Literal(Literal::int(0))],
333 ))],
334 java::Type::Named { args, .. }
337 if crate::adapter::java::mapping() == crate::adapter::java::JavaMapping::Psm
338 && !args.is_empty() =>
339 {
340 vec![give_back(java::Expr::New {
341 type_: Box::new(java::Type::generic(
342 Path::new(crate::adapter::java::ARRAY_LIST),
343 args,
344 )),
345 args: Vec::new(),
346 })]
347 }
348 _ => {
349 return Err(refuse(
350 "collection whose Java form is neither an array nor a Collection",
351 ));
352 }
353 },
354
355 TypeKind::Array { element, dims } => {
360 let Some(element) = element.resolved() else {
361 return Err(refuse("array with an unresolved element"));
362 };
363 let mut lengths = Vec::new();
364 for dim in dims {
365 lengths.push(
366 ast.eval_integral(*dim)
367 .map_err(|_| refuse("array whose length does not evaluate"))?,
368 );
369 }
370 let mut statements = vec![java::Statement::Declare {
371 final_: false,
372 type_: value_type(ast, id),
373 name: Ident::new("v"),
374 value: Some(new_array(
375 Box::new(value_type(ast, element)),
376 lengths
377 .iter()
378 .map(|length| java::Expr::Literal(Literal::int(*length)))
379 .collect(),
380 )),
381 }];
382 let mut access = name("v");
383 for level in 0..lengths.len() {
384 access = java::Expr::Index {
385 value: Box::new(access),
386 index: Box::new(name(&format!("zd_i{level}"))),
387 };
388 }
389 let mut inner = java::Block {
390 statements: vec![default_into(ast, element, access)],
391 };
392 for (level, length) in lengths.iter().enumerate().rev() {
393 inner = java::Block {
394 statements: vec![counted_loop(
395 &format!("zd_i{level}"),
396 java::Expr::Literal(Literal::int(*length)),
397 inner,
398 )],
399 };
400 }
401 statements.extend(inner.statements);
402 statements.push(give_back(name("v")));
403 statements
404 }
405
406 TypeKind::Structure { .. } | TypeKind::Valuetype { .. } => {
409 let mut statements = vec![new_local(value_type(ast, id))];
410 for member_id in &ast.all_members_of(id) {
411 let Ok(member_node) = ast.member(*member_id) else {
412 continue;
413 };
414 let field = java::escape_keyword(&member_node.name);
415 if member_node.facets.is_optional() {
416 statements.push(assign(
422 member("v", &field),
423 java::Expr::Literal(Literal::Null),
424 ));
425 continue;
426 }
427 let Some(member_type) = member_node.type_.resolved() else {
428 return Err(EncodeError::NoWriter {
429 member: member_node.name.clone(),
430 kind: "member with an unresolved type",
431 });
432 };
433 statements.extend(member_default(
434 ast,
435 member_node,
436 member_type,
437 member("v", &field),
438 )?);
439 }
440 statements.push(give_back(name("v")));
441 statements
442 }
443
444 TypeKind::Union { discriminator, .. } => {
449 let Some(discriminator) = discriminator.resolved() else {
450 return Err(refuse("union with an unresolved discriminator"));
451 };
452 let mut statements = vec![
453 new_local(value_type(ast, id)),
454 default_into(ast, discriminator, member("v", "_d")),
455 ];
456 if let Some((member_type, field)) = selected_by_default(ast, id, discriminator)? {
457 statements.push(default_into(ast, member_type, member("v", &field)));
458 }
459 statements.push(give_back(name("v")));
460 statements
461 }
462
463 TypeKind::Native | TypeKind::ObjectRef { .. } | TypeKind::AnnotationType { .. } => {
464 return Ok(None);
465 }
466 TypeKind::ValueBox { .. } => {
467 return Err(refuse(
468 "boxed value, whose presence flag has no settled wire form",
469 ));
470 }
471 TypeKind::Any => {
477 return Err(refuse(
478 "`any`, which DDS-XTypes has no encoding for; only CORBA CDR writes one, \
479 as a TypeCode ahead of the value",
480 ));
481 }
482 TypeKind::ValueBase => {
483 return Err(refuse(
484 "`ValueBase`, which DDS-XTypes has no encoding for; only CORBA CDR writes \
485 one, as a chunked value with its repository id",
486 ));
487 }
488 };
489 Ok(Some(statements))
490}
491
492fn primitive_default(kind: PrimitiveKind) -> java::Expr {
498 match kind {
499 PrimitiveKind::Boolean => java::Expr::Literal(Literal::Bool(false)),
500 PrimitiveKind::Char | PrimitiveKind::WChar => {
503 java::Expr::Literal(Literal::Int("'\\0'".to_string()))
504 }
505 PrimitiveKind::Float32 => java::Expr::Literal(Literal::Float("0.0f".to_string())),
506 PrimitiveKind::Float64 => java::Expr::Literal(Literal::Float("0.0".to_string())),
507 PrimitiveKind::Float128 => java::Expr::Path(Path::new(&["Float128", "ZERO"])),
510 PrimitiveKind::Int8 | PrimitiveKind::Octet => java::Expr::Cast {
511 type_: Box::new(java::Type::Primitive(java::Primitive::Byte)),
512 value: Box::new(java::Expr::Literal(Literal::int(0))),
513 },
514 PrimitiveKind::Int16 => java::Expr::Cast {
515 type_: Box::new(java::Type::Primitive(java::Primitive::Short)),
516 value: Box::new(java::Expr::Literal(Literal::int(0))),
517 },
518 PrimitiveKind::Int64 | PrimitiveKind::UInt32 | PrimitiveKind::UInt64 => {
519 java::Expr::Literal(Literal::Int("0L".to_string()))
520 }
521 PrimitiveKind::UInt8 | PrimitiveKind::UInt16 | PrimitiveKind::Int32 => {
522 java::Expr::Literal(Literal::int(0))
523 }
524 }
525}
526
527fn zero_of(holder: &java::Type) -> java::Expr {
529 if *holder == java::Type::Primitive(java::Primitive::Long) {
530 return java::Expr::Literal(Literal::Int("0L".to_string()));
531 }
532 java::Expr::Literal(Literal::int(0))
533}
534
535pub(crate) fn enumerator_constant(ast: &Ast, id: Id<TypeNode>, enumerator: &str) -> java::Expr {
539 let owner = declared_path(ast, id).unwrap_or_else(|_| {
540 format!("UnresolvedEnum{}", id.slot())
544 });
545 java::Expr::Path(Path::new(
546 &format!("{owner}.{}", java::escape_keyword(enumerator))
547 .split('.')
548 .collect::<Vec<_>>(),
549 ))
550}
551
552fn selected_by_default(
554 ast: &Ast,
555 id: Id<TypeNode>,
556 discriminator: Id<TypeNode>,
557) -> Result<Option<(Id<TypeNode>, String)>, EncodeError> {
558 let Some(selector) = discriminator_default_value(ast, discriminator) else {
559 return Ok(None);
560 };
561 Ok(selected_case(ast, id, selector)?
562 .map(|(member, member_type)| (member_type, java::escape_keyword(&member.name))))
563}
564
565#[allow(clippy::too_many_lines)]
567fn explicit(
568 ast: &Ast,
569 expr: Id<zerodds_ast::ConstExprNode>,
570 type_: Id<TypeNode>,
571 member_name: &str,
572) -> Result<java::Expr, EncodeError> {
573 let refuse = |kind: &'static str| EncodeError::NoWriter {
574 member: member_name.to_string(),
575 kind,
576 };
577 let node = ast
578 .expr(expr)
579 .map_err(|_| refuse("a `@default` this frontend cannot follow"))?;
580 let resolved = resolve_alias(ast, type_);
581 let kind = ast.type_(resolved).map(|node| node.kind.clone());
582 match &node.expr {
583 ConstExpr::Literal(AstLiteral::Boolean(flag)) => {
584 Ok(java::Expr::Literal(Literal::Bool(*flag)))
585 }
586 ConstExpr::Literal(AstLiteral::Char(ch)) => Ok(char_literal(u32::from(*ch))),
590 ConstExpr::Literal(AstLiteral::WChar(code)) => Ok(char_literal(*code)),
591 ConstExpr::Literal(AstLiteral::String(value)) => Ok(text(value)),
592 ConstExpr::Literal(AstLiteral::WString(codes)) => {
593 let mut out = String::new();
594 for code in codes {
595 let Some(ch) = char::from_u32(*code) else {
596 return Err(refuse("a `@default` wide string that is not code points"));
597 };
598 out.push(ch);
599 }
600 Ok(text(&out))
601 }
602 ConstExpr::Literal(AstLiteral::Float { mantissa, exponent }) => {
603 let suffix = match kind {
604 Ok(TypeKind::Primitive(PrimitiveKind::Float32)) => "f",
605 _ => "",
606 };
607 let exponent = exponent
608 .as_ref()
609 .map_or(String::new(), |text| format!("e{text}"));
610 Ok(java::Expr::Literal(Literal::Float(format!(
611 "{mantissa}{exponent}{suffix}"
612 ))))
613 }
614 ConstExpr::Literal(AstLiteral::Fixed { digits, scale }) => {
617 Ok(big_decimal(&fixed_text(digits, *scale)))
618 }
619 ConstExpr::Literal(AstLiteral::Enumerator(reference)) => {
620 let target = reference
621 .resolved()
622 .ok_or_else(|| refuse("a `@default` enumerator that is unresolved"))?;
623 let enumerator = ast
624 .enumerator(target)
625 .map_err(|_| refuse("a `@default` enumerator this frontend cannot follow"))?;
626 Ok(enumerator_constant(ast, resolved, &enumerator.name))
627 }
628 _ => {
629 let value = ast
632 .eval_integral(expr)
633 .map_err(|_| refuse("a `@default` this frontend cannot evaluate"))?;
634 Ok(match kind {
635 Ok(TypeKind::Primitive(PrimitiveKind::Char | PrimitiveKind::WChar)) => {
636 char_literal(u32::try_from(value).unwrap_or(0))
637 }
638 Ok(TypeKind::Primitive(PrimitiveKind::Int8)) => java::Expr::Cast {
639 type_: Box::new(java::Type::Primitive(java::Primitive::Byte)),
640 value: Box::new(java::Expr::Literal(Literal::int(value))),
641 },
642 Ok(TypeKind::Primitive(PrimitiveKind::Int16)) => java::Expr::Cast {
643 type_: Box::new(java::Type::Primitive(java::Primitive::Short)),
644 value: Box::new(java::Expr::Literal(Literal::int(value))),
645 },
646 Ok(TypeKind::Primitive(
647 PrimitiveKind::Int64 | PrimitiveKind::UInt32 | PrimitiveKind::UInt64,
648 )) => wide(value),
649 _ => java::Expr::Literal(Literal::int(value)),
650 })
651 }
652 }
653}
654
655fn wide(value: i128) -> java::Expr {
657 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
658 let pattern = if value > i128::from(i64::MAX) {
659 value as u64 as i64
660 } else {
661 value as i64
662 };
663 java::Expr::Literal(Literal::Int(format!("{pattern}L")))
664}
665
666fn char_literal(code: u32) -> java::Expr {
668 java::Expr::Cast {
669 type_: Box::new(java::Type::Primitive(java::Primitive::Char)),
670 value: Box::new(java::Expr::Literal(Literal::int(i128::from(code)))),
671 }
672}
673
674fn big_decimal(decimal: &str) -> java::Expr {
677 java::Expr::New {
678 type_: Box::new(java::Type::named(Path::new(&[
679 "java",
680 "math",
681 "BigDecimal",
682 ]))),
683 args: vec![text(decimal)],
684 }
685}
686
687fn calls_in_member(member: &java::Member, out: &mut Vec<String>) {
690 match member {
691 java::Member::Method(method) => {
692 if let Some(body) = &method.body {
693 calls_in_block(body, out);
694 }
695 }
696 java::Member::Field(field) => {
697 if let Some(value) = &field.value {
698 calls_in_expr(value, out);
699 }
700 }
701 java::Member::Constructor(constructor) => calls_in_block(&constructor.body, out),
702 java::Member::Initialiser { body, .. } => calls_in_block(body, out),
703 java::Member::Nested(_) | java::Member::Comment(_) | java::Member::Verbatim(_) => {}
704 }
705}
706
707fn calls_in_block(block: &java::Block, out: &mut Vec<String>) {
712 for statement in &block.statements {
713 calls_in_statement(statement, out);
714 }
715}
716
717#[allow(clippy::too_many_lines)]
722fn calls_in_statement(statement: &java::Statement, out: &mut Vec<String>) {
723 match statement {
724 java::Statement::Declare { value, .. } => {
725 if let Some(value) = value {
726 calls_in_expr(value, out);
727 }
728 }
729 java::Statement::Expr(expr) | java::Statement::Throw(expr) => calls_in_expr(expr, out),
730 java::Statement::Return(value) => {
731 if let Some(value) = value {
732 calls_in_expr(value, out);
733 }
734 }
735 java::Statement::If {
736 condition,
737 then,
738 otherwise,
739 } => {
740 calls_in_expr(condition, out);
741 calls_in_block(then, out);
742 if let Some(otherwise) = otherwise {
743 calls_in_block(otherwise, out);
744 }
745 }
746 java::Statement::ForEach { range, body, .. } => {
747 calls_in_expr(range, out);
748 calls_in_block(body, out);
749 }
750 java::Statement::For {
751 init,
752 condition,
753 step,
754 body,
755 } => {
756 calls_in_statement(init, out);
757 calls_in_expr(condition, out);
758 calls_in_expr(step, out);
759 calls_in_block(body, out);
760 }
761 java::Statement::While { condition, body } => {
762 calls_in_expr(condition, out);
763 calls_in_block(body, out);
764 }
765 java::Statement::Switch { value, cases } => {
766 calls_in_expr(value, out);
767 for case in cases {
768 for label in &case.labels {
769 calls_in_expr(label, out);
770 }
771 calls_in_block(&case.body, out);
772 }
773 }
774 java::Statement::Break | java::Statement::Comment(_) => {}
775 }
776}
777
778#[allow(clippy::too_many_lines)]
783fn calls_in_expr(expr: &java::Expr, out: &mut Vec<String>) {
784 match expr {
785 java::Expr::MethodCall {
786 receiver,
787 name,
788 args,
789 } => {
790 if receiver.is_none() {
794 let name = name.as_str();
795 if name.starts_with("zd_def_") && !out.iter().any(|seen| seen == name) {
796 out.push(name.to_string());
797 }
798 }
799 if let Some(receiver) = receiver {
800 calls_in_expr(receiver, out);
801 }
802 for arg in args {
803 calls_in_expr(arg, out);
804 }
805 }
806 java::Expr::Field { value, .. }
807 | java::Expr::Cast { value, .. }
808 | java::Expr::InstanceOf { value, .. }
809 | java::Expr::Paren(value) => calls_in_expr(value, out),
810 java::Expr::Index { value, index } => {
811 calls_in_expr(value, out);
812 calls_in_expr(index, out);
813 }
814 java::Expr::New { args, .. } => {
815 for arg in args {
816 calls_in_expr(arg, out);
817 }
818 }
819 java::Expr::NewArray {
820 lengths, elements, ..
821 } => {
822 for length in lengths {
823 calls_in_expr(length, out);
824 }
825 for element in elements {
826 calls_in_expr(element, out);
827 }
828 }
829 java::Expr::Binary { lhs, rhs, .. } => {
830 calls_in_expr(lhs, out);
831 calls_in_expr(rhs, out);
832 }
833 java::Expr::Ternary {
834 condition,
835 then,
836 otherwise,
837 } => {
838 calls_in_expr(condition, out);
839 calls_in_expr(then, out);
840 calls_in_expr(otherwise, out);
841 }
842 java::Expr::Lambda { body, .. } => calls_in_expr(body, out),
843 java::Expr::ArrayInit(elements) => {
844 for element in elements {
845 calls_in_expr(element, out);
846 }
847 }
848 java::Expr::Literal(_)
849 | java::Expr::Path(_)
850 | java::Expr::This
851 | java::Expr::Annotation(_) => {}
852 }
853}
854
855fn name(text: &str) -> java::Expr {
858 java::Expr::Path(Path::new(&text.split('.').collect::<Vec<_>>()))
859}
860
861fn text(value: &str) -> java::Expr {
862 java::Expr::Literal(Literal::Str(value.to_string()))
863}
864
865fn call(callee: &str, args: Vec<java::Expr>) -> java::Expr {
866 java::Expr::MethodCall {
867 receiver: None,
868 name: Ident::new(callee),
869 args,
870 }
871}
872
873fn member(base: &str, field: &str) -> java::Expr {
877 if crate::adapter::java::mapping() == crate::adapter::java::JavaMapping::Psm {
878 return crate::adapter::java::accessor(name(base), field);
879 }
880 java::Expr::Field {
881 value: Box::new(name(base)),
882 name: Ident::new(field),
883 }
884}
885
886fn assign(place: java::Expr, value: java::Expr) -> java::Statement {
887 crate::adapter::java::assign(place, value)
888}
889
890fn new_array(element: Box<java::Type>, lengths: Vec<java::Expr>) -> java::Expr {
899 let mut innermost = &*element;
900 while let java::Type::Array(inner) = innermost {
901 innermost = inner;
902 }
903 if let java::Type::Named { path, args } = innermost {
904 if !args.is_empty() {
905 let mut segments: Vec<&str> = path
906 .segments()
907 .iter()
908 .map(|segment| segment.as_str())
909 .collect();
910 segments.push("class");
911 let mut arguments = vec![java::Expr::Path(Path::new(&segments))];
912 arguments.extend(lengths);
913 return java::Expr::MethodCall {
914 receiver: Some(Box::new(java::Expr::Path(Path::new(&[
915 crate::adapter::java::SEQUENCES,
916 ])))),
917 name: Ident::new("newArray"),
918 args: arguments,
919 };
920 }
921 }
922 java::Expr::NewArray {
923 element,
924 lengths,
925 elements: Vec::new(),
926 }
927}
928
929fn give_back(value: java::Expr) -> java::Statement {
930 java::Statement::Return(Some(value))
931}
932
933fn new_local(type_: java::Type) -> java::Statement {
935 java::Statement::Declare {
936 final_: false,
937 type_: type_.clone(),
938 name: Ident::new("v"),
939 value: Some(java::Expr::New {
940 type_: Box::new(type_),
941 args: Vec::new(),
942 }),
943 }
944}
945
946fn counted_loop(index: &str, count: java::Expr, body: java::Block) -> java::Statement {
947 java::Statement::For {
948 init: Box::new(java::Statement::Declare {
949 final_: false,
950 type_: java::Type::Primitive(java::Primitive::Int),
951 name: Ident::new(index),
952 value: Some(java::Expr::Literal(Literal::int(0))),
953 }),
954 condition: java::Expr::Binary {
955 op: "<",
956 lhs: Box::new(name(index)),
957 rhs: Box::new(count),
958 },
959 step: java::Expr::Binary {
960 op: "=",
961 lhs: Box::new(name(index)),
962 rhs: Box::new(java::Expr::Binary {
963 op: "+",
964 lhs: Box::new(name(index)),
965 rhs: Box::new(java::Expr::Literal(Literal::int(1))),
966 }),
967 },
968 body,
969 }
970}
971
972const _: Option<MaterialiseError> = None;