Phase generating methods (code) to serialize Nit objects

Introduced classes

Redefined classes

redef class ToolContext

nitc :: serialization_code_gen_phase $ ToolContext

Global context for tools
package_diagram nitc::serialization_code_gen_phase serialization_code_gen_phase nitc::serialization_model_phase serialization_model_phase nitc::serialization_code_gen_phase->nitc::serialization_model_phase nitc::parser_util parser_util nitc::serialization_model_phase->nitc::parser_util nitc\>modelize\> modelize nitc::serialization_model_phase->nitc\>modelize\> ...nitc::parser_util ... ...nitc::parser_util->nitc::parser_util ...nitc\>modelize\> ... ...nitc\>modelize\>->nitc\>modelize\> nitc::code_gen code_gen nitc::code_gen->nitc::serialization_code_gen_phase nitc::nit nit nitc::nit->nitc::code_gen nitc::nitc nitc nitc::nitc->nitc::code_gen nitc::nitmetrics nitmetrics nitc::nitmetrics->nitc::code_gen nitc::nitvm nitvm nitc::nitvm->nitc::code_gen nitc::nit... ... nitc::nit...->nitc::nit nitc::nitc... ... nitc::nitc...->nitc::nitc nitc::nitmetrics... ... nitc::nitmetrics...->nitc::nitmetrics nitc::nitvm... ... nitc::nitvm...->nitc::nitvm

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module annotation

nitc :: annotation

Management and utilities on annotations
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module console

console :: console

Defines some ANSI Terminal Control Escape Sequences.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module digraph

graph :: digraph

Implementation of directed graphs, also called digraphs.
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module ini

ini :: ini

Read and write INI configuration files
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module lexer

nitc :: lexer

Lexer and its tokens.
module lexer_work

nitc :: lexer_work

Internal algorithm and data structures for the Nit lexer
module list

core :: list

This module handle double linked lists
module literal

nitc :: literal

Parsing of literal values in the abstract syntax tree.
module loader

nitc :: loader

Loading of Nit source files
module location

nitc :: location

Nit source-file and locations in source-file
module math

core :: math

Mathematical operations
module mdoc

nitc :: mdoc

Documentation of model entities
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module mmodule

nitc :: mmodule

modules and module hierarchies in the metamodel
module mmodule_data

nitc :: mmodule_data

Define and retrieve data in modules
module model

nitc :: model

Classes, types and properties
module model_base

nitc :: model_base

The abstract concept of model and related common things
module modelbuilder_base

nitc :: modelbuilder_base

Load nit source files and build the associated model
module modelize

nitc :: modelize

Create a model from nit source files
module modelize_class

nitc :: modelize_class

Analysis and verification of class definitions to instantiate model element
module modelize_property

nitc :: modelize_property

Analysis and verification of property definitions to instantiate model element
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module mpackage

nitc :: mpackage

Modelisation of a Nit package
module native

core :: native

Native structures for text and bytes
module nitpm_shared

nitc :: nitpm_shared

Services related to the Nit package manager
module numeric

core :: numeric

Advanced services for Numeric types
module opts

opts :: opts

Management of options on the command line
module ordered_tree

ordered_tree :: ordered_tree

Manipulation and presentation of ordered trees.
module parser

nitc :: parser

Parser.
module parser_nodes

nitc :: parser_nodes

AST nodes of the Nit language
module parser_prod

nitc :: parser_prod

Production AST nodes full definition.
module parser_util

nitc :: parser_util

Utils and tools related to parsers and AST
module parser_work

nitc :: parser_work

Internal algorithm and data structures for the Nit parser
module phase

nitc :: phase

Phases of the processing of nit programs
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module tables

nitc :: tables

Module that interfaces the parsing tables.
module template

template :: template

Basic template system
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module toolcontext

nitc :: toolcontext

Common command-line tool infrastructure than handle options and error messages
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O
module version

nitc :: version

This file was generated by git-gen-version.sh

Parents

module serialization_model_phase

nitc :: serialization_model_phase

Phase generating methods (model-only) to serialize Nit objects

Children

module code_gen

nitc :: code_gen

Main frontend phases plus code generation phases

Descendants

module a_star-m

a_star-m

module nit

nitc :: nit

A naive Nit interpreter
module nitc

nitc :: nitc

A Nit compiler
module nitmetrics

nitc :: nitmetrics

A program that collects various metrics on nit programs and libraries
module nitvm

nitc :: nitvm

The Nit virtual machine launcher
module test_astbuilder

nitc :: test_astbuilder

Program used to test the clone method of the astbuilder tool
# Phase generating methods (code) to serialize Nit objects
module serialization_code_gen_phase

intrude import serialization_model_phase

redef class ToolContext

	# The second phase of the serialization
	var serialization_phase_post_model: Phase = new SerializationPhasePostModel(self,
		[modelize_property_phase, serialization_phase_pre_model])
end

