<commit_before>package wyone.spec;

import java.util.*;

import wyone.core.*;
import wyone.util.*;
import static wyone.util.SyntaxError.*;

public class TypeInference {
	private String filename;

	// maps constructor names to their declared types.
	private final HashMap<String, Type.Term> terms = new HashMap<String, Type.Term>();

	// globals contains the list of global variables
	// private final HashMap<String,Type> globals = new HashMap();

	public void infer(SpecFile spec) {
		filename = spec.filename;

		for (SpecFile.Decl d : spec.declarations) {
			if (d instanceof SpecFile.ClassDecl) {
				SpecFile.ClassDecl cd = (SpecFile.ClassDecl) d;
				terms.put(cd.name, Type.T_TERM(cd.name, null));
			} else if (d instanceof SpecFile.TermDecl) {
				SpecFile.TermDecl td = (SpecFile.TermDecl) d;
				terms.put(td.type.name, td.type);
			}
		}

		for (SpecFile.Decl d : spec.declarations) {
			if (d instanceof SpecFile.RewriteDecl) {
				infer((SpecFile.RewriteDecl) d);
			}
		}
	}

	public void infer(SpecFile.RewriteDecl rd) {
		
		HashMap<String,Type> environment = new HashMap<String,Type>();
		
		infer(rd.pattern,environment);
		
		for(SpecFile.RuleDecl rule : rd.rules) {
			infer(rule,environment);
		}
	}
	
	public Type.Ref infer(Pattern pattern, HashMap<String,Type> environment) {
		Type.Ref type;
		if(pattern instanceof Pattern.Leaf) {
			Pattern.Leaf p = (Pattern.Leaf) pattern; 
			type = Type.T_REF(p.type);
		} else if(pattern instanceof Pattern.Term) {
			Pattern.Term p = (Pattern.Term) pattern;
			Type.Ref d = null;
			if(p.data != null) {
				d = infer(p.data,environment);
			}
			if(p.variable != null) {
				environment.put(p.variable, d);
			}
			type = Type.T_REF(Type.T_TERM(p.name, d));
		} else {
			Pattern.Compound p = (Pattern.Compound) pattern;
			ArrayList<Type> types = new ArrayList<Type>();
			Pair<Pattern,String>[] p_elements = p.elements;
			for (int i=0;i!=p_elements.length;++i) {
				Pair<Pattern,String> ps = p_elements[i];
				String var = ps.second();
				Pattern pat = ps.first();
				Type t = infer(pat,environment);				
				types.add(t);
				if(var != null) {
					if(p.unbounded && (i+1) == p_elements.length) {
						if(p instanceof Pattern.List) {
							t = Type.T_LIST(true,t);
						} else {
							t = Type.T_SET(true,t);
						}
					} 
					environment.put(var,t);					
				}
			}
			if(p instanceof Pattern.List) { 
				type = Type.T_REF(Type.T_LIST(p.unbounded, types));
			} else {
				type = Type.T_REF(Type.T_SET(p.unbounded, types));
			}
		}
		pattern.attributes().add(new Attribute.Type(type));
		return type;
	}
	
	public void infer(SpecFile.RuleDecl rd, HashMap<String,Type> environment) {
		 environment = new HashMap<String,Type>(environment);
		
		for(Pair<String,Expr> let : rd.lets) {
			Type expr = resolve(let.second(),environment);
			environment.put(let.first(), expr);
		}
		
		if(rd.condition != null) {
			Type condition = resolve(rd.condition,environment);
			checkSubtype(Type.T_BOOL,condition,rd.condition);
		}
		
		Type result = resolve(rd.result,environment);

		// TODO: check result is a ref?
	}

