<commit_before>package orc.type.java;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import orc.ast.oil.arg.Arg;
import orc.env.Env;
import orc.error.compiletime.typing.TypeArityException;
import orc.error.compiletime.typing.TypeException;
import orc.error.runtime.MessageNotUnderstoodException;
import orc.lib.state.types.RefType;
import orc.type.Type;


/**
 * Type associated with a class constructor. Note that this is
 * not a type operator (ClassTycon); it is the type of the
 * constructor site itself. Users cannot write this
 * type explicitly; it is syntesized as the type of the value
 * bound by a 'class ... =' declaration.
 * 
 * @author dkitchin
 *
 */
public class ConstructorType extends Type {

	public Class cls;
	
	public ConstructorType(Class cls) {
		this.cls = cls;
	}

	@Override
	public Type call(Env<Type> ctx, Env<Type> typectx, List<Arg> args,
			List<Type> typeActuals) throws TypeException {
		
		/* Type inference for type parameters to Java constructors is 
		 * not yet implemented, and may be impossible to reasonably
		 * implement under the current inference strategy.
		 */
		if (typeActuals == null) {
			typeActuals = new LinkedList<Type>();
		}
		
		String f = Arg.asField(args);
		Map<java.lang.reflect.TypeVariable, orc.type.Type> javaCtx = Type.makeJavaCtx(cls, typeActuals);
		
		if (f != null) {
			
			/* This is a class filter pattern. It filters out all values which
			 * are not subclasses of this class. 
			 * Thus, regardless of the argument type, the pattern always binds
			 * a value of this class type.
			 */
			if (f.equals("?")) {
				return fromJavaClass(cls);
			}
			
			// This is a call to a static method or member.
			// Return the appropriate method type, or try to resolve a static field.
			else {
				List<Method> matchingMethods = new LinkedList<Method>();
				for (Method m : cls.getDeclaredMethods()) {
					if (Modifier.isStatic(m.getModifiers())
							&& Modifier.isPublic(m.getModifiers())
							&& m.getName().equals(f)) 
					{
						matchingMethods.add(m);	
					}
				}

				if (!matchingMethods.isEmpty()) {
					return Type.fromJavaMethods(matchingMethods, javaCtx);
				}
				else {
					// No static method matches. Try static fields.
					for (java.lang.reflect.Field fld : cls.getDeclaredFields()) {
						if (Modifier.isStatic(fld.getModifiers())
								&& Modifier.isPublic(fld.getModifiers())
								&& fld.getName().equals(f)) {
							return (new RefType()).instance(Type.fromJavaType(fld.getGenericType(), javaCtx));
						}<commit_msg>Fixed class recognizers in typechecker.<commit_after>package orc.type.java;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import orc.ast.oil.arg.Arg;
import orc.env.Env;
import orc.error.compiletime.typing.TypeArityException;
import orc.error.compiletime.typing.TypeException;
import orc.error.runtime.MessageNotUnderstoodException;
import orc.lib.state.types.RefType;
import orc.type.ArrowType;
import orc.type.Type;


/**
 * Type associated with a class constructor. Note that this is
 * not a type operator (ClassTycon); it is the type of the
 * constructor site itself. Users cannot write this
 * type explicitly; it is syntesized as the type of the value
 * bound by a 'class ... =' declaration.
 * 
 * @author dkitchin
 *
 */
public class ConstructorType extends Type {

	public Class cls;
	
	public ConstructorType(Class cls) {
		this.cls = cls;
	}

	@Override
	public Type call(Env<Type> ctx, Env<Type> typectx, List<Arg> args,
			List<Type> typeActuals) throws TypeException {
		
		/* Type inference for type parameters to Java constructors is 
		 * not yet implemented, and may be impossible to reasonably
		 * implement under the current inference strategy.
		 */
		if (typeActuals == null) {
			typeActuals = new LinkedList<Type>();
		}
		
		String f = Arg.asField(args);
		Map<java.lang.reflect.TypeVariable, orc.type.Type> javaCtx = Type.makeJavaCtx(cls, typeActuals);
		
		if (f != null) {
			
			/* This is a class filter pattern. It filters out all values which
			 * are not subclasses of this class. 
			 * Thus, regardless of the argument type, the pattern always binds
			 * a value of this class type.
			 */
			if (f.equals("?")) {
				return new ArrowType(TOP, fromJavaClass(cls));
			}
			
			// This is a call to a static method or member.
			// Return the appropriate method type, or try to resolve a static field.
			else {
				List<Method> matchingMethods = new LinkedList<Method>();
				for (Method m : cls.getDeclaredMethods()) {
					if (Modifier.isStatic(m.getModifiers())
							&& Modifier.isPublic(m.getModifiers())
							&& m.getName().equals(f)) 
					{
						matchingMethods.add(m);	
					}
				}

				if (!matchingMethods.isEmpty()) {
					return Type.fromJavaMethods(matchingMethods, javaCtx);
				}
				else {
					// No static method matches. Try static fields.
					for (java.lang.reflect.Field fld : cls.getDeclaredFields()) {
						if (Modifier.isStatic(fld.getModifiers())
								&& Modifier.isPublic(fld.getModifiers())
								&& fld.getName().equals(f)) {
							return (new RefType()).instance(Type.fromJavaType(fld.getGenericType(), javaCtx));
						}
{'fraction_non_alphanumeric': 0.11222037345165466, 'fraction_numerical': 0.0, 'mean_word_length': 3.3558776167471818, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, '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': '4930596', 'n_tokens_mistral': 1937, 'n_tokens_neox': 1645, 'n_words': 490}