Try to compile self as an expression

Do not call this method directly, use v.expr instead

Property definitions

nitc :: abstract_compiler $ AExpr :: expr
	# Try to compile self as an expression
	# Do not call this method directly, use `v.expr` instead
	private fun expr(v: AbstractCompilerVisitor): nullable RuntimeVariable
	do
		v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED {class_name}:{location.to_s}\\n\");")
		var mtype = self.mtype
		if mtype == null then
			return null
		else
			var res = v.new_var(mtype)
			v.add("/* {res} = NOT YET {class_name} */")
			return res
		end
	end
src/compiler/abstract_compiler.nit:3722,2--3735,4

nitc :: abstract_compiler $ ABlockExpr :: expr
	redef fun expr(v)
	do
		var last = self.n_expr.last
		for e in self.n_expr do
			if e == last then break
			v.stmt(e)
		end
		return v.expr(last, null)
	end
src/compiler/abstract_compiler.nit:3750,2--3758,4

nitc :: abstract_compiler $ ASelfExpr :: expr
	redef fun expr(v) do return v.frame.arguments.first
src/compiler/abstract_compiler.nit:3805,2--52

nitc :: abstract_compiler $ AIfExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var cond = v.expr_bool(self.n_expr)
		v.add("if ({cond})\{")
		v.assign(res, v.expr(self.n_then.as(not null), null))
		v.add("\} else \{")
		v.assign(res, v.expr(self.n_else.as(not null), null))
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:3847,2--3857,4

nitc :: abstract_compiler $ AIfexprExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var cond = v.expr_bool(self.n_expr)
		v.add("if ({cond})\{")
		v.assign(res, v.expr(self.n_then, null))
		v.add("\} else \{")
		v.assign(res, v.expr(self.n_else, null))
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:3861,2--3871,4

nitc :: abstract_compiler $ AIntegerExpr :: expr
	redef fun expr(v) do
		if value isa Int then return v.int_instance(value.as(Int))
		if value isa Byte then return v.byte_instance(value.as(Byte))
		if value isa Int8 then return v.int8_instance(value.as(Int8))
		if value isa Int16 then return v.int16_instance(value.as(Int16))
		if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
		if value isa Int32 then return v.int32_instance(value.as(Int32))
		if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
		# Should never happen
		abort
	end
src/compiler/abstract_compiler.nit:4107,2--4117,4

nitc :: abstract_compiler $ AFloatExpr :: expr
	redef fun expr(v) do return v.float_instance(self.value.as(Float))
src/compiler/abstract_compiler.nit:4121,2--67

nitc :: abstract_compiler $ AArrayExpr :: expr
	redef fun expr(v)
	do
		var mtype = self.element_mtype.as(not null)
		var array = new Array[RuntimeVariable]
		var res = v.array_instance(array, mtype)

		var old_comprehension = v.frame.comprehension
		v.frame.comprehension = res
		for nexpr in self.n_exprs do
			v.stmt(nexpr)
		end
		v.frame.comprehension = old_comprehension

		return res
	end
src/compiler/abstract_compiler.nit:4134,2--4148,4

nitc :: abstract_compiler $ ANullExpr :: expr
	redef fun expr(v) do return v.null_instance
src/compiler/abstract_compiler.nit:4318,2--44

nitc :: abstract_compiler $ AParExpr :: expr
	redef fun expr(v) do return v.expr(self.n_expr, null)
src/compiler/abstract_compiler.nit:4358,2--54

nitc :: abstract_compiler $ AOnceExpr :: expr
	redef fun expr(v)
	do
		var mtype = self.mtype.as(not null)
		var name = v.get_name("varonce")
		var guard = v.get_name(name + "_guard")
		v.add_decl("static {mtype.ctype} {name};")
		v.add_decl("static int {guard};")
		var res = v.new_var(mtype)
		v.add("if (likely({guard})) \{")
		v.add("{res} = {name};")
		v.add("\} else \{")
		var i = v.expr(self.n_expr, mtype)
		v.add("{res} = {i};")
		v.add("{name} = {res};")
		v.add("{guard} = 1;")
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:4362,2--4379,4

