<commit_before># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Thansformations that simplify the AST of expressions
# This module transform complex AST `AExpr` nodes into simplier ones
module transform

import astbuilder
import astvalidation
import semantize
intrude import semantize::scope

redef class ToolContext
	var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])

	# --no-shortcut-range
	var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range")

	redef init
	do
		super
		self.option_context.add_option(self.opt_no_shortcut_range)
	end
end

private class TransformPhase
	super Phase

	redef fun process_npropdef(npropdef: APropdef)
	do
		var val

		var m = npropdef.mpropdef
		if m == null then return
		var v = new TransformVisitor(self, m)
		v.enter_visit(npropdef)

		val = new ASTValidationVisitor
		val.enter_visit(npropdef)
	end
end

private class TransformVisitor
	super Visitor

	var phase: TransformPhase
	var mmodule: MModule is noinit
	var mclassdef: MClassDef is noinit
	var mpropdef: MPropDef
	var builder: ASTBuilder is noinit

	init
	do
		self.mclassdef = mpropdef.mclassdef
		self.mmodule = mclassdef.mmodule
		self.builder = new ASTBuilder(mmodule, mpropdef.mclassdef.bound_mtype)
	end

	redef fun visit(node)
	do
		if node isa AAnnotations then return
		node.full_transform_visitor(self)
	end

	# Get a primitive method or display a fatal error on `location`.
	fun get_method(location: AExpr, name: String, recv: MClass): MMethod
	do
		return phase.toolcontext.modelbuilder.force_get_primitive_method(location, name, recv, mmodule)
	end
end

redef class ANode
	private fun full_transform_visitor(v: TransformVisitor)
	do
		visit_all(v)
		accept_transform_visitor(v)
	end
	private fun accept_transform_visitor(v: TransformVisitor)
	do
	end
end

redef class AExpr
	redef fun full_transform_visitor(v: TransformVisitor)
	do
		var na = comprehension
		if na != null then
			# We are building a comprehension array `array`
			# Replace `self` with `array.push(self)`
			var place = detach_with_placeholder
			var recv = na.nnew.make_var_read
			var nadd = v.builder.make_call(recv, na.push_callsite.as(not null), [self])
			place.replace_with(nadd)
		end
		super
	end
end

redef class AVardeclExpr
	# `var x = y` is replaced with `x = y`
	#
	# Declarations are only useful for scope rules
	# Once names are associated with real objects, ther declaration become useless
	# Therefore, if there is no initial value, then just ignore it
	# Else, replace it with a simple assignment
	redef fun accept_transform_visitor(v)
	do
		var nexpr = n_expr
		if nexpr == null then
			# do nothing
			# note: not detached because the collection is currently under iteration<commit_msg>transform: do not lose autocast information<commit_after># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Thansformations that simplify the AST of expressions
# This module transform complex AST `AExpr` nodes into simplier ones
module transform

import astbuilder
import astvalidation
import semantize
intrude import semantize::scope
intrude import semantize::typing

redef class ToolContext
	var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])

	# --no-shortcut-range
	var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range")

	redef init
	do
		super
		self.option_context.add_option(self.opt_no_shortcut_range)
	end
end

private class TransformPhase
	super Phase

	redef fun process_npropdef(npropdef: APropdef)
	do
		var val

		var m = npropdef.mpropdef
		if m == null then return
		var v = new TransformVisitor(self, m)
		v.enter_visit(npropdef)

		val = new ASTValidationVisitor
		val.enter_visit(npropdef)
	end
end

private class TransformVisitor
	super Visitor

	var phase: TransformPhase
	var mmodule: MModule is noinit
	var mclassdef: MClassDef is noinit
	var mpropdef: MPropDef
	var builder: ASTBuilder is noinit

	init
	do
		self.mclassdef = mpropdef.mclassdef
		self.mmodule = mclassdef.mmodule
		self.builder = new ASTBuilder(mmodule, mpropdef.mclassdef.bound_mtype)
	end

	redef fun visit(node)
	do
		if node isa AAnnotations then return
		node.full_transform_visitor(self)
	end

	# Get a primitive method or display a fatal error on `location`.
	fun get_method(location: AExpr, name: String, recv: MClass): MMethod
	do
		return phase.toolcontext.modelbuilder.force_get_primitive_method(location, name, recv, mmodule)
	end
end

redef class ANode
	private fun full_transform_visitor(v: TransformVisitor)
	do
		visit_all(v)
		accept_transform_visitor(v)
	end
	private fun accept_transform_visitor(v: TransformVisitor)
	do
	end
end

redef class AExpr
	redef fun full_transform_visitor(v: TransformVisitor)
	do
		var na = comprehension
		if na != null then
			# We are building a comprehension array `array`
			# Replace `self` with `array.push(self)`
			var place = detach_with_placeholder
			var recv = na.nnew.make_var_read
			var nadd = v.builder.make_call(recv, na.push_callsite.as(not null), [self])
			place.replace_with(nadd)
		end
		super
	end

	redef fun replace_with(other)
	do
		super
		if other isa AExpr then
			if other.implicit_cast_to == null then other.implicit_cast_to = implicit_cast_to
		end
	end
end

redef class AVardeclExpr
	# `var x = y` is replaced with `x = y`
	#
	# Declarations are only useful for scope rules
	# Once names are associated with real objects, ther declaration become useless
	# Therefore, if there is no initial value, then just ignore it
	# Else, replace it with a simple assignment
	redef fun accept_transform_visitor(v)
	do
		var nexpr = n_expr
		if nexpr == null then
			# do nothing
			# note: not detached because the collection is currently under iteration
{'fraction_non_alphanumeric': 0.0642754662840746, 'fraction_numerical': 0.0011477761836441894, 'mean_word_length': 4.463166144200627, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3577941', 'n_tokens_mistral': 2313, 'n_tokens_neox': 2167, 'n_words': 797}