<commit_before>package org.xtuml.bp.xtext.masl.typesystem

import java.util.List
import java.util.Map
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.Data
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.xtuml.bp.xtext.masl.masl.structure.ObjectDeclaration
import org.xtuml.bp.xtext.masl.masl.structure.TerminatorDefinition
import org.xtuml.bp.xtext.masl.masl.types.EnumerationTypeDefinition
import org.xtuml.bp.xtext.masl.masl.types.StructureTypeDefinition
import org.xtuml.bp.xtext.masl.masl.types.TypeDeclaration

/**
 * Dealing with EMF objects is tedious, so we define our own types
 */
interface MaslType {

	def MaslType getPrimitiveType()

	def boolean isAnonymous()
	
	def MaslType getComponentType()
	
	def MaslType stripName()
	
	def String toString(Map<MaslType, String> seenTypes)
}

@FinalFieldsConstructor
@Accessors(PUBLIC_GETTER)
abstract class AbstractMaslType implements MaslType {

	transient val boolean anonymous

	new() {
		anonymous = false
	}

	override MaslType getComponentType() {
		this
	}
	
	protected def prefix() {
		(if (anonymous) 'anonymous ' else '') 
	}
	
	override stripName() {
		this
	}
	
	override toString() {
		toStringRecursionSafe
	}
	
	protected def toStringRecursionSafe() {
		toString(newHashMap)
	}
	
	override String toString(Map<MaslType, String> seenTypes) {
		val seenName = seenTypes.get(this)
		if(seenName !== null)
			return seenName
		else
			return toStringInternal(seenTypes)
	}
	
	protected def String toStringInternal(Map<MaslType, String> map)
	
}

@Data
@FinalFieldsConstructor
class BuiltinType extends AbstractMaslType {
	val String name

	public static val CHARACTER = new BuiltinType('character')
	public static val STRING = new BuiltinType('string')
	public static val BOOLEAN = new BuiltinType('boolean')
	public static val BYTE = new BuiltinType('byte')
	public static val INTEGER = new BuiltinType('integer')
	public static val LONG_INTEGER = new BuiltinType('long_integer')
	public static val REAL = new BuiltinType('real')
	public static val DEVICE = new BuiltinType('device')
	public static val DURATION = new BuiltinType('duration')
	public static val TIMESTAMP = new BuiltinType('timestamp')
	public static val TIMER = new BuiltinType('timer')

	public static val ANONYMOUS_CHARACTER = new BuiltinType('character', true)
	public static val ANONYMOUS_STRING = new BuiltinType('string', true)
	public static val ANONYMOUS_BOOLEAN = new BuiltinType('boolean', true)
	public static val ANONYMOUS_BYTE = new BuiltinType('byte', true)
	public static val ANONYMOUS_INTEGER = new BuiltinType('integer', true)
	public static val ANONYMOUS_LONG_INTEGER = new BuiltinType('long_integer', true)
	public static val ANONYMOUS_REAL = new BuiltinType('real', true)
	public static val ANONYMOUS_DEVICE = new BuiltinType('device', true)
	public static val ANONYMOUS_DURATION = new BuiltinType('duration', true)
	public static val ANONYMOUS_TIMESTAMP = new BuiltinType('timestamp', true)
	public static val ANONYMOUS_TIMER = new BuiltinType('timer', true)

	// needed by the typesystem
	public static val ANY_TYPE = new BuiltinType('any_type', true)
	public static val NO_TYPE = new BuiltinType('no_type', true)
	public static val STREAM_MANIPULATOR = new BuiltinType('stream_manipulator_type', true)
	public static val MISSING_TYPE = new BuiltinType('missing_type', true)

	new(String name, boolean anonymous) {
		super(anonymous)
		this.name = name
	}

	override MaslType getPrimitiveType() {
		switch name {
			case 'integer',
			case 'byte': new BuiltinType('long_integer')
			case 'string': new SequenceType(CHARACTER)
			default: 
				new BuiltinType(name)
		}
	}

	override String toStringInternal(Map<MaslType, String> seenTypes) {
		return prefix + name
	}
	
	override toString() {
		toStringRecursionSafe
	}
}

@Data
@FinalFieldsConstructor
class NamedType extends AbstractMaslType {
	String name
	MaslType type

	new(String name, MaslType type, boolean anonymous) {
		super(anonymous)
		this.name = name
		this.type = type
	}

	override getPrimitiveType() {
		type.primitiveType
	}

	override getComponentType() {
		type.componentType
	}
	
	override String toStringInternal(Map<MaslType, String> seenTypes) {
		seenTypes.put(this, name)
		prefix + 'type ' + name + ' is ' + type.toString(seenTypes)
	}
	
