changeset 73:f86e4f77ef32

add package module git-svn-id: https://luan-java.googlecode.com/svn/trunk@74 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 12 Feb 2013 09:46:45 +0000
parents cd9dbd7477ca
children f003338d503b
files src/luan/LuanState.java src/luan/interp/UpValue.java src/luan/lib/BasicLib.java src/luan/lib/HtmlLib.java src/luan/lib/JavaLib.java src/luan/lib/MathLib.java src/luan/lib/PackageLib.java src/luan/lib/StringLib.java src/luan/lib/TableLib.java src/luan/tools/CmdLine.java src/luan/tools/WebRun.java src/luan/tools/WebShell.java
diffstat 12 files changed, 266 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/LuanState.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/LuanState.java	Tue Feb 12 09:46:45 2013 +0000
@@ -6,6 +6,7 @@
 import java.util.ArrayList;
 import luan.interp.LuanCompiler;
 import luan.lib.BasicLib;
+import luan.lib.PackageLib;
 import luan.lib.JavaLib;
 import luan.lib.MathLib;
 import luan.lib.StringLib;
@@ -15,15 +16,44 @@
 
 public abstract class LuanState {
 
+	public final LuanTable global = new LuanTable();
+	public final LuanTable loaded = new LuanTable();
+	public final LuanTable preload = new LuanTable();
+
+	public InputStream in = System.in;
+	public PrintStream out = System.out;
+	public PrintStream err = System.err;
+
+	private final List<MetatableGetter> mtGetters = new ArrayList<MetatableGetter>();
+	final List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>();
+
+
+	public Object load(LuanFunction loader,String modName) throws LuanException {
+		return load(loader,modName,null);
+	}
+
+	public Object load(LuanFunction loader,String modName,Object extra) throws LuanException {
+		Object mod = Luan.first(call(loader,LuanElement.JAVA,"loader",modName,extra));
+		if( mod == null )
+			mod = true;
+		loaded.put(modName,mod);
+		return mod;
+	}
+
 	public static LuanState newStandard() {
-		LuanState luan = LuanCompiler.newLuanState();
-		BasicLib.register(luan);
-		JavaLib.register(luan);
-		MathLib.register(luan);
-		StringLib.register(luan);
-		TableLib.register(luan);
-		HtmlLib.register(luan);
-		return luan;
+		try {
+			LuanState luan = LuanCompiler.newLuanState();
+			luan.load(BasicLib.LOADER,BasicLib.NAME);
+			luan.load(PackageLib.LOADER,PackageLib.NAME);
+			luan.load(JavaLib.LOADER,JavaLib.NAME);
+			luan.load(MathLib.LOADER,MathLib.NAME);
+			luan.load(StringLib.LOADER,StringLib.NAME);
+			luan.load(TableLib.LOADER,TableLib.NAME);
+			luan.load(HtmlLib.LOADER,HtmlLib.NAME);
+			return luan;
+		} catch(LuanException e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	public Object[] eval(String cmd,String sourceName) throws LuanException {
@@ -32,19 +62,6 @@
 	}
 
 
-
-	private final LuanTable global = new LuanTable();
-	private final List<MetatableGetter> mtGetters = new ArrayList<MetatableGetter>();
-	final List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>();
-
-	public InputStream in = System.in;
-	public PrintStream out = System.out;
-	public PrintStream err = System.err;
-
-	public final LuanTable global() {
-		return global;
-	}
-
 	public final LuanTable getMetatable(Object obj) {
 		if( obj instanceof LuanTable ) {
 			LuanTable table = (LuanTable)obj;
--- a/src/luan/interp/UpValue.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/interp/UpValue.java	Tue Feb 12 09:46:45 2013 +0000
@@ -65,7 +65,7 @@
 
 	static final Getter globalGetter = new Getter() {
 		public UpValue get(LuanStateImpl luan) {
-			return new UpValue(luan.global());
+			return new UpValue(luan.global);
 		}
 	};
 
--- a/src/luan/lib/BasicLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/BasicLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -21,46 +21,51 @@
 
 public final class BasicLib {
 
-	public static void register(LuanState luan) {
-		LuanTable global = luan.global();
-		global.put( "_G", global );
-		try {
-			global.put( "assert", new LuanJavaFunction(BasicLib.class.getMethod("assert_",LuanState.class,Object.class,String.class),null) );
-			add( global, "assert_boolean", LuanState.class, Boolean.TYPE );
-			add( global, "assert_nil", LuanState.class, Object.class );
-			add( global, "assert_number", LuanState.class, Number.class );
-			add( global, "assert_string", LuanState.class, String.class );
-			add( global, "assert_table", LuanState.class, LuanTable.class );
-			add( global, "do_file", LuanState.class, String.class );
-			add( global, "error", LuanState.class, Object.class );
-			add( global, "get_metatable", LuanState.class, Object.class );
-			add( global, "ipairs", LuanTable.class );
-			add( global, "load", LuanState.class, String.class, String.class );
-			add( global, "load_file", LuanState.class, String.class );
-			add( global, "pairs", LuanTable.class );
-			add( global, "print", LuanState.class, new Object[0].getClass() );
-			add( global, "raw_equal", Object.class, Object.class );
-			add( global, "raw_get", LuanTable.class, Object.class );
-			add( global, "raw_len", LuanState.class, Object.class );
-			add( global, "raw_set", LuanTable.class, Object.class, Object.class );
-			add( global, "set_metatable", LuanTable.class, LuanTable.class );
-			add( global, "to_number", Object.class, Integer.class );
-			add( global, "to_string", LuanState.class, Object.class );
-			add( global, "type", Object.class );
-			global.put( "_VERSION", Luan.version );
-	
-			add( global, "make_standard", LuanState.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "basic";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			LuanTable global = luan.global;
+			global.put( "_G", global );
+			try {
+				global.put( "assert", new LuanJavaFunction(BasicLib.class.getMethod("assert_",LuanState.class,Object.class,String.class),null) );
+				add( global, "assert_boolean", LuanState.class, Boolean.TYPE );
+				add( global, "assert_nil", LuanState.class, Object.class );
+				add( global, "assert_number", LuanState.class, Number.class );
+				add( global, "assert_string", LuanState.class, String.class );
+				add( global, "assert_table", LuanState.class, LuanTable.class );
+				add( global, "do_file", LuanState.class, String.class );
+				add( global, "error", LuanState.class, Object.class );
+				add( global, "get_metatable", LuanState.class, Object.class );
+				add( global, "ipairs", LuanTable.class );
+				add( global, "load", LuanState.class, String.class, String.class );
+				add( global, "load_file", LuanState.class, String.class );
+				add( global, "pairs", LuanTable.class );
+				add( global, "print", LuanState.class, new Object[0].getClass() );
+				add( global, "raw_equal", Object.class, Object.class );
+				add( global, "raw_get", LuanTable.class, Object.class );
+				add( global, "raw_len", LuanState.class, Object.class );
+				add( global, "raw_set", LuanTable.class, Object.class, Object.class );
+				add( global, "set_metatable", LuanTable.class, LuanTable.class );
+				add( global, "to_number", Object.class, Integer.class );
+				add( global, "to_string", LuanState.class, Object.class );
+				add( global, "type", Object.class );
+				global.put( "_VERSION", Luan.version );
+		
+				add( global, "make_standard", LuanState.class );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
 		t.put( method, new LuanJavaFunction(BasicLib.class.getMethod(method,parameterTypes),null) );
 	}
 
 	public static void make_standard(LuanState luan) {
-		LuanTable global = luan.global();
+		LuanTable global = luan.global;
 		global.put( "dofile", global.get("do_file") );
 		global.put( "getmetatable", global.get("get_metatable") );
 		global.put( "loadfile", global.get("load_file") );
--- a/src/luan/lib/HtmlLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/HtmlLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -2,21 +2,27 @@
 
 import luan.LuanState;
 import luan.LuanTable;
+import luan.LuanFunction;
 import luan.LuanJavaFunction;
 
 
 public final class HtmlLib {
 
-	public static void register(LuanState luan) {
-		LuanTable module = new LuanTable();
-		LuanTable global = luan.global();
-		global.put("html",module);
-		try {
-			add( module, "encode", String.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "html";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) {
+			LuanTable module = new LuanTable();
+			LuanTable global = luan.global;
+			global.put(NAME,module);
+			try {
+				add( module, "encode", String.class );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
 		t.put( method, new LuanJavaFunction(HtmlLib.class.getMethod(method,parameterTypes),null) );
--- a/src/luan/lib/JavaLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/JavaLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -27,19 +27,24 @@
 
 public final class JavaLib {
 
-	public static void register(LuanState luan) {
-		luan.addMetatableGetter(mg);
-		LuanTable module = new LuanTable();
-		LuanTable global = luan.global();
-		global.put("java",module);
-		try {
-			global.put( "import", new LuanJavaFunction(JavaLib.class.getMethod("importClass",LuanState.class,String.class),null) );
-			module.put( "class", new LuanJavaFunction(JavaLib.class.getMethod("getClass",LuanState.class,String.class),null) );
-			add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "java";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			luan.addMetatableGetter(mg);
+			LuanTable module = new LuanTable();
+			LuanTable global = luan.global;
+			global.put(NAME,module);
+			try {
+				global.put( "import", new LuanJavaFunction(JavaLib.class.getMethod("importClass",LuanState.class,String.class),null) );
+				module.put( "class", new LuanJavaFunction(JavaLib.class.getMethod("getClass",LuanState.class,String.class),null) );
+				add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static final LuanTable mt = new LuanTable();
 	static {
@@ -294,7 +299,7 @@
 	}
 
 	public static void importClass(LuanState luan,String name) throws LuanException {
-		luan.global().put( name.substring(name.lastIndexOf('.')+1), getClass(luan,name) );
+		luan.global.put( name.substring(name.lastIndexOf('.')+1), getClass(luan,name) );
 	}
 
 	static class AmbiguousJavaFunction extends LuanFunction {
--- a/src/luan/lib/MathLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/MathLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -2,21 +2,27 @@
 
 import luan.LuanState;
 import luan.LuanTable;
+import luan.LuanFunction;
 import luan.LuanJavaFunction;
 
 
 public final class MathLib {
 
-	public static void register(LuanState luan) {
-		LuanTable module = new LuanTable();
-		LuanTable global = luan.global();
-		global.put("math",module);
-		try {
-			add( module, "floor", Double.TYPE );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "math";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) {
+			LuanTable module = new LuanTable();
+			LuanTable global = luan.global;
+			global.put(NAME,module);
+			try {
+				add( module, "floor", Double.TYPE );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
 		t.put( method, new LuanJavaFunction(MathLib.class.getMethod(method,parameterTypes),null) );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/lib/PackageLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -0,0 +1,91 @@
+package luan.lib;
+
+import java.io.File;
+import java.util.List;
+import java.util.ArrayList;
+import luan.Luan;
+import luan.LuanState;
+import luan.LuanTable;
+import luan.LuanFunction;
+import luan.LuanJavaFunction;
+import luan.LuanElement;
+import luan.LuanException;
+
+
+public final class PackageLib {
+
+	public static final String NAME = "package";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			LuanTable global = luan.global;
+			LuanTable module = new LuanTable();
+			List<Object> searchers = new ArrayList<Object>();
+			global.put(NAME,module);
+			module.put("loaded",luan.loaded);
+			module.put("preload",luan.preload);
+			module.put("path","?.lua");
+			try {
+				add( global, "require", LuanState.class, String.class );
+				add( module, "search_path", String.class, String.class );
+				searchers.add( new LuanJavaFunction(PackageLib.class.getMethod("preloadSearcher",LuanState.class,String.class),null) );
+				searchers.add( new LuanJavaFunction(PackageLib.class.getMethod("fileSearcher",LuanState.class,String.class),null) );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			module.put("searchers",new LuanTable(searchers));
+			return LuanFunction.EMPTY_RTN;
+		}
+	};
+
+	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
+		t.put( method, new LuanJavaFunction(PackageLib.class.getMethod(method,parameterTypes),null) );
+	}
+
+	public static Object require(LuanState luan,String modName) throws LuanException {
+		LuanTable module = (LuanTable)luan.global.get(NAME);
+		Object mod = luan.loaded.get(modName);
+		if( mod == null ) {
+			LuanTable searchers = (LuanTable)module.get("searchers");
+			for( Object s : searchers.asList() ) {
+				LuanFunction searcher = (LuanFunction)s;
+				Object[] a = luan.call(searcher,LuanElement.JAVA,"searcher",modName);
+				if( a.length >= 1 && a[0] instanceof LuanFunction ) {
+					LuanFunction loader = (LuanFunction)a[0];
+					Object extra = a.length >= 2 ? a[1] : null;
+					mod = luan.load(loader,modName,extra);
+				}
+			}
+			if( mod == null )
+				throw new LuanException( luan, LuanElement.JAVA, "module '"+modName+"' not found" );
+		}
+		return mod;
+	}
+
+	public static String search_path(String NAME,String path) {
+		for( String s : path.split(";") ) {
+			String file = s.replaceAll("\\?",NAME);
+			if( new File(file).exists() )
+				return file;
+		}
+		return null;
+	}
+
+	private static final LuanFunction fileLoader = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			return BasicLib.do_file(luan,(String)args[1]);
+		}
+	};
+
+	public static Object[] fileSearcher(LuanState luan,String modName) {
+		LuanTable module = (LuanTable)luan.global.get(NAME);
+		String path = (String)module.get("path");
+		String file = search_path(modName,path);
+		return file==null ? LuanFunction.EMPTY_RTN : new Object[]{fileLoader,file};
+	}
+
+	public static Object preloadSearcher(LuanState luan,String modName) {
+		return luan.preload.get(modName);
+	}
+		
+}
--- a/src/luan/lib/StringLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/StringLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -13,27 +13,32 @@
 
 public final class StringLib {
 
-	public static void register(LuanState luan) {
-		LuanTable module = new LuanTable();
-		LuanTable global = luan.global();
-		global.put("string",module);
-		try {
-			module.put( "byte", new LuanJavaFunction(StringLib.class.getMethod("byte_",String.class,Integer.class,Integer.class),null) );
-			module.put( "char", new LuanJavaFunction(StringLib.class.getMethod("char_",new byte[0].getClass()),null) );
-			add( module, "find", String.class, String.class, Integer.class, Boolean.class );
-			add( module, "gmatch", String.class, String.class );
-			add( module, "gsub", LuanState.class, String.class, String.class, Object.class, Integer.class );
-			add( module, "len", String.class );
-			add( module, "lower", String.class );
-			add( module, "match", String.class, String.class, Integer.class );
-			add( module, "rep", String.class, Integer.TYPE, String.class );
-			add( module, "reverse", String.class );
-			add( module, "sub", String.class, Integer.TYPE, Integer.class );
-			add( module, "upper", String.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "string";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			LuanTable module = new LuanTable();
+			LuanTable global = luan.global;
+			global.put(NAME,module);
+			try {
+				module.put( "byte", new LuanJavaFunction(StringLib.class.getMethod("byte_",String.class,Integer.class,Integer.class),null) );
+				module.put( "char", new LuanJavaFunction(StringLib.class.getMethod("char_",new byte[0].getClass()),null) );
+				add( module, "find", String.class, String.class, Integer.class, Boolean.class );
+				add( module, "gmatch", String.class, String.class );
+				add( module, "gsub", LuanState.class, String.class, String.class, Object.class, Integer.class );
+				add( module, "len", String.class );
+				add( module, "lower", String.class );
+				add( module, "match", String.class, String.class, Integer.class );
+				add( module, "rep", String.class, Integer.TYPE, String.class );
+				add( module, "reverse", String.class );
+				add( module, "sub", String.class, Integer.TYPE, Integer.class );
+				add( module, "upper", String.class );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
 		t.put( method, new LuanJavaFunction(StringLib.class.getMethod(method,parameterTypes),null) );
--- a/src/luan/lib/TableLib.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/lib/TableLib.java	Tue Feb 12 09:46:45 2013 +0000
@@ -14,22 +14,27 @@
 
 public final class TableLib {
 
-	public static void register(LuanState luan) {
-		LuanTable module = new LuanTable();
-		LuanTable global = luan.global();
-		global.put("table",module);
-		try {
-			add( module, "concat", LuanState.class, LuanTable.class, String.class, Integer.class, Integer.class );
-			add( module, "insert", LuanState.class, LuanTable.class, Integer.TYPE, Object.class );
-			add( module, "pack", new Object[0].getClass() );
-			add( module, "remove", LuanState.class, LuanTable.class, Integer.TYPE );
-			add( module, "sort", LuanState.class, LuanTable.class, LuanFunction.class );
-			add( module, "sub_list", LuanTable.class, Integer.TYPE, Integer.TYPE );
-			add( module, "unpack", LuanTable.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
+	public static final String NAME = "table";
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		public Object[] call(LuanState luan,Object[] args) throws LuanException {
+			LuanTable module = new LuanTable();
+			LuanTable global = luan.global;
+			global.put(NAME,module);
+			try {
+				add( module, "concat", LuanState.class, LuanTable.class, String.class, Integer.class, Integer.class );
+				add( module, "insert", LuanState.class, LuanTable.class, Integer.TYPE, Object.class );
+				add( module, "pack", new Object[0].getClass() );
+				add( module, "remove", LuanState.class, LuanTable.class, Integer.TYPE );
+				add( module, "sort", LuanState.class, LuanTable.class, LuanFunction.class );
+				add( module, "sub_list", LuanTable.class, Integer.TYPE, Integer.TYPE );
+				add( module, "unpack", LuanTable.class );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			return LuanFunction.EMPTY_RTN;
 		}
-	}
+	};
 
 	private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
 		t.put( method, new LuanJavaFunction(TableLib.class.getMethod(method,parameterTypes),null) );
--- a/src/luan/tools/CmdLine.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/tools/CmdLine.java	Tue Feb 12 09:46:45 2013 +0000
@@ -65,7 +65,7 @@
 			for( int j=0; j<args.length; j++ ) {
 				argsTable.put( j, args[j] );
 			}
-			luan.global().put("arg",argsTable);
+			luan.global.put("arg",argsTable);
 			try {
 				LuanFunction fn = BasicLib.load_file(luan,file);
 				luan.call(fn,null,null,varArgs);
--- a/src/luan/tools/WebRun.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/tools/WebRun.java	Tue Feb 12 09:46:45 2013 +0000
@@ -33,8 +33,8 @@
 		try {
 			LuanState luan = newLuanState();
 			luan.out = out;
-			luan.global().put("request",request);
-			luan.global().put("response",response);
+			luan.global.put("request",request);
+			luan.global.put("response",response);
 			luan.eval(code,"WebRun");
 		} catch(LuanException e) {
 			logger.error(null,e);
--- a/src/luan/tools/WebShell.java	Tue Feb 12 05:44:15 2013 +0000
+++ b/src/luan/tools/WebShell.java	Tue Feb 12 09:46:45 2013 +0000
@@ -59,8 +59,8 @@
 						session.putValue("luan",luan);
 					}
 					luan.out = new PrintStream(history);
-					luan.global().put("request",request);
-					luan.global().put("response",response);
+					luan.global.put("request",request);
+					luan.global.put("response",response);
 					Object[] result = eval(luan,cmd);
 					if( result.length > 0 ) {
 						for( int i=0; i<result.length; i++ ) {