	protected Type resolve(Expr expr, HashMap<String,Type> environment) {
		try {
			Type result;
			if (expr instanceof Expr.Constant) {
				result = resolve((Expr.Constant) expr, environment);
			} else if (expr instanceof Expr.UnOp) {
				result = resolve((Expr.UnOp) expr, environment);
			} else if (expr instanceof Expr.BinOp) {
				result = resolve((Expr.BinOp) expr, environment);
			} else if (expr instanceof Expr.NaryOp) {
				result = resolve((Expr.NaryOp) expr, environment);
			} else if (expr instanceof Expr.Constructor) {
				result = resolve((Expr.Constructor) expr, environment);
			} else if (expr instanceof Expr.Variable) {
				result = resolve((Expr.Variable) expr, environment);
			} else {
				syntaxError("unknown code encountered", filename, expr);
				return null;
			}
			expr.attributes().add(new Attribute.Type(result));
			return result; // dead code
		} catch (SyntaxError se) {
			throw se;
		} catch (Exception ex) {
			syntaxError("internal failure", filename, expr, ex);
		}
		return null; // dead code
	}

	protected Type resolve(Expr.Constant expr, HashMap<String, Type> environment) {
		Object v = expr.value;
		if (v instanceof Boolean) {
			return Type.T_BOOL;
		} else if (v instanceof Integer) {
			return Type.T_INT;
		} else if (v instanceof Double) {
			return Type.T_REAL;
		} else if (v instanceof String) {
			return Type.T_STRING;
		} else {
			syntaxError("unknown constant encountered ("
					+ v.getClass().getName() + ")", filename, expr);
			return null; // deadcode
		}
	}