nitc :: abstract_compiler $ ASendExpr :: expr
	redef fun expr(v)
	do
		var recv = v.expr(self.n_expr, null)
		if is_safe then
			v.add "if ({recv}!=NULL) \{"
		end
		var callsite = self.callsite.as(not null)
		if callsite.is_broken then return null
		var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
		var res = v.compile_callsite(callsite, args)
		if is_safe then
			if res != null then
				# `callsite.mpropdef` may reference a method whose
				# return type is a primitive type in C. If it is
				# the case, we must convert the primitive type to
				# a `val*` to support nullable assignment.
				# Autobox's job is to convert primitive type to
				# nullable type, eg from `Int` to `nullable `Int`.
				# The target type reside in `self.mtype`.
				var original_res = v.autobox(res, self.mtype.as(not null))

				# Here we must create a new_var in case the original
				# type is not nullable. We can't call `autobox` to
				# convert a complex type to its nullable version.
				# eg if we have a type `A`, calling autobox like
				# `autobox(A, nullable A)` will return `A` since
				# `A` and `nullable A` have the same primitive
				# type. The nullable qualifier is only used at
				# compile time to add appropriate null checks.
				res = v.new_var(self.mtype.as(not null))
				v.add("{res} = {original_res};")
				v.add("\} else \{")
				v.add("{res} = NULL;")
			end
			v.add("\}")
		end
		return res
	end
src/compiler/abstract_compiler.nit:4383,2--4420,4

