verilization_compiler/lang/
generator.rs

1use crate::lang::GeneratorError;
2use crate::model;
3
4use model::Named;
5
6use std::collections::HashMap;
7use num_bigint::{BigUint, BigInt, Sign};
8use num_traits::One;
9use std::io::Write;
10use std::marker::PhantomData;
11
12#[derive(Copy, Clone, Debug)]
13pub enum VersionedTypeKind {
14	Struct,
15	Enum,
16}
17
18#[derive(Clone, Debug)]
19pub enum LangType<'model> {
20	Versioned(VersionedTypeKind, &'model model::QualifiedName, BigUint, Vec<LangType<'model>>, LangVerTypeFields<'model>),
21	Extern(&'model model::QualifiedName, Vec<LangType<'model>>, LangExternTypeLiterals<'model>),
22	TypeParameter(String),
23	Converter(Box<LangType<'model>>, Box<LangType<'model>>),
24	Codec(Box<LangType<'model>>),
25}
26
27pub struct LangField<'model> {
28	pub name: &'model String,
29	pub field_type: LangType<'model>,
30}
31
32impl <'model> Clone for LangField<'model> {
33	fn clone(&self) -> Self {
34		LangField {
35			name: self.name,
36			field_type: self.field_type.clone(),
37		}
38	}
39}
40
41pub enum LangLiteral<'model> {
42	Integer(model::ExternLiteralIntBound, Option<BigInt>, model::ExternLiteralIntBound, Option<BigInt>),
43	String,
44	Sequence(LangType<'model>),
45	Case(String, Vec<LangType<'model>>),
46	Record(Vec<LangField<'model>>),
47}
48
49pub struct LangVerTypeFields<'model> {
50	model: &'model model::Verilization,
51	type_args: HashMap<String, LangType<'model>>,
52	type_def: Named<'model, model::VersionedTypeDefinitionData>,
53	ver_type: model::TypeVersionInfo<'model>,
54}
55
56impl <'model> Clone for LangVerTypeFields<'model> {
57	fn clone(&self) -> Self {
58		LangVerTypeFields {
59			model: self.model,
60			type_args: self.type_args.clone(),
61			type_def: self.type_def,
62			ver_type: self.ver_type.clone(),
63		}
64	}
65}
66
67impl <'model> std::fmt::Debug for LangVerTypeFields<'model> {
68	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
69		f.debug_struct("LangVerTypeFields").finish()
70	}
71}
72
73impl <'model> LangVerTypeFields<'model> {
74	pub fn build(&self) -> Result<Vec<LangField<'model>>, GeneratorError> {
75		let scope = self.type_def.scope();
76		let mut fields = Vec::new();
77
78		for (name, field) in self.ver_type.ver_type.fields() {
79			let t = build_type_impl(self.model, &self.ver_type.version, &field.field_type, &scope, &self.type_args)?;
80			
81			fields.push(LangField {
82				name: &name,
83				field_type: t,
84			});
85		}
86
87		Ok(fields)
88	}
89}
90
91pub struct LangExternTypeLiterals<'model> {
92	model: &'model model::Verilization,
93	type_args: HashMap<String, LangType<'model>>,
94	type_def: Named<'model, model::ExternTypeDefinitionData>,
95}
96
97impl <'model> Clone for LangExternTypeLiterals<'model> {
98	fn clone(&self) -> Self {
99		LangExternTypeLiterals {
100			model: self.model,
101			type_args: self.type_args.clone(),
102			type_def: self.type_def,
103		}
104	}
105}
106
107impl <'model> std::fmt::Debug for LangExternTypeLiterals<'model> {
108	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
109		f.debug_struct("LangExternTypeLiterals").finish()
110	}
111}
112
113impl <'model> LangExternTypeLiterals<'model> {
114	pub fn build(self) -> Result<Vec<LangLiteral<'model>>, GeneratorError> {
115		let scope = self.type_def.scope();
116		let mut fields = Vec::new();
117
118		for literal in self.type_def.literals() {
119			let lang_literal = match literal {
120				model::ExternLiteralSpecifier::Integer(lower_type, lower, upper_type, upper) => LangLiteral::Integer(*lower_type, lower.clone(), *upper_type, upper.clone()),
121				model::ExternLiteralSpecifier::String => LangLiteral::String,
122				model::ExternLiteralSpecifier::Sequence(t) => LangLiteral::Sequence(build_type_impl(self.model, &BigUint::one(), t, &scope, &self.type_args)?),
123				model::ExternLiteralSpecifier::Case(name, params) =>
124					LangLiteral::Case(name.clone(), params.iter().map(|param| build_type_impl(self.model, &BigUint::one(), param, &scope, &self.type_args)).collect::<Result<Vec<_>, _>>()?),
125				model::ExternLiteralSpecifier::Record(fields) => {
126					let mut lang_fields = Vec::new();
127
128					for (name, field) in fields {
129						let t = build_type_impl(self.model, &BigUint::one(), &field.field_type, &scope, &self.type_args)?;
130						
131						lang_fields.push(LangField {
132							name: &name,
133							field_type: t,
134						});
135					}
136
137					LangLiteral::Record(lang_fields)
138				}
139			};
140			
141			fields.push(lang_literal);
142		}
143
144		Ok(fields)
145	}
146}
147
148
149#[derive(Debug)]
150pub enum Operation {
151	FromPreviousVersion(BigUint),
152	FinalTypeConverter,
153	TypeCodec,
154	FromInteger,
155	FromString,
156	FromSequence,
157	FromCase(String),
158	FromRecord(Vec<String>),
159}
160
161#[derive(Debug)]
162pub enum OperationTarget<'model> {
163	VersionedType(&'model model::QualifiedName, BigUint),
164	ExternType(&'model model::QualifiedName)
165}
166
167#[derive(Debug)]
168pub enum LangExpr<'model> {
169	Identifier(String),
170	IntegerLiteral(BigInt),
171	StringLiteral(String),
172	InvokeConverter {
173		converter: Box<LangExpr<'model>>,
174		value: Box<LangExpr<'model>>,
175	},
176	IdentityConverter(LangType<'model>),
177	ReadDiscriminator,
178	WriteDiscriminator(BigUint),
179	CodecRead {
180		codec: Box<LangExpr<'model>>,
181	},
182	CodecWrite {
183		codec: Box<LangExpr<'model>>,
184		value: Box<LangExpr<'model>>,
185	},
186	InvokeOperation(Operation, OperationTarget<'model>, Vec<LangType<'model>>, Vec<LangExpr<'model>>),
187	InvokeUserConverter {
188		name: &'model model::QualifiedName,
189		prev_ver: BigUint,
190		version: BigUint,
191		type_args: Vec<LangType<'model>>,
192		args: Vec<LangExpr<'model>>,
193	},
194	ConstantValue(&'model model::QualifiedName, BigUint),
195	CreateStruct(&'model model::QualifiedName, BigUint, Vec<LangType<'model>>, Vec<(&'model String, LangExpr<'model>)>),
196	CreateEnum(&'model model::QualifiedName, BigUint, Vec<LangType<'model>>, &'model String, Box<LangExpr<'model>>),
197	StructField(&'model model::QualifiedName, BigUint, &'model String, Box<LangExpr<'model>>),
198}
199
200pub struct OperationInfo<'model> {
201	pub operation: Operation,
202	pub version: BigUint,
203	pub type_params: Vec<String>,
204	pub params: Vec<(String, LangType<'model>)>,
205	pub result: LangType<'model>,
206	pub implementation: LangExprStmt<'model>,
207}
208
209pub struct MatchCase<'model> {
210	pub binding_name: String,
211	pub case_name: String,
212	pub body: LangStmt<'model>,
213}
214
215pub enum LangExprStmt<'model> {
216	Expr(LangExpr<'model>),
217	CreateCodec {
218		t: LangType<'model>,
219		read: Box<LangStmt<'model>>,
220		write: Box<LangStmt<'model>>,
221	},
222	CreateConverter {
223		from_type: LangType<'model>,
224		to_type: LangType<'model>,
225		body: Box<LangStmt<'model>>,
226	},
227}
228
229pub enum LangStmt<'model> {
230	Expr(Vec<LangExpr<'model>>, Option<LangExpr<'model>>),
231	MatchEnum {
232		value: LangExpr<'model>,
233		value_type: LangType<'model>,
234		cases: Vec<MatchCase<'model>>,
235	},
236	MatchDiscriminator {
237		value: LangExpr<'model>,
238		cases: Vec<(BigUint, LangStmt<'model>)>,
239	},
240}
241
242impl <'model> LangStmt<'model> {
243	pub fn has_value(&self) -> bool {
244		match self {
245			LangStmt::Expr(_, None) => false,
246			LangStmt::Expr(_, Some(_)) => true,
247			LangStmt::MatchEnum { cases, .. } => cases.iter().any(|MatchCase { body, .. }| body.has_value()),
248			LangStmt::MatchDiscriminator { cases, .. } => cases.iter().any(|(_, body)| body.has_value()),
249		}
250	}
251}
252
253pub enum ConvertParam<'model> {
254	ConverterObject,
255	Expression(LangExpr<'model>),
256}
257
258fn requires_conversion<'model, G: Generator<'model>>(gen: &G, t: &model::Type, prev_ver: &BigUint) -> bool {
259	match gen.scope().lookup(t.name.clone()) {
260		model::ScopeLookup::NamedType(name) => match gen.model().get_type(&name) {
261			Some(model::NamedTypeDefinition::StructType(type_def)) | Some(model::NamedTypeDefinition::EnumType(type_def)) => {
262				!type_def.is_final() ||
263					(match type_def.last_explicit_version() {
264						Some(last_ver) => last_ver > prev_ver,
265						None => true
266					}) ||
267					t.args.iter().any(|arg| requires_conversion(gen, arg, prev_ver))
268			},
269
270			Some(model::NamedTypeDefinition::ExternType(_)) => false,
271
272			None => true, // Error condition, assume conversion required. Should fail when determining the conversion.
273		},
274		model::ScopeLookup::TypeParameter(_) => true,
275	}
276}
277
278pub trait GeneratorNameMapping {
279	fn convert_prev_type_param(param: &str) -> String;
280	fn convert_current_type_param(param: &str) -> String;
281	fn convert_conv_param_name(param: &str) -> String;
282	fn convert_prev_param_name() -> &'static str;
283
284	fn codec_write_value_name() -> &'static str;
285	fn codec_codec_param_name(param: &str) -> String;
286	
287	fn constant_version_name(version: &BigUint) -> String;
288}
289
290
291fn build_type_impl<'model>(model: &'model model::Verilization, version: &BigUint, t: &model::Type, scope: &model::Scope<'model>, type_args: &HashMap<String, LangType<'model>>) -> Result<LangType<'model>, GeneratorError> {
292	let lang_args = t.args.iter()
293		.map(|arg| build_type_impl(model, version, arg, scope, type_args))
294		.collect::<Result<Vec<_>, _>>()?;
295
296	Ok(match scope.lookup(t.name.clone()) {
297		model::ScopeLookup::NamedType(name) => match model.get_type(&name).ok_or_else(|| GeneratorError::CouldNotFind(name.clone()))? {
298			model::NamedTypeDefinition::StructType(type_def) => {
299				let lang_args_map = type_def.type_params().clone().into_iter()
300					.zip(lang_args.clone().into_iter())
301					.collect::<HashMap<_, _>>();
302
303					let ver_type = type_def.versioned(version).ok_or_else(|| GeneratorError::CouldNotFindVersion(name, version.clone()))?;
304					let type_ver = ver_type.version.clone();
305
306				let fields = LangVerTypeFields {
307					model: model,
308					type_args: lang_args_map,
309					type_def: type_def,
310					ver_type: ver_type,
311				};
312
313				LangType::Versioned(VersionedTypeKind::Struct, type_def.name(), type_ver, lang_args, fields)
314			},
315
316			model::NamedTypeDefinition::EnumType(type_def) => {
317				let lang_args_map = type_def.type_params().clone().into_iter()
318					.zip(lang_args.clone().into_iter())
319					.collect::<HashMap<_, _>>();
320
321				let ver_type = type_def.versioned(version).ok_or_else(|| GeneratorError::CouldNotFindVersion(name, version.clone()))?;
322				let type_ver = ver_type.version.clone();
323
324				let fields = LangVerTypeFields {
325					model: model,
326					type_args: lang_args_map,
327					type_def: type_def,
328					ver_type: ver_type,
329				};
330
331				LangType::Versioned(VersionedTypeKind::Enum, type_def.name(), type_ver, lang_args, fields)
332			},
333
334			model::NamedTypeDefinition::ExternType(type_def) => {
335				let lang_args_map = type_def.type_params().clone().into_iter()
336					.zip(lang_args.clone().into_iter())
337					.collect::<HashMap<_, _>>();
338
339				let literals = LangExternTypeLiterals {
340					model: model,
341					type_args: lang_args_map,
342					type_def: type_def,
343				};
344
345				LangType::Extern(type_def.name(), lang_args, literals)
346			},
347		},
348		model::ScopeLookup::TypeParameter(name) => type_args.get(&name).ok_or_else(|| GeneratorError::CouldNotResolveTypeParameter(name))?.clone(),
349	})
350}
351
352fn constant_invoke_operation<'model>(op: Operation, values: Vec<LangExpr<'model>>, t: LangType<'model>) -> Result<LangExpr<'model>, GeneratorError> {
353	let (target, type_args) = match t {
354		LangType::Versioned(_, name, version, type_args, _) => (OperationTarget::VersionedType(name, version), type_args),
355		LangType::Extern(name, type_args, _) => (OperationTarget::ExternType(name), type_args),
356		LangType::TypeParameter(_) | LangType::Codec(_) | LangType::Converter(_, _) => return Err(GeneratorError::InvalidTypeForConstant),
357	};
358
359	Ok(LangExpr::InvokeOperation(op, target, type_args, values))
360}
361
362pub trait Generator<'model> : Sized {
363	type Lang: GeneratorNameMapping;
364
365	fn model(&self) -> &'model model::Verilization;
366	fn scope(&self) -> &model::Scope<'model>;
367
368
369	fn build_type<'gen>(&'gen self, version: &BigUint, t: &model::Type) -> Result<LangType<'model>, GeneratorError> {
370		let type_args = self.scope().type_params().into_iter().map(|param| (param.clone(), LangType::TypeParameter(param))).collect::<HashMap<_, _>>();
371
372		build_type_impl(self.model(), version, t, self.scope(), &type_args)
373	}
374
375	fn build_codec(&self, t: LangType<'model>) -> Result<LangExpr<'model>, GeneratorError> {
376		Ok(match t {
377			LangType::Versioned(_, name, version, args, _) => {
378				let codec_args = args.iter().map(|arg| self.build_codec(arg.clone())).collect::<Result<Vec<_>, _>>()?;
379
380				LangExpr::InvokeOperation(
381					Operation::TypeCodec,
382					OperationTarget::VersionedType(name, version),
383					args,
384					codec_args,
385				)
386			},
387
388			LangType::Extern(name, args, _) => {
389				let codec_args = args.iter().map(|arg| self.build_codec(arg.clone())).collect::<Result<Vec<_>, _>>()?;
390
391				LangExpr::InvokeOperation(
392					Operation::TypeCodec,
393					OperationTarget::ExternType(name),
394					args,
395					codec_args,
396				)
397			},
398
399			LangType::TypeParameter(name) => LangExpr::Identifier(Self::Lang::codec_codec_param_name(&name)),
400
401			LangType::Codec(_) | LangType::Converter(_, _) => return Err(GeneratorError::InvalidTypeForCodec),
402		})
403	}
404
405	fn build_conversion(&self, prev_ver: &BigUint, version: &BigUint, t: &model::Type, param: ConvertParam<'model>) -> Result<LangExpr<'model>, GeneratorError> {
406		if !requires_conversion(self, t, prev_ver) {
407			return Ok(match param {
408				ConvertParam::ConverterObject => LangExpr::IdentityConverter(self.build_type(version, t)?),
409				ConvertParam::Expression(expr) => expr,
410			})
411		}
412
413		let converter = match self.scope().lookup(t.name.clone()) {
414			model::ScopeLookup::NamedType(name) => {
415
416				let mut op_type_args = Vec::new();
417				let mut op_args = Vec::new();
418
419				for arg in &t.args {
420					op_type_args.push(self.build_type(prev_ver, arg)?);
421					op_type_args.push(self.build_type(version, arg)?);
422					op_args.push(self.build_conversion(prev_ver, version, arg, ConvertParam::ConverterObject)?);
423				}
424
425
426				let named_type_def = self.model().get_type(&name).ok_or_else(|| GeneratorError::CouldNotFind(name.clone()))?;
427				let operation;
428				let target;
429				match named_type_def {
430					model::NamedTypeDefinition::StructType(type_def) | model::NamedTypeDefinition::EnumType(type_def) => {
431						let ver_type = type_def.versioned(version).ok_or_else(|| GeneratorError::CouldNotFindVersion(name.clone(), version.clone()))?;
432
433						operation =
434							if ver_type.version < *version {
435								Operation::FinalTypeConverter
436							}
437							else {
438								Operation::FromPreviousVersion(prev_ver.clone())
439							};
440
441						target = OperationTarget::VersionedType(named_type_def.name(), ver_type.version.clone());
442					},
443
444					model::NamedTypeDefinition::ExternType(_) => {
445						operation = Operation::FinalTypeConverter;
446						target = OperationTarget::ExternType(named_type_def.name());
447					},
448				};
449
450				LangExpr::InvokeOperation(
451					operation,
452					target,
453					op_type_args,
454					op_args
455				)
456			},
457			model::ScopeLookup::TypeParameter(name) => LangExpr::Identifier(Self::Lang::convert_conv_param_name(&name)),
458		};
459
460					
461		Ok(match param {
462			ConvertParam::ConverterObject => converter,
463			ConvertParam::Expression(expr) => LangExpr::InvokeConverter {
464				converter: Box::new(converter),
465				value: Box::new(expr),
466			},
467		})
468	}
469
470	fn build_value(&self, version: &BigUint, t: LangType<'model>, value: model::ConstantValue) -> Result<LangExpr<'model>, GeneratorError> {
471		Ok(match value {
472			model::ConstantValue::Integer(n) => constant_invoke_operation(Operation::FromInteger, vec!(LangExpr::IntegerLiteral(n.clone())), t)?,
473			model::ConstantValue::String(s) => constant_invoke_operation(Operation::FromString, vec!(LangExpr::StringLiteral(s.clone())), t)?,
474			model::ConstantValue::Sequence(seq) => match t {
475				LangType::Extern(type_name, type_args, literals) => {
476					let literals = literals.build()?;
477
478					let element_type = literals
479						.into_iter()
480						.find_map(|literal| match literal {
481							LangLiteral::Sequence(element_type) => Some(element_type),
482							_ => None,
483						})
484						.ok_or_else(|| GeneratorError::TypeCannotBeSequence(type_name.clone()))?;
485
486					let args = seq.into_iter()
487						.map(|elem| self.build_value(version, element_type.clone(), elem))
488						.collect::<Result<Vec<_>, _>>()?;
489
490					LangExpr::InvokeOperation(
491						Operation::FromSequence,
492						OperationTarget::ExternType(type_name),
493						type_args,
494						args,
495					)
496				},
497				LangType::Versioned(_, type_name, ..) => return Err(GeneratorError::TypeCannotBeSequence(type_name.clone())),
498				LangType::TypeParameter(_) | LangType::Codec(_) | LangType::Converter(_, _) => return Err(GeneratorError::InvalidTypeForConstant),
499			},
500			
501			model::ConstantValue::Case(case_name, mut args) => match t {
502				LangType::Versioned(VersionedTypeKind::Enum, type_name, type_version, type_args, fields) if args.len() == 1 => {
503					let field = fields.build()?.into_iter().find(|field| *field.name == case_name).ok_or_else(|| GeneratorError::TypeDoesNotHaveCase(type_name.clone(), Some(type_version.clone()), case_name.clone()))?;
504					
505					let arg = self.build_value(version, field.field_type, args.remove(0))?;
506					LangExpr::CreateEnum(type_name, type_version, type_args, field.name, Box::new(arg))
507				},
508				LangType::Versioned(VersionedTypeKind::Enum, type_name, ..) => return Err(GeneratorError::IncorrectCaseArity(type_name.clone(), case_name.clone())),
509
510				LangType::Extern(type_name, type_args, literals) => {
511					let case_params = literals.build()?
512						.into_iter()
513						.find_map(|literal| match literal {
514							LangLiteral::Case(name, case_params) if name == *case_name => Some(case_params),
515							_ => None,
516						})
517						.ok_or_else(|| GeneratorError::TypeDoesNotHaveCase(type_name.clone(), None, case_name.clone()))?;
518
519					let args = args.into_iter().zip(case_params.into_iter())
520						.map(|(arg, param)| self.build_value(version, param, arg))
521						.collect::<Result<Vec<_>, _>>()?;
522
523					LangExpr::InvokeOperation(
524						Operation::FromCase(case_name.clone()),
525						OperationTarget::ExternType(type_name),
526						type_args,
527						args,
528					)
529				},
530
531				LangType::Versioned(VersionedTypeKind::Struct, ..) => return Err(GeneratorError::RecordLiteralNotForStruct),
532				LangType::TypeParameter(_) | LangType::Codec(_) | LangType::Converter(_, _) => return Err(GeneratorError::InvalidTypeForConstant),
533			},
534			
535			model::ConstantValue::Record(record) => match t {
536				LangType::Versioned(VersionedTypeKind::Struct, type_name, type_version, type_args, fields) => {
537					let mut lang_args = Vec::new();
538					let mut field_values = record.into_field_values();
539
540					for field in fields.build()? {
541						let value = field_values.remove(field.name).ok_or_else(|| GeneratorError::CouldNotFindRecordField(type_name.clone(), Some(type_version.clone()), field.name.clone()))?;
542						let value = self.build_value(version, field.field_type, value)?;
543						lang_args.push((field.name, value));
544					}
545
546					LangExpr::CreateStruct(type_name, type_version, type_args, lang_args)
547				},
548
549				LangType::Extern(type_name, type_args, literals) => {
550					let record_fields = literals.build()?
551						.into_iter()
552						.find_map(|literal| match literal {
553							LangLiteral::Record(fields) => Some(fields),
554							_ => None,
555						})
556						.ok_or_else(|| GeneratorError::ExternTypeDoesNotHaveRecordLiteral(type_name.clone()))?;
557
558					let mut field_values = record.into_field_values();
559					let mut field_names = Vec::new();
560					let mut args = Vec::new();
561
562					for field in record_fields {
563						let value = field_values.remove(field.name).ok_or_else(|| GeneratorError::CouldNotFindRecordField(type_name.clone(), None, field.name.clone()))?;
564						let value = self.build_value(version, field.field_type, value)?;
565						field_names.push(field.name.clone());
566						args.push(value);
567					}
568
569					LangExpr::InvokeOperation(
570						Operation::FromRecord(field_names),
571						OperationTarget::ExternType(type_name),
572						type_args,
573						args,
574					)
575				},
576
577				LangType::Versioned(VersionedTypeKind::Enum, ..) => return Err(GeneratorError::InvalidTypeForConstant),
578				LangType::TypeParameter(_) => return Err(GeneratorError::InvalidTypeForConstant),
579				LangType::Codec(_) | LangType::Converter(_, _) => return Err(GeneratorError::InvalidTypeForConstant),
580			},
581			model::ConstantValue::Constant(name) => {
582				match self.scope().lookup(name) {
583					model::ScopeLookup::NamedType(name) => {
584						let constant = self.model().get_constant(&name).ok_or_else(|| GeneratorError::CouldNotFind(name))?;
585
586						LangExpr::ConstantValue(constant.name(), version.clone())
587					},
588					model::ScopeLookup::TypeParameter(name) => return Err(GeneratorError::CouldNotFind(model::QualifiedName { package: model::PackageName::new(), name: name, }))
589				}
590				
591			},
592		})
593	}
594	
595}
596
597#[derive(Default)]
598pub struct GenConstant {}
599
600#[derive(Default)]
601pub struct GenType<GenTypeKind> {
602	type_gen: PhantomData<GenTypeKind>,
603}
604
605pub trait ConstGenerator<'model> : Generator<'model> {
606	fn constant(&self) -> Named<'model, model::Constant>;
607
608	fn write_header(&mut self) -> Result<(), GeneratorError>;
609	fn write_constant(&mut self, version_name: String, t: LangType<'model>, value: LangExpr<'model>) -> Result<(), GeneratorError>;
610	fn write_footer(&mut self) -> Result<(), GeneratorError>;
611
612
613	fn generate(&mut self) -> Result<(), GeneratorError> {
614		self.write_header()?;
615
616		for ver in self.constant().versions() {
617			let version_name = Self::Lang::constant_version_name(&ver.version);
618			let t = self.build_type(&ver.version, self.constant().value_type())?;
619			let value =
620				if let Some(value) = ver.value {
621					self.build_value(&ver.version, t.clone(), value.clone())?
622				}
623				else {
624					let prev_ver: BigInt = BigInt::from_biguint(Sign::Plus, ver.version.clone()) - 1;
625					let prev_ver = prev_ver.to_biguint().unwrap();
626					self.build_value_from_prev(&prev_ver, &ver.version, self.constant().value_type())?
627				};
628
629			self.write_constant(version_name, t, value)?;
630		}
631
632		self.write_footer()
633	}
634
635	fn build_value_from_prev(&self, prev_ver: &BigUint, version: &BigUint, t: &model::Type) -> Result<LangExpr<'model>, GeneratorError> {
636		self.build_conversion(prev_ver, version, t, ConvertParam::Expression(LangExpr::ConstantValue(self.constant().name(), prev_ver.clone())))
637	}
638
639
640
641}
642
643pub trait VersionedTypeGenerator<'model> : Generator<'model> {
644	fn type_def(&self) -> Named<'model, model::VersionedTypeDefinitionData>;
645
646	fn write_header(&mut self) -> Result<(), GeneratorError>;
647	fn write_version_header(&mut self, t: LangType<'model>) -> Result<(), GeneratorError>;
648	fn write_operation(&mut self, operation: OperationInfo<'model>) -> Result<(), GeneratorError>;
649	fn write_version_footer(&mut self) -> Result<(), GeneratorError>;
650	fn write_footer(&mut self) -> Result<(), GeneratorError>;
651
652
653	fn generate(&mut self) -> Result<(), GeneratorError> {
654		self.write_header()?;
655
656		let mut first_version = true;
657		
658		for ver_type in self.type_def().versions() {
659			let version = &ver_type.version;
660	
661			let prev_ver: BigInt = BigInt::from_biguint(Sign::Plus, version.clone()) - 1;
662			let prev_ver = prev_ver.to_biguint().unwrap();
663
664			let type_params_as_args = self.type_def().type_params().iter()
665				.map(|param| model::Type { name: model::QualifiedName::from_parts(&[], &param), args: vec!() })
666				.collect::<Vec<_>>();
667
668			let t = self.build_type(version, &model::Type { name: self.type_def().name().clone(), args: type_params_as_args.clone() })?;
669			let type_kind = match &t {
670				LangType::Versioned(kind, ..) => *kind,
671				_ => return Err(GeneratorError::CouldNotGenerateType),
672			};
673			self.write_version_header(t)?;
674
675			// Converter for latest version of final type with type parameters
676			if self.type_def().is_final() && !self.type_def().type_params().is_empty() && self.type_def().last_explicit_version() == Some(&ver_type.version) {
677				self.write_operation(build_converter_operation_common(self, Operation::FinalTypeConverter, type_kind, &ver_type, version)?)?;
678			}
679			
680			// Conversion from previous version
681			if !first_version { // Skip when there is no prevous version.
682				self.write_operation(build_converter_operation_common(self, Operation::FromPreviousVersion(prev_ver.clone()), type_kind, &ver_type, &prev_ver)?)?;
683			}
684
685			// Codec
686			{
687				let mut codec_params = Vec::new();
688
689				for param in self.type_def().type_params() {
690					let param_type = LangType::TypeParameter(param.clone());
691
692					codec_params.push((Self::Lang::codec_codec_param_name(param), LangType::Codec(Box::new(param_type.clone()))));
693				}
694
695				let obj_type = self.build_type(version, &model::Type { name: self.type_def().name().clone(), args: type_params_as_args })?;
696
697				let codec_type = LangType::Codec(Box::new(obj_type.clone()));
698
699				let op = OperationInfo {
700					operation: Operation::TypeCodec,
701					version: version.clone(),
702					type_params: self.type_def().type_params().clone(),
703					params: codec_params,
704					result: codec_type,
705					implementation: LangExprStmt::CreateCodec {
706						t: obj_type.clone(),
707						read: Box::new(codec_read_implementation(self, obj_type.clone())?),
708						write: Box::new(codec_write_implementation(self, obj_type)?),
709					},
710				};
711
712				self.write_operation(op)?;
713			}
714
715
716			self.write_version_footer()?;
717			first_version = false;
718		}
719
720		self.write_footer()
721	}
722}
723
724fn build_converter_operation_common<'model, Gen>(gen: &Gen, op: Operation, type_kind: VersionedTypeKind, ver_type: &model::TypeVersionInfo<'model>, prev_ver: &BigUint) -> Result<OperationInfo<'model>, GeneratorError> where
725	Gen : VersionedTypeGenerator<'model>
726{
727	let version = &ver_type.version;
728
729	let mut type_params_as_args = Vec::new();
730	let mut type_params = Vec::new();
731	let mut type_args = Vec::new();
732	let mut params = Vec::new();
733	let mut result_type_args = Vec::new();
734	let mut prev_type_args = HashMap::new();
735	let mut result_type_args_map = HashMap::new();
736	let mut impl_call_args = Vec::new();
737
738	for param in gen.type_def().type_params() {
739		type_params_as_args.push(model::Type { name: model::QualifiedName::from_parts(&[], &param), args: vec!() });
740		let t1 = Gen::Lang::convert_prev_type_param(&param);
741		let t2 = Gen::Lang::convert_current_type_param(&param);
742		type_params.push(t1.clone());
743		type_params.push(t2.clone());
744		let t1_arg = LangType::TypeParameter(t1.clone());
745		let t2_arg = LangType::TypeParameter(t2.clone());
746		type_args.push(t1_arg.clone());
747		type_args.push(t2_arg.clone());
748		result_type_args.push(t2_arg.clone());
749		prev_type_args.insert(param.clone(), t1_arg);
750		result_type_args_map.insert(param.clone(), t2_arg);
751
752		let conv_type = LangType::Converter(
753			Box::new(LangType::TypeParameter(t1)),
754			Box::new(LangType::TypeParameter(t2)),
755		);
756
757		let conv_param = Gen::Lang::convert_conv_param_name(param);
758		params.push((conv_param.clone(), conv_type));
759		impl_call_args.push(LangExpr::Identifier(conv_param));
760	}
761
762	let prev_type = build_type_impl(gen.model(), prev_ver, &model::Type { name: gen.type_def().name().clone(), args: type_params_as_args.clone() }, gen.scope(), &prev_type_args)?;
763	let result_type = build_type_impl(gen.model(), version, &model::Type { name: gen.type_def().name().clone(), args: type_params_as_args.clone() }, gen.scope(), &result_type_args_map)?;
764
765	let converter_type = LangType::Converter(Box::new(prev_type.clone()), Box::new(result_type.clone()));
766
767	let implementation = if ver_type.explicit_version && ver_type.version != *prev_ver {
768		LangExprStmt::Expr(LangExpr::InvokeUserConverter {
769			name: gen.type_def().name(),
770			prev_ver: prev_ver.clone(),
771			version: version.clone(),
772			type_args: type_args,
773			args: impl_call_args,
774		})
775	}
776	else {
777		let body = match type_kind {
778			VersionedTypeKind::Struct => {
779				let mut fields = Vec::new();
780		
781				for (field_name, field) in ver_type.ver_type.fields() {
782					let obj_value = LangExpr::Identifier(Gen::Lang::convert_prev_param_name().to_string());
783		
784					let value_expr = LangExpr::StructField(gen.type_def().name(), ver_type.version.clone(), field_name, Box::new(obj_value));
785					let conv_value = gen.build_conversion(prev_ver, &ver_type.version, &field.field_type, ConvertParam::Expression(value_expr))?;
786		
787					fields.push((field_name, conv_value));
788				}
789		
790				LangStmt::Expr(vec!(),
791					Some(LangExpr::CreateStruct(gen.type_def().name(), ver_type.version.clone(), result_type_args, fields))
792				)
793			},
794			VersionedTypeKind::Enum => {
795				let mut cases = Vec::new();
796		
797		
798				for (field_name, field) in ver_type.ver_type.fields() {
799		
800					let value_expr = LangExpr::Identifier(field_name.clone());
801					let conv_value = gen.build_conversion(prev_ver, &ver_type.version, &field.field_type, ConvertParam::Expression(value_expr))?;
802					let enum_value = LangExpr::CreateEnum(gen.type_def().name(), ver_type.version.clone(), result_type_args.clone(), field_name, Box::new(conv_value));
803		
804					cases.push(MatchCase {
805						binding_name: field_name.clone(),
806						case_name: field_name.clone(),
807						body: LangStmt::Expr(vec!(), Some(enum_value)),
808					});
809				}
810		
811				LangStmt::MatchEnum {
812					value: LangExpr::Identifier(Gen::Lang::convert_prev_param_name().to_string()),
813					value_type: build_type_impl(gen.model(), prev_ver, &model::Type { name: gen.type_def().name().clone(), args: type_params_as_args.clone() }, gen.scope(), &prev_type_args)?,
814					cases: cases,
815				}
816			},
817		};
818
819		LangExprStmt::CreateConverter {
820			from_type: prev_type,
821			to_type: result_type,
822			body: Box::new(body),
823		}
824	};
825
826	Ok(OperationInfo {
827		operation: op,
828		version: version.clone(),
829		type_params: type_params,
830		params: params,
831		result: converter_type,
832		implementation: implementation,
833	})
834}
835
836
837fn codec_read_implementation<'model, Gen>(gen: &Gen, t: LangType<'model>) -> Result<LangStmt<'model>, GeneratorError> where
838	Gen : VersionedTypeGenerator<'model>
839{
840	Ok(match t {
841		LangType::Versioned(VersionedTypeKind::Struct, _, version, type_args, fields) => {
842			let mut field_values = Vec::new();
843		
844			for field in fields.build()? {
845				let field_codec = gen.build_codec(field.field_type)?;
846				field_values.push((field.name, LangExpr::CodecRead { codec: Box::new(field_codec) }));
847			}
848		
849			LangStmt::Expr(vec!(),
850				Some(LangExpr::CreateStruct(gen.type_def().name(), version, type_args, field_values))
851			)
852		},
853
854		LangType::Versioned(VersionedTypeKind::Enum, _, version, type_args, fields) => {
855			let mut cases = Vec::new();
856	
857			for (index, field) in fields.build()?.into_iter().enumerate() {	
858				let codec = gen.build_codec(field.field_type)?;
859	
860				let body = LangStmt::Expr(vec!(),
861					Some(LangExpr::CreateEnum(
862						gen.type_def().name(),
863						version.clone(),
864						type_args.clone(),
865						field.name,
866						Box::new(LangExpr::CodecRead {
867							codec: Box::new(codec),
868						})
869					))
870				);
871	
872				cases.push((BigUint::from(index), body));
873			}
874	
875			LangStmt::MatchDiscriminator {
876				value: LangExpr::ReadDiscriminator,
877				cases: cases,
878			}
879		},
880
881		_ => return Err(GeneratorError::InvalidTypeForCodec),
882	})
883}
884
885fn codec_write_implementation<'model, Gen>(gen: &Gen, t: LangType<'model>) -> Result<LangStmt<'model>, GeneratorError> where
886	Gen : VersionedTypeGenerator<'model>
887{
888	Ok(match t.clone() {
889		LangType::Versioned(VersionedTypeKind::Struct, _, version, _, fields) => {
890			let mut field_values = Vec::new();
891	
892			for field in fields.build()? {
893				let obj_value = LangExpr::Identifier(Gen::Lang::codec_write_value_name().to_string());
894				let field_codec = gen.build_codec(field.field_type)?;
895				let value_expr = LangExpr::StructField(gen.type_def().name(), version.clone(), field.name, Box::new(obj_value));
896	
897				field_values.push(LangExpr::CodecWrite {
898					codec: Box::new(field_codec),
899					value: Box::new(value_expr),
900				});
901			}
902	
903			LangStmt::Expr(field_values, None)
904		},
905
906		LangType::Versioned(VersionedTypeKind::Enum, _, _, _, fields) => {
907			let mut cases = Vec::new();
908	
909			for (index, field) in fields.build()?.into_iter().enumerate() {
910				let value_expr = LangExpr::Identifier(field.name.clone());
911				let codec = gen.build_codec(field.field_type)?;
912	
913	
914				cases.push(MatchCase {
915					binding_name: field.name.clone(),
916					case_name: field.name.clone(),
917					body: LangStmt::Expr(vec!(
918						LangExpr::WriteDiscriminator(BigUint::from(index)),
919						LangExpr::CodecWrite {
920							codec: Box::new(codec),
921							value: Box::new(value_expr),
922						},
923					), None),
924				});
925			}
926	
927			LangStmt::MatchEnum {
928				value: LangExpr::Identifier(Gen::Lang::codec_write_value_name().to_string()),
929				value_type: t,
930				cases: cases,
931			}
932		},
933
934		_ => return Err(GeneratorError::InvalidTypeForCodec),
935	})
936}
937
938
939pub trait GeneratorWithFile {
940	type GeneratorFile : Write;
941	fn file(&mut self) -> &mut Self::GeneratorFile;
942}
943
944pub trait Indentation : GeneratorWithFile {
945    fn indentation_size(&mut self) -> &mut u32;
946
947    fn write_indent(&mut self) -> Result<(), GeneratorError> {
948        for _ in 0..*self.indentation_size() {
949            write!(self.file(), "\t")?;
950        }
951		Ok(())
952    }
953
954	fn indent_increase(&mut self) {
955		*self.indentation_size() += 1;
956	}
957
958	fn indent_decrease(&mut self) {
959		*self.indentation_size() -= 1;
960	}
961}