	protected Type resolve(Expr.Constructor expr, HashMap<String,Type> environment) {
	
		if(expr.argument != null) {
			Type arg_t = resolve(expr.argument,environment);
			
			// TODO: type check parameter argument
		}

		Type.Term type = terms.get(expr.name);
		if (type == null) {
			syntaxError("function not declared", filename, expr);
		}<commit_msg>Minor bug fix for integer constants.<commit_after>package wyone.spec;

import java.math.BigInteger;
import java.util.*;

import wyone.core.*;
import wyone.util.*;
import static wyone.util.SyntaxError.*;

public class TypeInference {
	private String filename;

	// maps constructor names to their declared types.
	private final HashMap<String, Type.Term> terms = new HashMap<String, Type.Term>();

	// globals contains the list of global variables
	// private final HashMap<String,Type> globals = new HashMap();

	public void infer(SpecFile spec) {
		filename = spec.filename;

		for (SpecFile.Decl d : spec.declarations) {
			if (d instanceof SpecFile.ClassDecl) {
				SpecFile.ClassDecl cd = (SpecFile.ClassDecl) d;
				terms.put(cd.name, Type.T_TERM(cd.name, null));
			} else if (d instanceof SpecFile.TermDecl) {
				SpecFile.TermDecl td = (SpecFile.TermDecl) d;
				terms.put(td.type.name, td.type);
			}
		}

		for (SpecFile.Decl d : spec.declarations) {
			if (d instanceof SpecFile.RewriteDecl) {
				infer((SpecFile.RewriteDecl) d);
			}
		}
	}

	public void infer(SpecFile.RewriteDecl rd) {
		
		HashMap<String,Type> environment = new HashMap<String,Type>();
		
		infer(rd.pattern,environment);
		
		for(SpecFile.RuleDecl rule : rd.rules) {
			infer(rule,environment);
		}
	}
	
	public Type.Ref infer(Pattern pattern, HashMap<String,Type> environment) {
		Type.Ref type;
		if(pattern instanceof Pattern.Leaf) {
			Pattern.Leaf p = (Pattern.Leaf) pattern; 
			type = Type.T_REF(p.type);
		} else if(pattern instanceof Pattern.Term) {
			Pattern.Term p = (Pattern.Term) pattern;
			Type.Ref d = null;
			if(p.data != null) {
				d = infer(p.data,environment);
			}
			if(p.variable != null) {
				environment.put(p.variable, d);
			}
			type = Type.T_REF(Type.T_TERM(p.name, d));
		} else {
			Pattern.Compound p = (Pattern.Compound) pattern;
			ArrayList<Type> types = new ArrayList<Type>();
			Pair<Pattern,String>[] p_elements = p.elements;
			for (int i=0;i!=p_elements.length;++i) {
				Pair<Pattern,String> ps = p_elements[i];
				String var = ps.second();
				Pattern pat = ps.first();
				Type t = infer(pat,environment);				
				types.add(t);
				if(var != null) {
					if(p.unbounded && (i+1) == p_elements.length) {
						if(p instanceof Pattern.List) {
							t = Type.T_LIST(true,t);
						} else {
							t = Type.T_SET(true,t);
						}
					} 
					environment.put(var,t);					
				}
			}
			if(p instanceof Pattern.List) { 
				type = Type.T_REF(Type.T_LIST(p.unbounded, types));
			} else {
				type = Type.T_REF(Type.T_SET(p.unbounded, types));
			}
		}
		pattern.attributes().add(new Attribute.Type(type));
		return type;
	}
	
	public void infer(SpecFile.RuleDecl rd, HashMap<String,Type> environment) {
		 environment = new HashMap<String,Type>(environment);
		
		for(Pair<String,Expr> let : rd.lets) {
			Type expr = resolve(let.second(),environment);
			environment.put(let.first(), expr);
		}
		
		if(rd.condition != null) {
			Type condition = resolve(rd.condition,environment);
			checkSubtype(Type.T_BOOL,condition,rd.condition);
		}
		
		Type result = resolve(rd.result,environment);

		// TODO: check result is a ref?
	}

	protected Type resolve(Expr expr, HashMap<String,Type> environment) {
		try {
			Type result;
			if (expr instanceof Expr.Constant) {
				result = resolve((Expr.Constant) expr, environment);
			} else if (expr instanceof Expr.UnOp) {
				result = resolve((Expr.UnOp) expr, environment);
			} else if (expr instanceof Expr.BinOp) {
				result = resolve((Expr.BinOp) expr, environment);
			} else if (expr instanceof Expr.NaryOp) {
				result = resolve((Expr.NaryOp) expr, environment);
			} else if (expr instanceof Expr.Constructor) {
				result = resolve((Expr.Constructor) expr, environment);
			} else if (expr instanceof Expr.Variable) {
				result = resolve((Expr.Variable) expr, environment);
			} else {
				syntaxError("unknown code encountered", filename, expr);
				return null;
			}
			expr.attributes().add(new Attribute.Type(result));
			return result; // dead code
		} catch (SyntaxError se) {
			throw se;
		} catch (Exception ex) {
			syntaxError("internal failure", filename, expr, ex);
		}
		return null; // dead code
	}

	protected Type resolve(Expr.Constant expr, HashMap<String, Type> environment) {
		Object v = expr.value;
		if (v instanceof Boolean) {
			return Type.T_BOOL;
		} else if (v instanceof BigInteger) {
			return Type.T_INT;
		} else if (v instanceof Double) {
			return Type.T_REAL;
		} else if (v instanceof String) {
			return Type.T_STRING;
		} else {
			syntaxError("unknown constant encountered ("
					+ v.getClass().getName() + ")", filename, expr);
			return null; // deadcode
		}
	}

	protected Type resolve(Expr.Constructor expr, HashMap<String,Type> environment) {
	
		if(expr.argument != null) {
			Type arg_t = resolve(expr.argument,environment);
			
			// TODO: type check parameter argument
		}

		Type.Term type = terms.get(expr.name);
		if (type == null) {
			syntaxError("function not declared", filename, expr);
		}
{'fraction_non_alphanumeric': 0.13673163418290854, 'fraction_numerical': 0.000399800099950025, 'mean_word_length': 3.429393536963258, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, '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': '2265493', 'n_tokens_mistral': 3843, 'n_tokens_neox': 3205, 'n_words': 795}