changeset 24:7ee247560db5

add VarArgs git-svn-id: https://luan-java.googlecode.com/svn/trunk@25 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 06 Dec 2012 04:40:54 +0000
parents 2446c1755d9b
children 0e406bd9ac7b
files src/luan/LuaClosure.java src/luan/LuaState.java src/luan/interp/Chunk.java src/luan/interp/LuaParser.java src/luan/interp/VarArgs.java
diffstat 5 files changed, 67 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
diff -r 2446c1755d9b -r 7ee247560db5 src/luan/LuaClosure.java
--- a/src/luan/LuaClosure.java	Thu Dec 06 00:35:13 2012 +0000
+++ b/src/luan/LuaClosure.java	Thu Dec 06 04:40:54 2012 +0000
@@ -14,7 +14,18 @@
 	public Object[] call(LuaState lua,Object... args) throws LuaException {
 		Chunk chunk = this.chunk;
 		while(true) {
-			Object[] stack = lua.newStack(chunk.stackSize);
+			Object[] varArgs = null;
+			if( chunk.isVarArg ) {
+				if( args.length > chunk.numArgs ) {
+					varArgs = new Object[ args.length - chunk.numArgs ];
+					for( int i=0; i<varArgs.length; i++ ) {
+						varArgs[i] = args[chunk.numArgs+i];
+					}
+				} else {
+					varArgs = LuaFunction.EMPTY_RTN;
+				}
+			}
+			Object[] stack = lua.newStack(chunk.stackSize,varArgs);
 			final int n = Math.min(args.length,chunk.numArgs);
 			for( int i=0; i<n; i++ ) {
 				stack[i] = args[i];
diff -r 2446c1755d9b -r 7ee247560db5 src/luan/LuaState.java
--- a/src/luan/LuaState.java	Thu Dec 06 00:35:13 2012 +0000
+++ b/src/luan/LuaState.java	Thu Dec 06 04:40:54 2012 +0000
@@ -12,10 +12,12 @@
 	private static class LuaStack {
 		final LuaStack previousStack;
 		final Object[] a;
+		final Object[] varArgs;
 
-		LuaStack( LuaStack previousStack, int stackSize) {
+		LuaStack( LuaStack previousStack, int stackSize, Object[] varArgs) {
 			this.previousStack = previousStack;
 			this.a = new Object[stackSize];
+			this.varArgs = varArgs;
 		}
 	}
 
@@ -23,8 +25,8 @@
 	public Object[] returnValues;
 	public LuaClosure tailFn;
 
-	Object[] newStack(int stackSize) {
-		stack = new LuaStack(stack,stackSize);
+	Object[] newStack(int stackSize, Object[] varArgs) {
+		stack = new LuaStack(stack,stackSize,varArgs);
 		return stack.a;
 	}
 
@@ -38,4 +40,7 @@
 		return stack.a;
 	}
 
+	public Object[] varArgs() {
+		return stack.varArgs;
+	}
 }
diff -r 2446c1755d9b -r 7ee247560db5 src/luan/interp/Chunk.java
--- a/src/luan/interp/Chunk.java	Thu Dec 06 00:35:13 2012 +0000
+++ b/src/luan/interp/Chunk.java	Thu Dec 06 04:40:54 2012 +0000
@@ -9,11 +9,13 @@
 	public final Stmt block;
 	public final int stackSize;
 	public final int numArgs;
+	public final boolean isVarArg;
 
-	Chunk(Stmt block,int stackSize,int numArgs) {
+	Chunk(Stmt block,int stackSize,int numArgs,boolean isVarArg) {
 		this.block = block;
 		this.stackSize = stackSize;
 		this.numArgs = numArgs;
+		this.isVarArg = isVarArg;
 		fixReturns(block);
 	}
 
diff -r 2446c1755d9b -r 7ee247560db5 src/luan/interp/LuaParser.java
--- a/src/luan/interp/LuaParser.java	Thu Dec 06 00:35:13 2012 +0000
+++ b/src/luan/interp/LuaParser.java	Thu Dec 06 04:40:54 2012 +0000
@@ -28,6 +28,7 @@
 		final List<String> symbols = new ArrayList<String>();
 		int stackSize = 0;
 		int loops = 0;
+		boolean isVarArg = false;
 
 		Frame(Frame parent) {
 			this.parent = parent;
@@ -105,7 +106,7 @@
 				Sequence(
 					Block(),
 					EOI,
-					push( new Chunk( (Stmt)pop(), frame.stackSize, 0 ) )
+					push( new Chunk( (Stmt)pop(), frame.stackSize, 0, false ) )
 				)
 			)
 		);
@@ -391,7 +392,10 @@
 	}
 
 	Rule Expr() {
-		return OrExpr();
+		return FirstOf(
+			VarArgs(),
+			OrExpr()
+		);
 	}
 
 	Rule OrExpr() {
@@ -488,12 +492,34 @@
 	Rule Function() {
 		return Sequence(
 			action( frame = new Frame(frame) ),
-			'(', incParens(), Spaces(), Optional(NameList()), ')', decParens(), Spaces(), Block(), Keyword("end"),
-			push( new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize() ) ),
+			'(', incParens(), Spaces(),
+			Optional(
+				FirstOf(
+					Sequence( NameList(), Optional( ',', Spaces(), VarArgName() ) ),
+					VarArgName()
+				)
+			),
+			')', decParens(), Spaces(), Block(), Keyword("end"),
+			push( new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize(), frame.isVarArg ) ),
 			action( frame = frame.parent )
 		);
 	}
 
+	Rule VarArgName() {
+		return Sequence(
+			"...", Spaces(),
+			action( frame.isVarArg = true )
+		);
+	}
+
+	Rule VarArgs() {
+		return Sequence(
+			"...", Spaces(),
+			frame.isVarArg,
+			push( VarArgs.INSTANCE )
+		);
+	}
+
 	Rule TableExpr() {
 		return Sequence(
 			'{', incParens(), Spaces(),
diff -r 2446c1755d9b -r 7ee247560db5 src/luan/interp/VarArgs.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/VarArgs.java	Thu Dec 06 04:40:54 2012 +0000
@@ -0,0 +1,14 @@
+package luan.interp;
+
+import luan.LuaState;
+
+
+final class VarArgs implements Expressions {
+	static final VarArgs INSTANCE = new VarArgs();
+
+	private VarArgs() {}
+
+	@Override public Object[] eval(LuaState lua) {
+		return lua.varArgs();
+	}
+}