view core/src/luan/modules/PackageLuan.java @ 339:673eebd83b74

remove circular package loading
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 31 Mar 2015 00:29:06 -0600
parents 0be73ac9103d
children 23b99a5039b5
line wrap: on
line source

package luan.modules;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import luan.Luan;
import luan.LuanState;
import luan.LuanTable;
import luan.LuanFunction;
import luan.LuanJavaFunction;
import luan.LuanElement;
import luan.LuanException;


public final class PackageLuan {

	public static final LuanFunction requireFn;
	static {
		try {
			requireFn = new LuanJavaFunction(PackageLuan.class.getMethod("require",LuanState.class,String.class),null);
		} catch(NoSuchMethodException e) {
			throw new RuntimeException(e);
		}
	}

	public static LuanTable loaded(LuanState luan) {
		LuanTable tbl = (LuanTable)luan.registry().get("Package.loaded");
		if( tbl == null ) {
			tbl = Luan.newTable();
			luan.registry().put("Package.loaded",tbl);
		}
		return tbl;
	}

	public static Object require(LuanState luan,String modName) throws LuanException {
		Object mod = load(luan,modName);
		if( mod==null )
			throw luan.exception( "module '"+modName+"' not found" );
		return mod;
	}

	public static Object load(LuanState luan,String modName) throws LuanException {
		LuanTable loaded = loaded(luan);
		Object mod = loaded.get(modName);
		if( mod == null ) {
			if( modName.startsWith("java:") ) {
				mod = JavaLuan.load(luan,modName.substring(5));
			} else {
				String src = read(luan,modName+".luan");
				if( src == null )
					return null;
				LuanTable env = Luan.newTable();
				LuanFunction loader = BasicLuan.load(luan,src,modName,env,false);
				Object result = Luan.first(
					luan.call(loader,"<require \""+modName+"\">",new Object[]{modName})
				);
				mod = result!=null ? result : env;
			}
			loaded.put(modName,mod);
		}
		return mod;
	}

	static String read(LuanState luan,String uri) throws LuanException {
		LuanTable t = IoLuan.Uri(luan,uri);
		if( t == null )
			return null;
		LuanFunction existsFn = (LuanFunction)t.get("exists");
		boolean exists = (Boolean)Luan.first(luan.call(existsFn));
		if( !exists )
			return null;
		LuanFunction reader = (LuanFunction)t.get("read_text");
		return (String)Luan.first(luan.call(reader));
	}

}