verilization_lang_java/
lib.rs

1use verilization_compiler::{model, lang, util, for_sep};
2
3use model::Named;
4use crate::lang::{GeneratorError, Language, OutputHandler};
5use std::ffi::OsString;
6use std::collections::HashMap;
7use std::io::Write;
8use std::path::PathBuf;
9use num_bigint::BigUint;
10use lang::generator::*;
11use util::{capitalize_identifier, uncapitalize_identifier};
12use num_traits::ToPrimitive;
13
14type PackageMap = HashMap<model::PackageName, model::PackageName>;
15type ExternMap = HashMap<model::QualifiedName, model::QualifiedName>;
16const RUNTIME_PACKAGE: &str = "dev.argon.verilization.runtime";
17
18
19pub struct JavaOptionsBuilder {
20	output_dir: Option<OsString>,
21	package_mapping: PackageMap,
22	library_mapping: PackageMap,
23	extern_mapping: ExternMap,
24}
25
26pub struct JavaOptions {
27	pub output_dir: OsString,
28	pub package_mapping: PackageMap,
29	pub library_mapping: PackageMap,
30	pub extern_mapping: ExternMap,
31}
32
33fn make_type_name(name: &str) -> String {
34	let mut name = String::from(name);
35	capitalize_identifier(&mut name);
36	name
37}
38
39fn make_field_name(field_name: &str) -> String {
40	let mut name = String::from(field_name);
41	uncapitalize_identifier(&mut name);
42	name
43}
44
45
46fn java_package_impl<'opt>(options: &'opt JavaOptions, package: &model::PackageName) -> Result<&'opt model::PackageName, GeneratorError> {
47	options.package_mapping.get(&package)
48		.or_else(|| options.library_mapping.get(&package))
49		.ok_or_else(|| GeneratorError::UnmappedPackage(package.clone()))
50}
51
52fn open_java_file<'output, Output: OutputHandler<'output>>(options: &JavaOptions, output: &'output mut Output, name: &model::QualifiedName) -> Result<Output::FileHandle, GeneratorError> {
53	let java_pkg = java_package_impl(options, &name.package)?;
54	let mut path = PathBuf::from(&options.output_dir);
55	for part in &java_pkg.package {
56		path.push(part);
57	}
58	
59	path.push(make_type_name(&name.name) + ".java");
60	Ok(output.create_file(path)?)
61}
62
63pub trait JavaGenerator<'model, 'opt> : Generator<'model> + GeneratorWithFile {
64	fn options(&self) -> &'opt JavaOptions;
65	fn referenced_types(&self) -> model::ReferencedTypeIterator<'model>;
66
67	fn java_package(&self, package: &model::PackageName) -> Result<&'opt model::PackageName, GeneratorError> {
68		java_package_impl(self.options(), package)
69	}
70
71	fn write_package(&mut self, package: &model::PackageName) -> Result<(), GeneratorError> {
72	
73		let pkg = self.java_package(package)?;
74	
75		let mut pkg_iter = pkg.package.iter();
76	
77		if let Some(part) = pkg_iter.next() {
78			write!(self.file(), "package {}", part)?;
79			while let Some(part) = pkg_iter.next() {
80				write!(self.file(), ".{}", part)?;
81			}
82			writeln!(self.file(), ";")?;
83		}
84	
85		Ok(())
86	}
87
88	fn write_qual_name(&mut self, name: &model::QualifiedName) -> Result<(), GeneratorError> {
89		let pkg = self.java_package(&name.package)?;
90		for part in &pkg.package {
91			write!(self.file(), "{}.", part)?;
92		}
93	
94		write!(self.file(), "{}", make_type_name(&name.name))?;
95	
96		Ok(())
97	}
98	
99	fn write_type_args(&mut self, args: &Vec<LangType<'model>>) -> Result<(), GeneratorError> {
100		if !args.is_empty() {
101			write!(self.file(), "<")?;
102			for_sep!(arg, args, { write!(self.file(), ", ")?; }, {
103				self.write_type(arg, true)?;
104			});
105			write!(self.file(), ">")?;
106
107		}
108	
109		Ok(())
110	}
111	
112	fn extern_type_name(&self, name: &model::QualifiedName, erased: bool) -> Result<model::QualifiedName, GeneratorError> {
113		Ok(if let Some(mapped_name) = self.options().extern_mapping.get(name) {
114			if erased {
115				match (&mapped_name.package.package[..], mapped_name.name.as_ref()) {
116					([], "byte") => model::QualifiedName::from_parts(&["java", "lang"], "Byte"),
117					([], "short") => model::QualifiedName::from_parts(&["java", "lang"], "Short"),
118					([], "int") => model::QualifiedName::from_parts(&["java", "lang"], "Integer"),
119					([], "long") => model::QualifiedName::from_parts(&["java", "lang"], "Long"),
120					([], "float") => model::QualifiedName::from_parts(&["java", "lang"], "Float"),
121					([], "double") => model::QualifiedName::from_parts(&["java", "lang"], "Double"),
122					([], "boolean") => model::QualifiedName::from_parts(&["java", "lang"], "Boolean"),
123					([], "char") => model::QualifiedName::from_parts(&["java", "lang"], "Character"),
124					_ => mapped_name.clone(),
125				}
126			}
127			else {
128				mapped_name.clone()
129			}
130		}
131		else {
132			model::QualifiedName {
133				package: self.java_package(&name.package)?.clone(),
134				name: make_type_name(&name.name),
135			}
136		})
137	}
138	
139	fn write_type(&mut self, t: &LangType<'model>, erased: bool) -> Result<(), GeneratorError> {
140		Ok(match t {
141			LangType::Versioned(_, name, version, args, _) => {
142				self.write_qual_name(name)?;
143				write!(self.file(), ".V{}", version)?;
144				self.write_type_args(args)?;
145			},
146
147			LangType::Extern(name, args, _) => {
148				let mapped_name = self.extern_type_name(name, erased)?;
149
150				for part in &mapped_name.package.package {
151					write!(self.file(), "{}.", part)?;
152				}
153			
154				write!(self.file(), "{}", mapped_name.name)?;
155
156
157				self.write_type_args(args)?;
158			},
159
160			LangType::TypeParameter(name) => {
161				write!(self.file(), "{}", name)?;
162			},
163
164			LangType::Converter(from, to) => {
165				write!(self.file(), "{}.Converter<", RUNTIME_PACKAGE)?;
166				self.write_type(&*from, true)?;
167				write!(self.file(), ", ")?;
168				self.write_type(&*to, true)?;
169				write!(self.file(), ">")?;
170			},
171
172			LangType::Codec(t) => {
173				write!(self.file(), "{}.Codec<", RUNTIME_PACKAGE)?;
174				self.write_type(&*t, true)?;
175				write!(self.file(), ">")?;
176			},
177		})
178	}
179
180	fn write_args(&mut self, args: &Vec<LangExpr<'model>>) -> Result<(), GeneratorError> {
181		if !args.is_empty() {
182			write!(self.file(), "(")?;
183			for_sep!(arg, args, { write!(self.file(), ", ")?; }, {
184				self.write_expr(&arg)?;
185			});
186			write!(self.file(), ")")?;
187		}
188
189		Ok(())
190	}
191
192	fn write_operation_name(&mut self, op: &Operation) -> Result<(), GeneratorError> {
193		match op {
194			Operation::FromPreviousVersion(prev_ver) => write!(self.file(), "fromV{}", prev_ver)?,
195			Operation::FinalTypeConverter => write!(self.file(), "converter")?,
196			Operation::TypeCodec => write!(self.file(), "codec")?,
197			Operation::FromInteger => write!(self.file(), "fromInteger")?,
198			Operation::FromString => write!(self.file(), "fromString")?,
199			Operation::FromSequence => write!(self.file(), "fromSequence")?,
200			Operation::FromRecord(_) => write!(self.file(), "fromRecord")?,
201			Operation::FromCase(name) => write!(self.file(), "fromCase{}", make_type_name(name))?,
202		}
203
204		Ok(())
205	}
206	
207	fn write_expr(&mut self, expr: &LangExpr<'model>) -> Result<(), GeneratorError> {
208		match expr {
209			LangExpr::Identifier(name) => write!(self.file(), "{}", name)?,
210			LangExpr::IntegerLiteral(n) => {
211				if let Some(n) = n.to_i32() {
212					write!(self.file(), "{}", n)?;
213				}
214				else if let Some(n) = n.to_i64() {
215					write!(self.file(), "{}L", n)?;
216				}
217				else {
218					write!(self.file(), "java.math.BigInteger.valueOf(\"{}\")", n)?;
219				}
220			},
221			LangExpr::StringLiteral(s) => {
222				write!(self.file(), "\"")?;
223				for codepoint in s.chars() {
224					match codepoint {
225						'"' => write!(self.file(), "\\\"")?,
226						'\\' => write!(self.file(), "\\\\")?,
227						'\n' => write!(self.file(), "\\n")?,
228						'\r' => write!(self.file(), "\\r")?,
229						_ => write!(self.file(), "{}", codepoint)?,
230					}
231				}
232				write!(self.file(), "\"")?;
233			},
234			LangExpr::InvokeConverter { converter, value } => {
235				self.write_expr(&*converter)?;
236				write!(self.file(), ".convert(")?;
237				self.write_expr(&*value)?;
238				write!(self.file(), ")")?;
239			},
240			LangExpr::IdentityConverter(t) => {
241				write!(self.file(), "{}.Converter.<", RUNTIME_PACKAGE)?;
242				self.write_type(t, true)?;
243				write!(self.file(), ">identity()")?;
244			},
245			LangExpr::ReadDiscriminator => write!(self.file(), "{}.Nat.codec.read(reader)", RUNTIME_PACKAGE)?,
246			LangExpr::WriteDiscriminator(value) => write!(self.file(), "{}.Nat.codec.write(writer, java.math.BigInteger.valueOf({}))", RUNTIME_PACKAGE, value)?,
247			LangExpr::CodecRead { codec } => {
248				self.write_expr(&*codec)?;
249				write!(self.file(), ".read(reader)")?;
250			},
251			LangExpr::CodecWrite { codec, value } => {
252				self.write_expr(&*codec)?;
253				write!(self.file(), ".write(writer, ")?;
254				self.write_expr(value)?;
255				write!(self.file(), ")")?;
256			},
257			LangExpr::InvokeOperation(op, target, type_args, args) => {
258				match target {
259					OperationTarget::VersionedType(name, version) => {
260						self.write_qual_name(name)?;
261						write!(self.file(), ".V{}.", version)?;
262					},
263					OperationTarget::ExternType(name) => {
264						self.write_qual_name(name)?;
265						write!(self.file(), ".")?;
266					},
267				}
268				self.write_type_args(type_args)?;
269				self.write_operation_name(op)?;
270				self.write_args(args)?;
271			},
272			LangExpr::InvokeUserConverter { name, prev_ver, version, type_args, args } => {
273				self.write_qual_name(name)?;
274				write!(self.file(), "_Conversions.")?;
275				self.write_type_args(type_args)?;
276				write!(self.file(), "v{}ToV{}", prev_ver, version)?;
277				self.write_args(args)?;
278			},
279			LangExpr::ConstantValue(name, version) => {
280				self.write_qual_name(name)?;
281				write!(self.file(), ".{}", JavaLanguage::constant_version_name(version))?;
282			},
283			LangExpr::CreateStruct(name, version, type_args, fields) => {
284				write!(self.file(), "new ")?;
285				self.write_qual_name(name)?;
286				write!(self.file(), ".V{}", version)?;
287				self.write_type_args(type_args)?;
288				write!(self.file(), "(")?;
289				for_sep!((_, value), fields, { write!(self.file(), ", ")?; }, {
290					self.write_expr(value)?;
291				});
292				write!(self.file(), ")")?;
293			},
294			LangExpr::CreateEnum(name, version, type_args, field_name, value) => {
295				write!(self.file(), "new ")?;
296				self.write_qual_name(name)?;
297				write!(self.file(), ".V{}.{}", version, make_type_name(field_name))?;
298				self.write_type_args(type_args)?;
299				write!(self.file(), "(")?;
300				self.write_expr(value)?;
301				write!(self.file(), ")")?;
302			},
303			LangExpr::StructField(_, _, field_name, value) => {
304				self.write_expr(value)?;
305				write!(self.file(), ".{}", make_field_name(field_name))?;
306			},
307		}
308
309		Ok(())
310	}
311}
312
313impl GeneratorNameMapping for JavaLanguage {
314	fn convert_prev_type_param(param: &str) -> String {
315		format!("{}_1", param)
316	}
317
318	fn convert_current_type_param(param: &str) -> String {
319		format!("{}_2", param)
320	}
321
322	fn convert_conv_param_name(param: &str) -> String {
323		format!("{}_conv", param)
324	}
325
326	fn convert_prev_param_name() -> &'static str {
327		"prev"
328	}
329
330	fn codec_write_value_name() -> &'static str {
331		"value"
332	}
333
334	fn codec_codec_param_name(param: &str) -> String {
335		format!("{}_codec", param)
336	}
337
338	fn constant_version_name(version: &BigUint) -> String {
339		format!("v{}", version)
340	}
341}
342
343
344struct JavaConstGenerator<'model, 'opt, 'output, Output: OutputHandler<'output>> {
345	file: Output::FileHandle,
346	model: &'model model::Verilization,
347	options: &'opt JavaOptions,
348	constant: Named<'model, model::Constant>,
349	scope: model::Scope<'model>,
350}
351
352impl <'model, 'opt, 'output, Output: OutputHandler<'output>> Generator<'model> for JavaConstGenerator<'model, 'opt, 'output, Output> {
353	type Lang = JavaLanguage;
354
355	fn model(&self) -> &'model model::Verilization {
356		self.model
357	}
358
359	fn scope(&self) -> &model::Scope<'model> {
360		&self.scope
361	}
362}
363
364impl <'model, 'opt, 'output, Output: OutputHandler<'output>> GeneratorWithFile for JavaConstGenerator<'model, 'opt, 'output, Output> {
365	type GeneratorFile = Output::FileHandle;
366	fn file(&mut self) -> &mut Self::GeneratorFile {
367		&mut self.file
368	}
369}
370
371impl <'model, 'opt, 'output, Output: OutputHandler<'output>> JavaGenerator<'model, 'opt> for JavaConstGenerator<'model, 'opt, 'output, Output> {
372	fn options(&self) -> &'opt JavaOptions {
373		self.options
374	}
375
376	fn referenced_types(&self) -> model::ReferencedTypeIterator<'model> {
377		self.constant.referenced_types()
378	}
379}
380
381impl <'model, 'opt, 'output, Output: OutputHandler<'output>> ConstGenerator<'model> for JavaConstGenerator<'model, 'opt, 'output, Output> {
382	fn constant(&self) -> Named<'model, model::Constant> {
383		self.constant
384	}
385
386	fn write_header(&mut self) -> Result<(), GeneratorError> {
387        self.write_package(&self.constant.name().package)?;
388
389		writeln!(self.file, "public final class {} {{", make_type_name(&self.constant.name().name))?;
390		writeln!(self.file, "\tprivate {}() {{}}", make_type_name(&self.constant.name().name))?;
391
392		Ok(())
393	}
394
395	fn write_constant(&mut self, version_name: String, t: LangType<'model>, value: LangExpr<'model>) -> Result<(), GeneratorError> {
396		write!(self.file, "\tpublic static final ")?;
397		self.write_type(&t, false)?;
398		write!(self.file, " {} = ", version_name)?;
399		self.write_expr(&value)?;
400		writeln!(self.file, ";")?;
401
402		Ok(())
403	}
404
405	fn write_footer(&mut self) -> Result<(), GeneratorError> {
406		writeln!(self.file, "}}")?;
407		Ok(())
408	}
409}
410
411impl <'model, 'opt, 'output, Output: OutputHandler<'output>> JavaConstGenerator<'model, 'opt, 'output, Output> {
412
413	fn open(model: &'model model::Verilization, options: &'opt JavaOptions, output: &'output mut Output, constant: Named<'model, model::Constant>) -> Result<Self, GeneratorError> {
414		let file = open_java_file(options, output, constant.name())?;
415		Ok(JavaConstGenerator {
416			file: file,
417			model: model,
418			options: options,
419			constant: constant,
420			scope: constant.scope(),
421		})
422	}
423}
424
425struct JavaTypeGenerator<'model, 'opt, 'output, Output: OutputHandler<'output>> {
426	file: Output::FileHandle,
427	model: &'model model::Verilization,
428	options: &'opt JavaOptions,
429	type_def: Named<'model, model::VersionedTypeDefinitionData>,
430	scope: model::Scope<'model>,
431	indentation_level: u32,
432}
433
434impl <'model, 'opt, 'output, Output: OutputHandler<'output>> Generator<'model> for JavaTypeGenerator<'model, 'opt, 'output, Output> {
435	type Lang = JavaLanguage;
436
437	fn model(&self) -> &'model model::Verilization {
438		self.model
439	}
440
441	fn scope(&self) -> &model::Scope<'model> {
442		&self.scope
443	}
444}
445
446impl <'model, 'opt, 'output, Output: OutputHandler<'output>> GeneratorWithFile for JavaTypeGenerator<'model, 'opt, 'output, Output> {
447	type GeneratorFile = Output::FileHandle;
448	fn file(&mut self) -> &mut Self::GeneratorFile {
449		&mut self.file
450	}
451}
452
453impl <'model, 'opt, 'output, Output: OutputHandler<'output>> Indentation for JavaTypeGenerator<'model, 'opt, 'output, Output> {
454	fn indentation_size(&mut self) -> &mut u32 {
455		&mut self.indentation_level
456	}
457}
458
459impl <'model, 'opt, 'output, Output: OutputHandler<'output>> JavaGenerator<'model, 'opt> for JavaTypeGenerator<'model, 'opt, 'output, Output> {
460	fn options(&self) -> &'opt JavaOptions {
461		self.options
462	}
463
464	fn referenced_types(&self) -> model::ReferencedTypeIterator<'model> {
465		self.type_def.referenced_types()
466	}
467}
468
469impl <'model, 'opt, 'output, Output: OutputHandler<'output>> VersionedTypeGenerator<'model> for JavaTypeGenerator<'model, 'opt, 'output, Output> {
470	fn type_def(&self) -> Named<'model, model::VersionedTypeDefinitionData> {
471		self.type_def
472	}
473
474	fn write_header(&mut self) -> Result<(), GeneratorError> {
475		self.write_package(&self.type_def.name().package)?;
476		writeln!(self.file, "public abstract class {} {{", make_type_name(&self.type_def.name().name))?;
477		self.indent_increase();
478		self.write_indent()?;
479		writeln!(self.file, "private {}() {{}}", make_type_name(&self.type_def.name().name))?;
480		
481		Ok(())
482	}
483
484	fn write_version_header(&mut self, t: LangType<'model>) -> Result<(), GeneratorError> {
485		self.write_indent()?;
486
487
488		match &t {
489			LangType::Versioned(VersionedTypeKind::Struct, _, version, _, _) => write!(self.file, "public static final class V{}", version)?,
490			LangType::Versioned(VersionedTypeKind::Enum, _, version, _, _) => write!(self.file, "public static abstract class V{}", version)?,
491			_ => return Err(GeneratorError::CouldNotGenerateType)
492		}
493		
494		self.write_type_params(self.type_def().type_params())?;
495		writeln!(self.file, " extends {} {{", self.type_def.name().name)?;
496		self.indent_increase();
497
498		match t {
499			LangType::Versioned(VersionedTypeKind::Struct, _, version, _, fields) => {
500				self.write_indent()?;
501				write!(self.file, "public V{}(", version)?;
502
503				let fields = fields.build()?;
504
505				for_sep!(field, &fields, { write!(self.file, ",")?; }, {
506					self.write_type(&field.field_type, false)?;
507					write!(self.file, " {}", make_field_name(field.name))?;
508				});
509
510				writeln!(self.file, ") {{")?;
511				self.indent_increase();
512				
513				for field in &fields {
514					self.write_indent()?;
515					writeln!(self.file, "this.{} = {};", make_field_name(field.name), make_field_name(field.name))?;
516				}
517
518				self.indent_decrease();
519				self.write_indent()?;
520				writeln!(self.file, "}}")?;
521
522				for field in &fields {
523					self.write_indent()?;
524					write!(self.file, "public final ")?;
525					self.write_type(&field.field_type, false)?;
526					writeln!(self.file, " {};", make_field_name(field.name))?;
527				}
528
529				self.write_indent()?;
530				writeln!(self.file, "@Override")?;
531
532				self.write_indent()?;
533				writeln!(self.file, "public int hashCode() {{")?;
534				self.indent_increase();
535
536				self.write_indent()?;
537				write!(self.file, "return java.util.Objects.hash(")?;
538				for_sep!(field, &fields, { write!(self.file, ", ")?; }, {
539					write!(self.file, "{}", make_field_name(field.name))?;
540				});
541				writeln!(self.file, ");")?;
542				self.indent_decrease();
543				self.write_indent()?;
544				writeln!(self.file, "}}")?;
545
546				self.write_indent()?;
547				writeln!(self.file, "@Override")?;
548				self.write_indent()?;
549				writeln!(self.file, "public boolean equals(Object obj) {{")?;
550				self.indent_increase();
551				self.write_indent()?;
552				writeln!(self.file, "if(!(obj instanceof V{})) return false;", version)?;
553				self.write_indent()?;
554				writeln!(self.file, "V{} other = (V{})obj;", version, version)?;
555				for field in &fields {
556					self.write_indent()?;
557					writeln!(self.file, "if(!java.util.Objects.deepEquals(this.{}, other.{})) return false;", make_field_name(field.name), make_field_name(field.name))?;
558				}
559				self.write_indent()?;
560				writeln!(self.file, "return true;")?;
561				self.indent_decrease();
562				self.write_indent()?;
563				writeln!(self.file, "}}")?;
564			},
565			LangType::Versioned(VersionedTypeKind::Enum, _, version, _, fields) => {
566				self.write_indent()?;
567				writeln!(self.file, "private V{}() {{}}", version)?;
568
569				let fields = fields.build()?;
570		
571				for (index, field) in fields.iter().enumerate() {
572					self.write_indent()?;
573					write!(self.file, "public static final class {}", make_type_name(field.name))?;
574					self.write_type_params(self.type_def().type_params())?;
575					write!(self.file, " extends V{}", version)?;
576					self.write_type_params(self.type_def().type_params())?;
577					writeln!(self.file, " {{")?;
578		
579					self.indent_increase();
580					self.write_indent()?;
581					write!(self.file, "public {}(", make_type_name(field.name))?;
582					self.write_type(&field.field_type, false)?;
583					writeln!(self.file, " {}) {{", make_field_name(field.name))?;
584					self.indent_increase();
585					self.write_indent()?;
586					writeln!(self.file, "this.{} = {};", make_field_name(field.name), make_field_name(field.name))?;
587					self.indent_decrease();
588					self.write_indent()?;
589					writeln!(self.file, "}}")?;
590					self.write_indent()?;
591					write!(self.file, "public final ")?;
592					self.write_type(&field.field_type, false)?;
593					writeln!(self.file, " {};", make_field_name(field.name))?;
594					
595					self.write_indent()?;
596					writeln!(self.file, "@Override")?;
597					self.write_indent()?;
598					writeln!(self.file, "public int hashCode() {{")?;
599					self.indent_increase();
600					self.write_indent()?;
601					writeln!(self.file, "return java.util.Objects.hash({}, this.{});", index, make_field_name(field.name))?;
602					self.indent_decrease();
603					self.write_indent()?;
604					writeln!(self.file, "}}")?;
605					
606					self.write_indent()?;
607					writeln!(self.file, "@Override")?;
608					self.write_indent()?;
609					writeln!(self.file, "public boolean equals(Object obj) {{")?;
610					self.indent_increase();
611					self.write_indent()?;
612					writeln!(self.file, "if(!(obj instanceof {})) return false;", make_type_name(field.name))?;
613					self.write_indent()?;
614					writeln!(self.file, "{} other = ({})obj;", make_type_name(field.name), make_type_name(field.name))?;
615					self.write_indent()?;
616					writeln!(self.file, "return java.util.Objects.deepEquals(this.{}, other.{});", make_field_name(field.name), make_field_name(field.name))?;
617					self.indent_decrease();
618					self.write_indent()?;
619					writeln!(self.file, "}}")?;
620			
621					self.indent_decrease();
622					self.write_indent()?;
623					writeln!(self.file, "}}")?;
624				}
625			},
626			_ => return Err(GeneratorError::CouldNotGenerateType)
627		}
628
629		Ok(())
630	}
631
632	fn write_operation(&mut self, operation: OperationInfo<'model>) -> Result<(), GeneratorError> {
633		let is_func = !operation.type_params.is_empty() || !operation.params.is_empty();
634
635		self.write_indent()?;
636		write!(self.file, "public static ")?;
637		if !is_func {
638			write!(self.file, "final ")?;
639		}
640		self.write_type_params(&operation.type_params)?;
641		if !operation.type_params.is_empty() {
642			write!(self.file, " ")?;
643		}
644
645		self.write_type(&operation.result, false)?;
646		write!(self.file, " ")?;
647
648		self.write_operation_name(&operation.operation)?;
649
650		if is_func {
651			write!(self.file, "(")?;
652			for_sep!((param_name, param), operation.params, { write!(self.file, ", ")?; }, {
653				self.write_type(&param, true)?;
654				write!(self.file, " {}", param_name)?;
655			});
656			writeln!(self.file, ") {{")?;
657			self.indent_increase();
658		}
659		else {
660			write!(self.file, " = ")?;
661		}
662
663		self.write_expr_statement(&operation.implementation, !is_func)?;
664
665		if is_func {
666			self.indent_decrease();
667			self.write_indent()?;
668			writeln!(self.file, "}}")?;
669		}
670
671		Ok(())
672	}
673
674	fn write_version_footer(&mut self) -> Result<(), GeneratorError> {
675		self.indent_decrease();
676		writeln!(self.file, "}}")?;
677
678		Ok(())
679	}
680
681	fn write_footer(&mut self) -> Result<(), GeneratorError> {
682		self.indent_decrease();
683		writeln!(self.file, "}}")?;
684		
685		Ok(())
686	}
687
688}
689
690
691fn write_enum_case_type<'model, 'opt, Gen>(gen: &mut Gen, value_type: &LangType<'model>, case_name: &str, wildcard: bool) -> Result<(), GeneratorError> where
692	Gen : JavaGenerator<'model, 'opt> + GeneratorWithFile
693{
694	match value_type {
695		LangType::Versioned(VersionedTypeKind::Enum, name, version, args, _) => {
696			gen.write_qual_name(name)?;
697			write!(gen.file(), ".V{}.{}", version, make_type_name(case_name))?;
698			if !args.is_empty() {
699				write!(gen.file(), "<")?;
700				for_sep!(arg, args, { write!(gen.file(), ", ")?; }, {
701					if wildcard {
702						write!(gen.file(), "?")?;
703					}
704					else {
705						gen.write_type(arg, true)?;
706					}
707				});
708				write!(gen.file(), ">")?;
709			}
710		},
711		_ => panic!("Invalid enum type."),
712	}
713
714	Ok(())
715}
716
717impl <'model, 'opt, 'output, Output: OutputHandler<'output>> JavaTypeGenerator<'model, 'opt, 'output, Output> {
718
719
720	fn open(model: &'model model::Verilization, options: &'opt JavaOptions, output: &'output mut Output, type_def: Named<'model, model::VersionedTypeDefinitionData>) -> Result<Self, GeneratorError> {
721		let file = open_java_file(options, output, type_def.name())?;
722		Ok(JavaTypeGenerator {
723			file: file,
724			model: model,
725			options: options,
726			type_def: type_def,
727			scope: type_def.scope(),
728			indentation_level: 0,
729		})
730	}
731
732	fn write_expr_statement(&mut self, stmt: &LangExprStmt<'model>, is_expr: bool) -> Result<(), GeneratorError> {
733		if !is_expr {
734			self.write_indent()?;
735			write!(self.file, "return ")?;
736		}
737
738		match stmt {
739			LangExprStmt::Expr(expr) => {
740				self.write_expr(expr)?;
741				writeln!(self.file, ";")?;
742			},
743
744			LangExprStmt::CreateCodec { t, read, write } => {
745				write!(self.file, "new {}.Codec<", RUNTIME_PACKAGE)?;
746				self.write_type(t, true)?;
747				writeln!(self.file, ">() {{")?;
748				self.indent_increase();
749
750
751				self.write_indent()?;
752				writeln!(self.file, "@Override")?;
753
754				self.write_indent()?;
755				write!(self.file, "public ")?;
756				self.write_type(t, true)?;
757				writeln!(self.file, " read({}.FormatReader reader) throws java.io.IOException {{", RUNTIME_PACKAGE)?;
758				self.indent_increase();
759				
760				self.write_statement(read)?;
761
762				self.indent_decrease();
763				self.write_indent()?;
764				writeln!(self.file, "}}")?;
765
766				self.write_indent()?;
767				writeln!(self.file, "@Override")?;
768
769				self.write_indent()?;
770				write!(self.file, "public void write({}.FormatWriter writer, ", RUNTIME_PACKAGE)?;
771				self.write_type(t, true)?;
772				writeln!(self.file, " value) throws java.io.IOException {{")?;
773				self.indent_increase();
774
775				self.write_statement(write)?;
776
777				self.indent_decrease();
778				self.write_indent()?;
779				writeln!(self.file, "}}")?;
780
781				self.indent_decrease();
782				self.write_indent()?;
783				writeln!(self.file, "}};")?;
784			},
785
786			LangExprStmt::CreateConverter { from_type, to_type, body } => {
787				write!(self.file, "new {}.Converter<", RUNTIME_PACKAGE)?;
788				self.write_type(from_type, true)?;
789				write!(self.file, ", ")?;
790				self.write_type(to_type, true)?;
791				writeln!(self.file, ">() {{")?;
792				self.indent_increase();
793
794
795				self.write_indent()?;
796				writeln!(self.file, "@Override")?;
797
798				self.write_indent()?;
799				write!(self.file, "public ")?;
800				self.write_type(to_type, true)?;
801				write!(self.file, " convert(")?;
802				self.write_type(from_type, true)?;
803				writeln!(self.file, " {}) {{", JavaLanguage::convert_prev_param_name())?;
804				self.indent_increase();
805
806				self.write_statement(body)?;
807
808				self.indent_decrease();
809				self.write_indent()?;
810				writeln!(self.file, "}}")?;
811
812				self.indent_decrease();
813				self.write_indent()?;
814				writeln!(self.file, "}};")?;
815			},
816
817		}
818
819		Ok(())
820	}
821	
822	fn write_statement(&mut self, stmt: &LangStmt<'model>) -> Result<(), GeneratorError> {
823		match stmt {
824			LangStmt::Expr(exprs, result_expr) => {
825				for expr in exprs {
826					self.write_indent()?;
827					self.write_expr(expr)?;
828					writeln!(self.file, ";")?;
829				}
830
831				if let Some(result_expr) = result_expr {
832					self.write_indent()?;
833					write!(self.file, "return ")?;
834					self.write_expr(result_expr)?;
835					writeln!(self.file, ";")?;
836				}
837			},
838
839			LangStmt::MatchEnum { value, value_type, cases } => {
840				self.write_indent()?;
841				for MatchCase { binding_name, case_name, body } in cases {
842					write!(self.file, "if(")?;
843					self.write_expr(value)?;
844					write!(self.file, " instanceof ")?;
845					write_enum_case_type(self, value_type, case_name, true)?;
846					writeln!(self.file, ") {{")?;
847					self.indent_increase();
848
849					self.write_indent()?;
850					write!(self.file, "var {} = ((", binding_name)?;
851					write_enum_case_type(self, value_type, case_name, false)?;
852					write!(self.file, ")")?;
853					self.write_expr(value)?;
854					writeln!(self.file, ").{};", make_field_name(case_name))?;
855
856					self.write_statement(body)?;
857
858					self.indent_decrease();
859					self.write_indent()?;
860					writeln!(self.file, "}}")?;
861
862					self.write_indent()?;
863					write!(self.file, "else ")?;
864				}
865				if !cases.is_empty() {
866					writeln!(self.file, "{{")?;
867					self.indent_increase();
868					self.write_indent()?;
869				}
870
871				writeln!(self.file, "throw new IllegalArgumentException();")?;
872				
873				if !cases.is_empty() {
874					self.indent_decrease();
875					self.write_indent()?;
876					writeln!(self.file, "}}")?;
877				}
878			},
879
880			LangStmt::MatchDiscriminator { value, cases } => {
881				self.write_indent()?;
882				write!(self.file, "switch(")?;
883				self.write_expr(value)?;
884				writeln!(self.file, ".intValueExact()) {{")?;
885				self.indent_increase();
886
887				for (n, body) in cases {
888					self.write_indent()?;
889					writeln!(self.file, "case {}:", n)?;
890					self.write_indent()?;
891					writeln!(self.file, "{{")?;
892					self.indent_increase();
893
894					self.write_statement(body)?;
895
896
897					if !body.has_value() {
898						self.write_indent()?;
899						writeln!(self.file, "break;")?;
900					}
901					self.indent_decrease();
902
903					self.write_indent()?;
904					writeln!(self.file, "}}")?;
905				}
906
907				self.write_indent()?;
908				writeln!(self.file, "default: throw new java.io.IOException(\"Invalid tag number.\");")?;
909
910				self.indent_decrease();
911
912				self.write_indent()?;
913				writeln!(self.file, "}}")?;
914			},
915			
916
917		}
918
919		Ok(())
920	}
921
922	fn write_type_params(&mut self, params: &Vec<String>) -> Result<(), GeneratorError> {
923		if !params.is_empty() {
924			write!(self.file, "<")?;
925			for_sep!(param, params, { write!(self.file, ", ")?; }, {
926				write!(self.file, "{}", param)?;
927			});
928			write!(self.file, ">")?;
929		}
930	
931		Ok(())
932	}
933	
934}
935
936
937pub struct JavaLanguage {}
938
939impl Language for JavaLanguage {
940	type OptionsBuilder = JavaOptionsBuilder;
941	type Options = JavaOptions;
942
943    fn name() -> &'static str {
944        "java"
945    }
946
947	fn empty_options() -> JavaOptionsBuilder {
948		JavaOptionsBuilder {
949			output_dir: None,
950			package_mapping: HashMap::new(),
951			library_mapping: HashMap::new(),
952			extern_mapping: HashMap::new(),
953		}
954	}
955
956	fn add_option(builder: &mut JavaOptionsBuilder, name: &str, value: OsString) -> Result<(), GeneratorError> {
957		if name == "out_dir" {
958			if builder.output_dir.is_some() {
959				return Err(GeneratorError::InvalidOptions(String::from("Output directory already specified")))
960			}
961
962			builder.output_dir = Some(value);
963			Ok(())
964		}
965		else if let Some(pkg) = name.strip_prefix("pkg:") {
966			let package = model::PackageName::from_str(pkg);
967
968            let java_package = model::PackageName::from_str(value.to_str().unwrap());
969
970			if builder.library_mapping.contains_key(&package) || builder.package_mapping.insert(package, java_package).is_some() {
971				return Err(GeneratorError::InvalidOptions(format!("Package already mapped: {}", pkg)))
972			}
973			Ok(())
974		}
975		else if let Some(pkg) = name.strip_prefix("lib:") {
976			let package = model::PackageName::from_str(pkg);
977
978            let java_package = model::PackageName::from_str(value.to_str().unwrap());
979
980			if builder.package_mapping.contains_key(&package) || builder.library_mapping.insert(package, java_package).is_some() {
981				return Err(GeneratorError::InvalidOptions(format!("Package already mapped: {}", pkg)))
982			}
983			Ok(())
984		}
985		else if let Some(extern_name) = name.strip_prefix("extern:") {
986			let qual_name = model::QualifiedName::from_str(extern_name).ok_or_else(|| GeneratorError::InvalidOptions(format!("Invalid extern type name: {}", extern_name)))?;
987
988			let java_name = model::QualifiedName::from_str(value.to_str().unwrap()).ok_or_else(|| GeneratorError::InvalidOptions(format!("Invalid Java type name: {}", value.to_str().unwrap())))?;
989
990			if builder.extern_mapping.insert(qual_name, java_name).is_some() {
991				return Err(GeneratorError::InvalidOptions(format!("Extern type already mapped: {}", extern_name)))
992			}
993
994			Ok(())
995		}
996		else {
997			Err(GeneratorError::InvalidOptions(format!("Unknown option: {}", name)))
998		}
999	}
1000
1001	fn finalize_options(builder: Self::OptionsBuilder) -> Result<Self::Options, GeneratorError> {
1002		Ok(JavaOptions {
1003			output_dir: builder.output_dir.ok_or_else(|| GeneratorError::InvalidOptions(String::from("Output directory not specified")))?,
1004			package_mapping: builder.package_mapping,
1005			library_mapping: builder.library_mapping,
1006			extern_mapping: builder.extern_mapping,
1007		})
1008	}
1009
1010	fn generate<Output : for<'output> OutputHandler<'output>>(model: &model::Verilization, options: Self::Options, output: &mut Output) -> Result<(), GeneratorError> {
1011		for constant in model.constants() {
1012			let mut const_gen = JavaConstGenerator::open(model, &options, output, constant)?;
1013			const_gen.generate()?;
1014		}
1015
1016		for t in model.types() {
1017			match t {
1018				model::NamedTypeDefinition::StructType(t) | model::NamedTypeDefinition::EnumType(t) => {
1019					let mut type_gen = JavaTypeGenerator::open(model, &options, output, t)?;
1020					type_gen.generate()?;		
1021				},
1022				model::NamedTypeDefinition::ExternType(_) => (),
1023			}
1024		}
1025
1026		Ok(())
1027	}
1028
1029}