private class SerializationPhasePostModel
	super Phase

	# Fill the deserialization init `from_deserializer` and `Deserializer.deserialize_class_intern`
	redef fun process_nmodule(nmodule)
	do
		for npropdef in nmodule.inits_to_retype do
			var nclassdef = npropdef.parent
			assert nclassdef isa AStdClassdef

			var serialize_by_default = nclassdef.how_serialize
			assert serialize_by_default != null

			var per_attribute = not serialize_by_default
			fill_deserialization_init(nclassdef, npropdef, per_attribute)
		end

		# collect all classes
		var auto_serializable_nclassdefs = nmodule.auto_serializable_nclassdefs
		if not auto_serializable_nclassdefs.is_empty then
			fill_deserialization_method(nmodule, auto_serializable_nclassdefs)
		end
	end

	# Fill the constructor to the generated `init_npropdef` of `nclassdef`
	fun fill_deserialization_init(nclassdef: AClassdef, init_npropdef: AMethPropdef, per_attribute: Bool)
	do
		var code = new Array[String]
		code.add """
redef init from_deserializer(v)
do
	super
	v.notify_of_creation self
"""

		for attribute in nclassdef.n_propdefs do
			if not attribute isa AAttrPropdef then continue

			# Is `attribute` to be skipped?
			if (per_attribute and not attribute.is_serialize) or
				attribute.is_noserialize then continue

			var mtype = attribute.mtype
			if mtype == null then continue
			var type_name = mtype.to_s
			var name = attribute.name

			if mtype.need_anchor then
				# Check dynamic type of virtual params
				code.add """
	var {{{name}}} = v.deserialize_attribute("{{{attribute.serialize_name}}}", (new GetName[{{{mtype}}}]).to_s)
"""
			else
				# No param to check
				code.add """
	var {{{name}}} = v.deserialize_attribute("{{{attribute.serialize_name}}}", "{{{type_name}}}")
"""
			end

			if type_name == "nullable Object" then
				# Don't type check
				code.add """
	self.{{{name}}} = {{{name}}}
"""
			else
				# Needs type check
				code.add """
	if v.deserialize_attribute_missing then
"""
				# What to do when an attribute is missing?
				if attribute.has_value then
					# Leave it to the default value
				else if mtype isa MNullableType then
					# This is always a nullable type
					code.add """
		self.{{{name}}} = null"""
				else if mtype isa MFormalType then
					# This type nullability may change in subclasses
					code.add """
		var n___{{{name}}} = null
		if n___{{{name}}} isa {{{mtype}}} then
			self.{{{name}}} = n___{{{name}}}
		else
			v.errors.add new AttributeMissingError(self, "{{{name}}}")
		end"""
				else code.add """
		v.errors.add new AttributeMissingError(self, "{{{name}}}")"""

				code.add """
	else if not {{{name}}} isa {{{type_name}}} then
		v.errors.add new AttributeTypeError(self, "{{{attribute.serialize_name}}}", {{{name}}}, "{{{type_name}}}")
		if v.keep_going == false then return
	else
		self.{{{name}}} = {{{name}}}
	end
"""
			end
		end

		code.add "end"

		# Replace the body of the constructor
		var npropdef = toolcontext.parse_propdef(code.join("\n")).as(AMethPropdef)
		init_npropdef.n_block = npropdef.n_block

		# Run the literal phase on the generated code
		var v = new LiteralVisitor(toolcontext)
		v.enter_visit(npropdef.n_block)
	end

	# Fill the abstract serialization service
	fun fill_deserialization_method(nmodule: AModule, nclassdefs: Array[AStdClassdef])
	do
		var deserializer_nclassdef = nmodule.deserializer_nclassdef
		if deserializer_nclassdef == null then return
		var deserializer_npropdef = deserializer_nclassdef.deserializer_npropdef
		if deserializer_npropdef == null then return

		# Collect local types expected to be deserialized
		#
		# Map types' `name` to their `full_name`.
		#
		# FIXME use only the full name when there's a `class_full_name`
		var types_to_deserialize = new Map[String, String]

		## Local serializable standard class without parameters
		for nclassdef in nclassdefs do
			var mclass = nclassdef.mclass
			if mclass == null then continue

			if mclass.arity == 0 and mclass.kind == concrete_kind then
				types_to_deserialize[mclass.name] = mclass.full_name
			end
		end

		## Static parametized types on serializable attributes
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef then continue

			for attribute in nclassdef.n_propdefs do
				if not attribute isa AAttrPropdef then continue

				var serialize_by_default = nclassdef.how_serialize
				if serialize_by_default == null then continue
				var per_attribute = not serialize_by_default

				# Is `attribute` to be skipped?
				if (per_attribute and not attribute.is_serialize) or
					attribute.is_noserialize then continue

				var mtype = attribute.mtype
				if mtype == null then continue
				if mtype isa MNullableType then mtype = mtype.mtype

				if mtype isa MClassType and mtype.mclass.arity > 0 and
				   mtype.mclass.kind == concrete_kind and not mtype.need_anchor then

					# Check is a `Serializable`
					var mmodule = nmodule.mmodule
					if mmodule == null then continue

					var greaters = mtype.mclass.in_hierarchy(mmodule).greaters
					var is_serializable = false
					for sup in greaters do if sup.name == "Serializable" then
						is_serializable = true
						break
					end

					if is_serializable then types_to_deserialize[mtype.name] = mtype.full_name
				end
			end
		end

		# Build implementation code
		var code = new Array[String]
		code.add "redef fun deserialize_class_intern(name)"
		code.add "do"

		for name, full_name in types_to_deserialize do

			if full_name.has('-') then
				# Invalid module name, it is either artificial or a script
				# without module declaration (like those generated by nitunit)
				full_name = name
			end

			code.add "	if name == \"{name}\" then return new {full_name}.from_deserializer(self)"
		end

		code.add "	return super"
		code.add "end"

		# Replace the body of the constructor
		var npropdef = toolcontext.parse_propdef(code.join("\n")).as(AMethPropdef)
		deserializer_npropdef.n_block = npropdef.n_block

		# Run the literal phase on the generated code
		var v = new LiteralVisitor(toolcontext)
		v.enter_visit(npropdef.n_block)
	end
end
src/frontend/serialization_code_gen_phase.nit:15,1--227,3