<commit_before>/**
 * This file is part of Erjang - A JVM-based Erlang VM
 *
 * Copyright (c) 2009 by Trifork
 *
 * 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.
 **/

package erjang;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

import kilim.Pausable;

/**
 * 
 */
public class EModuleManager {

	static private Map<EAtom, ModuleInfo> infos = new ConcurrentHashMap<EAtom, ModuleInfo>();

	static FunctionInfo undefined_function = null;

	static {
		FunID uf = new FunID("error_handler", "undefined_function", 3);
		undefined_function = get_module_info(uf.module).get_function_info(uf);
	}

	static class FunctionInfo {
		private final FunID fun;

		/**
		 * @param fun
		 */
		public FunctionInfo(FunID fun) {
			this.fun = fun;
		}

		EModule defining_module;
		EFun resolved_value;
		Collection<Field> resolve_points = new TreeSet<Field>(
				new Comparator<Field>() {

					@Override
					public int compare(Field o1, Field o2) {
						if (o1 == o2)
							return 0;
						int c1 = o1.getDeclaringClass().getName().compareTo(
								o2.getDeclaringClass().getName());
						if (c1 != 0)
							return c1;
						int c2 = o1.getName().compareTo(o2.getName());
						return c2;
					}
				});
		private EFun error_handler;

		/**
		 * @param ref
		 * @throws IllegalAccessException
		 * @throws IllegalArgumentException
		 */
		synchronized void add_import(final Field ref) throws Exception {
			resolve_points.add(ref);
			if (resolved_value != null) {
				// System.out.println("binding "+fun+" "+resolved_value+" -> "+ref);
				ref.set(null, resolved_value);
			} else {
				EFun h = getFunErrorHandler();
				ref.set(null, h);
			}
		}

		private EFun getFunction() {
			if (resolved_value != null) {
				return resolved_value;
			} else {
				return getFunErrorHandler();
			}
		}

		private EFun getFunErrorHandler() {
			if (error_handler != null) {
				return error_handler;
			}
			
			error_handler = makeErrorHandler();
			return error_handler;
		}

		private EFun makeErrorHandler() {
			return EFun.get_fun_with_handler(fun.arity,
					new EFunHandler() {
						public EObject invoke(EProc proc, EObject[] args)
								throws Pausable {
							
							/** Get reference to error_handler:undefined_function/3 */
							EFun uf = undefined_function.resolved_value;

							/** this is just some debugging info to help understand downstream errors */
							if (ERT.DEBUG) {
							if (get_module_info(fun.module).is_loaded()) {
								System.err.println("MISSING "+fun);
							} else {
								System.err.println("resolving "+fun);
							}
							}
								
							if (uf == null) {
								/** this is just some debugging info to help understand downstream errors */
								if (ERT.DEBUG) {
									System.err.println("failed to load "+fun+" (error_handler:undefined_function/3 not found)");
								}
								
								throw new ErlangUndefined(fun.module,
										fun.function, fun.arity);
							} else {
								ESeq arg_list = ESeq.fromArray(args);
								ESeq ufa = ESeq.fromArray(new EObject[] {
										fun.module, fun.function, arg_list });
								return uf.apply(proc, ufa);
							}
						}
					});
		}

		/**
		 * @param fun2
		 * @param value
		 */
		synchronized void add_export(EModule definer, FunID fun2, EFun value)
				throws Exception {
			this.resolved_value = value;
			this.defining_module = definer;<commit_msg>when non-OTP (non-error_handler), try to load modules from erjpath<commit_after>/**
 * This file is part of Erjang - A JVM-based Erlang VM
 *
 * Copyright (c) 2009 by Trifork
 *
 * 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.
 **/

package erjang;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

import erjang.beam.Compiler;

import kilim.Pausable;

/**
 * 
 */
public class EModuleManager {

	static private Map<EAtom, ModuleInfo> infos = new ConcurrentHashMap<EAtom, ModuleInfo>();

	static FunctionInfo undefined_function = null;

	static {
		FunID uf = new FunID("error_handler", "undefined_function", 3);
		undefined_function = get_module_info(uf.module).get_function_info(uf);
	}

	static class FunctionInfo {
		private final FunID fun;

		/**
		 * @param fun
		 */
		public FunctionInfo(FunID fun) {
			this.fun = fun;
		}

		EModule defining_module;
		EFun resolved_value;
		Collection<Field> resolve_points = new TreeSet<Field>(
				new Comparator<Field>() {

					@Override
					public int compare(Field o1, Field o2) {
						if (o1 == o2)
							return 0;
						int c1 = o1.getDeclaringClass().getName().compareTo(
								o2.getDeclaringClass().getName());
						if (c1 != 0)
							return c1;
						int c2 = o1.getName().compareTo(o2.getName());
						return c2;
					}
				});
		private EFun error_handler;

		/**
		 * @param ref
		 * @throws IllegalAccessException
		 * @throws IllegalArgumentException
		 */
		synchronized void add_import(final Field ref) throws Exception {
			resolve_points.add(ref);
			if (resolved_value != null) {
				// System.out.println("binding "+fun+" "+resolved_value+" -> "+ref);
				ref.set(null, resolved_value);
			} else {
				EFun h = getFunErrorHandler();
				ref.set(null, h);
			}
		}

		private EFun getFunction() {
			if (resolved_value != null) {
				return resolved_value;
			} else {
				return getFunErrorHandler();
			}
		}

		private EFun getFunErrorHandler() {
			if (error_handler != null) {
				return error_handler;
			}
			
			error_handler = makeErrorHandler();
			return error_handler;
		}

		private EFun makeErrorHandler() {
			return EFun.get_fun_with_handler(fun.arity,
					new EFunHandler() {
						public EObject invoke(EProc proc, EObject[] args)
								throws Pausable {
							
							/** Get reference to error_handler:undefined_function/3 */
							EFun uf = undefined_function.resolved_value;

							/** this is just some debugging info to help understand downstream errors */
							if (ERT.DEBUG) {
							if (get_module_info(fun.module).is_loaded()) {
								System.err.println("MISSING "+fun);
							} else {
								System.err.println("resolving "+fun);
							}
							}
								
							if (uf == null) {
								if (!module_loaded(fun.module)) {
									try {
										File f = Compiler.find_and_compile(fun.module.getName());
										EModuleManager.load_module(fun.module, f.toURI().toURL());										
									} catch (IOException e) {
										// we don't report this separately; it ends up causing an undefined below...
									}
								}
								
								if (resolved_value != null) {
									return resolved_value.invoke(proc, args);
								}
								
								/** this is just some debugging info to help understand downstream errors */
								if (ERT.DEBUG) {
									System.err.println("failed to load "+fun+" (error_handler:undefined_function/3 not found)");
								}
								
								throw new ErlangUndefined(fun.module,
										fun.function, fun.arity);
							} else {
								ESeq arg_list = ESeq.fromArray(args);
								ESeq ufa = ESeq.fromArray(new EObject[] {
										fun.module, fun.function, arg_list });
								return uf.apply(proc, ufa);
							}
						}
					});
		}

		/**
		 * @param fun2
		 * @param value
		 */
		synchronized void add_export(EModule definer, FunID fun2, EFun value)
				throws Exception {
			this.resolved_value = value;
			this.defining_module = definer;
{'fraction_non_alphanumeric': 0.10973390948373891, 'fraction_numerical': 0.006367978166931999, 'mean_word_length': 2.7942191544434856, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3093144', 'n_tokens_mistral': 3501, 'n_tokens_neox': 2627, 'n_words': 736}