	override stripName() {
		type
	}<commit_msg>#9476 handle nested user defined types properly when matching characteristics<commit_after>package org.xtuml.bp.xtext.masl.typesystem

import java.util.List
import java.util.Map
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.Data
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.xtuml.bp.xtext.masl.masl.structure.ObjectDeclaration
import org.xtuml.bp.xtext.masl.masl.structure.TerminatorDefinition
import org.xtuml.bp.xtext.masl.masl.types.EnumerationTypeDefinition
import org.xtuml.bp.xtext.masl.masl.types.StructureTypeDefinition
import org.xtuml.bp.xtext.masl.masl.types.TypeDeclaration

/**
 * Dealing with EMF objects is tedious, so we define our own types
 */
interface MaslType {

	def MaslType getPrimitiveType()

	def boolean isAnonymous()
	
	def MaslType getComponentType()
	
	def MaslType stripName()
	
	def String toString(Map<MaslType, String> seenTypes)
}

@FinalFieldsConstructor
@Accessors(PUBLIC_GETTER)
abstract class AbstractMaslType implements MaslType {

	transient val boolean anonymous

	new() {
		anonymous = false
	}

	override MaslType getComponentType() {
		this
	}
	
	protected def prefix() {
		(if (anonymous) 'anonymous ' else '') 
	}
	
	override stripName() {
		this
	}
	
	override toString() {
		toStringRecursionSafe
	}
	
	protected def toStringRecursionSafe() {
		toString(newHashMap)
	}
	
	override String toString(Map<MaslType, String> seenTypes) {
		val seenName = seenTypes.get(this)
		if(seenName !== null)
			return seenName
		else
			return toStringInternal(seenTypes)
	}
	
	protected def String toStringInternal(Map<MaslType, String> map)
	
}

@Data
@FinalFieldsConstructor
class BuiltinType extends AbstractMaslType {
	val String name

	public static val CHARACTER = new BuiltinType('character')
	public static val STRING = new BuiltinType('string')
	public static val BOOLEAN = new BuiltinType('boolean')
	public static val BYTE = new BuiltinType('byte')
	public static val INTEGER = new BuiltinType('integer')
	public static val LONG_INTEGER = new BuiltinType('long_integer')
	public static val REAL = new BuiltinType('real')
	public static val DEVICE = new BuiltinType('device')
	public static val DURATION = new BuiltinType('duration')
	public static val TIMESTAMP = new BuiltinType('timestamp')
	public static val TIMER = new BuiltinType('timer')

	public static val ANONYMOUS_CHARACTER = new BuiltinType('character', true)
	public static val ANONYMOUS_STRING = new BuiltinType('string', true)
	public static val ANONYMOUS_BOOLEAN = new BuiltinType('boolean', true)
	public static val ANONYMOUS_BYTE = new BuiltinType('byte', true)
	public static val ANONYMOUS_INTEGER = new BuiltinType('integer', true)
	public static val ANONYMOUS_LONG_INTEGER = new BuiltinType('long_integer', true)
	public static val ANONYMOUS_REAL = new BuiltinType('real', true)
	public static val ANONYMOUS_DEVICE = new BuiltinType('device', true)
	public static val ANONYMOUS_DURATION = new BuiltinType('duration', true)
	public static val ANONYMOUS_TIMESTAMP = new BuiltinType('timestamp', true)
	public static val ANONYMOUS_TIMER = new BuiltinType('timer', true)

	// needed by the typesystem
	public static val ANY_TYPE = new BuiltinType('any_type', true)
	public static val NO_TYPE = new BuiltinType('no_type', true)
	public static val STREAM_MANIPULATOR = new BuiltinType('stream_manipulator_type', true)
	public static val MISSING_TYPE = new BuiltinType('missing_type', true)

	new(String name, boolean anonymous) {
		super(anonymous)
		this.name = name
	}

	override MaslType getPrimitiveType() {
		switch name {
			case 'integer',
			case 'byte': new BuiltinType('long_integer')
			case 'string': new SequenceType(CHARACTER)
			default: 
				new BuiltinType(name)
		}
	}

	override String toStringInternal(Map<MaslType, String> seenTypes) {
		return prefix + name
	}
	
	override toString() {
		toStringRecursionSafe
	}
}

@Data
@FinalFieldsConstructor
class NamedType extends AbstractMaslType {
	String name
	MaslType type

	new(String name, MaslType type, boolean anonymous) {
		super(anonymous)
		this.name = name
		this.type = type
	}

	override getPrimitiveType() {
		type.primitiveType
	}

	override getComponentType() {
		type.componentType
	}
	
	override String toStringInternal(Map<MaslType, String> seenTypes) {
		seenTypes.put(this, name)
		prefix + 'type ' + name + ' is ' + type.toString(seenTypes)
	}
	
	override stripName() {
		type.stripName
	}
{'fraction_non_alphanumeric': 0.08949152542372882, 'fraction_numerical': 0.0004519774011299435, 'mean_word_length': 5.150799166087561, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4561371', 'n_tokens_mistral': 2969, 'n_tokens_neox': 2777, 'n_words': 751}