nitc :: abstract_compiler $ ASuperExpr :: expr
	redef fun expr(v)
	do
		var frame = v.frame.as(not null)
		var recv = frame.arguments.first

		var callsite = self.callsite
		if callsite != null then
			if callsite.is_broken then return null
			var args

			if self.n_args.n_exprs.is_empty then
				# Add automatic arguments for the super init call
				args = [recv]
				for i in [0..callsite.msignature.arity[ do
					args.add(frame.arguments[i+1])
				end
			else
				args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
			end

			# Super init call
			var res = v.compile_callsite(callsite, args)
			return res
		end

		var mpropdef = self.mpropdef.as(not null)

		var args
		if self.n_args.n_exprs.is_empty then
			args = frame.arguments
		else
			args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
		end

		# Standard call-next-method
		return v.supercall(mpropdef, recv.mtype.as(MClassType), args)
	end
src/compiler/abstract_compiler.nit:4454,2--4490,4

nitc :: abstract_compiler $ ANewExpr :: expr
	redef fun expr(v)
	do
		var mtype = self.recvtype
		assert mtype != null

		if mtype.mclass.name == "NativeArray" then
			assert self.n_args.n_exprs.length == 1
			var l = v.expr(self.n_args.n_exprs.first, null)
			assert mtype isa MGenericType
			var elttype = mtype.arguments.first
			return v.native_array_instance(elttype, l)
		end

		var callsite = self.callsite
		if callsite == null then return v.init_instance_or_extern(mtype)
		if callsite.is_broken then return null

		var recv
		# new factories are badly implemented.
		# They assume a stub temporary receiver exists.
		# This temporary receiver is required because it
		# currently holds the method and the formal types.
		#
		# However, this object could be reused if the formal types are the same.
		# Therefore, the following code will `once` it in these case
		if callsite.mproperty.is_new and not mtype.need_anchor then
			var name = v.get_name("varoncenew")
			var guard = v.get_name(name + "_guard")
			v.add_decl("static {mtype.ctype} {name};")
			v.add_decl("static int {guard};")
			recv = v.new_var(mtype)
			v.add("if (likely({guard})) \{")
			v.add("{recv} = {name};")
			v.add("\} else \{")
			var i = v.init_instance_or_extern(mtype)
			v.add("{recv} = {i};")
			v.add("{name} = {recv};")
			v.add("{guard} = 1;")
			v.add("\}")
		else
			recv = v.init_instance_or_extern(mtype)
		end

		var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
		var res2 = v.compile_callsite(callsite, args)
		if res2 != null then
			#self.debug("got {res2} from {mproperty}. drop {recv}")
			return res2
		end
		return recv
	end
src/compiler/abstract_compiler.nit:4494,2--4544,4

nitc :: abstract_compiler $ AVarargExpr :: expr
	redef fun expr(v)
	do
		return v.expr(self.n_expr, null)
	end
src/compiler/abstract_compiler.nit:4590,2--4593,4

nitc :: abstract_compiler $ ASafeExpr :: expr
	redef fun expr(v)
	do
		return v.expr(self.n_expr, null)
	end
src/compiler/abstract_compiler.nit:4597,2--4600,4

nitc :: abstract_compiler $ ANamedargExpr :: expr
	redef fun expr(v)
	do
		return v.expr(self.n_expr, null)
	end
src/compiler/abstract_compiler.nit:4604,2--4607,4

nitc :: abstract_compiler $ AVarExpr :: expr
	redef fun expr(v)
	do
		var res = v.variable(self.variable.as(not null))
		var mtype = self.mtype.as(not null)
		return v.autoadapt(res, mtype)
	end
src/compiler/abstract_compiler.nit:3774,2--3779,4

nitc :: abstract_compiler $ AImplicitSelfExpr :: expr
	redef fun expr(v) do
		if not is_sys then return super
		return v.new_expr("glob_sys", mtype.as(not null))
	end
src/compiler/abstract_compiler.nit:3809,2--3812,4

nitc :: abstract_compiler $ ANotExpr :: expr
	redef fun expr(v)
	do
		var cond = v.expr_bool(self.n_expr)
		return v.new_expr("!{cond}", self.mtype.as(not null))
	end
src/compiler/abstract_compiler.nit:4081,2--4085,4

nitc :: abstract_compiler $ ACharExpr :: expr
	redef fun expr(v) do
		if is_code_point then
			return v.int_instance(value.as(not null).code_point)
		end
		return v.char_instance(self.value.as(not null))
	end
src/compiler/abstract_compiler.nit:4125,2--4130,4

nitc :: abstract_compiler $ ACrangeExpr :: expr
	redef fun expr(v)
	do
		var i1 = v.expr(self.n_expr, null)
		var i2 = v.expr(self.n_expr2, null)
		var mtype = self.mtype.as(MClassType)
		var res = v.init_instance(mtype)
		v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
		return res
	end
src/compiler/abstract_compiler.nit:4286,2--4294,4

nitc :: abstract_compiler $ AOrangeExpr :: expr
	redef fun expr(v)
	do
		var i1 = v.expr(self.n_expr, null)
		var i2 = v.expr(self.n_expr2, null)
		var mtype = self.mtype.as(MClassType)
		var res = v.init_instance(mtype)
		v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
		return res
	end
src/compiler/abstract_compiler.nit:4298,2--4306,4

nitc :: abstract_compiler $ ATrueExpr :: expr
	redef fun expr(v) do return v.bool_instance(true)
src/compiler/abstract_compiler.nit:4310,2--50

nitc :: abstract_compiler $ AFalseExpr :: expr
	redef fun expr(v) do return v.bool_instance(false)
src/compiler/abstract_compiler.nit:4314,2--51

nitc :: abstract_compiler $ AIsaExpr :: expr
	redef fun expr(v)
	do
		var i = v.expr(self.n_expr, null)
		var cast_type = self.cast_type
		if cast_type == null then return null # no-no on broken node
		return v.type_test(i, cast_type, "isa")
	end
src/compiler/abstract_compiler.nit:4322,2--4328,4

nitc :: abstract_compiler $ AAsCastExpr :: expr
	redef fun expr(v)
	do
		var i = v.expr(self.n_expr, null)
		if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i

		v.add_cast(i, self.mtype.as(not null), "as")
		return i
	end
src/compiler/abstract_compiler.nit:4332,2--4339,4

nitc :: abstract_compiler $ AAsNotnullExpr :: expr
	redef fun expr(v)
	do
		var i = v.expr(self.n_expr, null)
		if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i

		if not v.maybe_null(i) then return i

		v.add("if (unlikely({i} == NULL)) \{")
		v.add_abort("Cast failed")
		v.add("\}")
		return i
	end
src/compiler/abstract_compiler.nit:4343,2--4354,4

nitc :: abstract_compiler $ AAttrExpr :: expr
	redef fun expr(v)
	do
		var recv = v.expr(self.n_expr, null)
		var mproperty = self.mproperty.as(not null)
		return v.read_attribute(mproperty, recv)
	end
src/compiler/abstract_compiler.nit:4548,2--4553,4

nitc :: abstract_compiler $ AIssetAttrExpr :: expr
	redef fun expr(v)
	do
		var recv = v.expr(self.n_expr, null)
		var mproperty = self.mproperty.as(not null)
		return v.isset_attribute(mproperty, recv)
	end
src/compiler/abstract_compiler.nit:4581,2--4586,4

nitc :: abstract_compiler $ AVarAssignExpr :: expr
	redef fun expr(v)
	do
		var variable = self.variable.as(not null)
		var i = v.expr(self.n_value, variable.declared_type)
		v.assign(v.variable(variable), i)
		return i
	end
src/compiler/abstract_compiler.nit:3783,2--3789,4

nitc :: abstract_compiler $ AOrElseExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var i1 = v.expr(self.n_expr, null)

		if not v.maybe_null(i1) then return i1

		v.add("if ({i1}!=NULL) \{")
		v.assign(res, i1)
		v.add("\} else \{")
		var i2 = v.expr(self.n_expr2, null)
		v.assign(res, i2)
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:4089,2--4103,4

nitc :: abstract_compiler $ AStringFormExpr :: expr
	redef fun expr(v) do return v.string_instance(value)
src/compiler/abstract_compiler.nit:4189,2--53

nitc :: abstract_compiler $ ASuperstringExpr :: expr
	redef fun expr(v)
	do
		var type_string = v.mmodule.string_type

		# Collect elements of the superstring
		var array = new Array[AExpr]
		for ne in self.n_exprs do
			# Drop literal empty string.
			# They appears in things like "{a}" that is ["", a, ""]
			if ne isa AStringFormExpr and ne.value == "" then continue # skip empty sub-strings
			array.add(ne)
		end

		# Store the allocated native array in a static variable
		# For reusing later
		var varonce = v.get_name("varonce")
		v.add("if (unlikely({varonce}==NULL)) \{")

		# The native array that will contains the elements to_s-ized.
		# For fast concatenation.
		var a = v.native_array_instance(type_string, v.int_instance(array.length))

		v.add_decl("static {a.mtype.ctype} {varonce};")

		# Pre-fill the array with the literal string parts.
		# So they do not need to be filled again when reused
		for i in [0..array.length[ do
			var ne = array[i]
			if not ne isa AStringFormExpr then continue
			var e = v.expr(ne, null)
			v.native_array_set(a, i, e)
		end

		v.add("\} else \{")
		# Take the native-array from the store.
		# The point is to prevent that some recursive execution use (and corrupt) the same native array
		# WARNING: not thread safe! (FIXME?)
		v.add("{a} = {varonce};")
		v.add("{varonce} = NULL;")
		v.add("\}")

		# Stringify the elements and put them in the native array
		var to_s_method = v.get_property("to_s", v.object_type)
		for i in [0..array.length[ do
			var ne = array[i]
			if ne isa AStringFormExpr then continue
			var e = v.expr(ne, null)
			# Skip the `to_s` if the element is already a String
			if not e.mcasttype.is_subtype(v.compiler.mainmodule, null, type_string) then
				e = v.send(to_s_method, [e]).as(not null)
			end
			v.native_array_set(a, i, e)
		end

		# Fast join the C string to get the result
		var res = v.send(v.get_property("native_to_s", a.mtype), [a])
		assert res != null

		if is_re then res = make_re(v, res)

		# We finish to work with the native array,
		# so store it so that it can be reused
		v.add("{varonce} = {a};")

		return res
	end
src/compiler/abstract_compiler.nit:4217,2--4282,4

nitc :: abstract_compiler $ ACallrefExpr :: expr
	redef fun expr(v)
	do
		var recv = v.expr(self.n_expr, null)
		var res = v.routine_ref_instance(mtype.as(MClassType), recv, callsite.as(not null))
		return res
	end
src/compiler/abstract_compiler.nit:4424,2--4429,4

nitc :: abstract_compiler $ AAttrAssignExpr :: expr
	redef fun expr(v)
	do
		var recv = v.expr(self.n_expr, null)
		var i = v.expr(self.n_value, null)
		var mproperty = self.mproperty.as(not null)
		v.write_attribute(mproperty, recv, i)
		return i
	end
src/compiler/abstract_compiler.nit:4557,2--4564,4

nitc :: abstract_compiler $ AOrExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var i1 = v.expr_bool(self.n_expr)
		v.add("if ({i1}) \{")
		v.add("{res} = 1;")
		v.add("\} else \{")
		var i2 = v.expr_bool(self.n_expr2)
		v.add("{res} = {i2};")
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:4036,2--4047,4

nitc :: abstract_compiler $ AImpliesExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var i1 = v.expr_bool(self.n_expr)
		v.add("if (!{i1}) \{")
		v.add("{res} = 1;")
		v.add("\} else \{")
		var i2 = v.expr_bool(self.n_expr2)
		v.add("{res} = {i2};")
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:4051,2--4062,4

nitc :: abstract_compiler $ AAndExpr :: expr
	redef fun expr(v)
	do
		var res = v.new_var(self.mtype.as(not null))
		var i1 = v.expr_bool(self.n_expr)
		v.add("if (!{i1}) \{")
		v.add("{res} = 0;")
		v.add("\} else \{")
		var i2 = v.expr_bool(self.n_expr2)
		v.add("{res} = {i2};")
		v.add("\}")
		return res
	end
src/compiler/abstract_compiler.nit:4066,2--4077,4

nitc :: abstract_compiler $ AStringExpr :: expr
	redef fun expr(v) do
		var s = v.string_instance(value)
		if is_string then return s
		if is_bytestring then
			var ns = v.c_string_instance(bytes.items, bytes.length)
			var ln = v.int_instance(bytes.length)
			var cs = to_bytes_with_copy
			assert cs != null
			var res = v.compile_callsite(cs, [ns, ln])
			assert res != null
			s = res
		else if is_re then
			var res = make_re(v, s)
			assert res != null
			s = res
		else
			print "Unimplemented prefix or suffix for {self}"
			abort
		end
		return s
	end
src/compiler/abstract_compiler.nit:4193,2--4213,4