diff src/luan/impl/LuanParser.java @ 1400:221eedb0f54e

fix inner class gc bug
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 13 Sep 2019 05:05:51 -0600
parents f5368cd8c056
children 514b7a62fe27
line wrap: on
line diff
--- a/src/luan/impl/LuanParser.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/impl/LuanParser.java	Fri Sep 13 05:05:51 2019 -0600
@@ -89,11 +89,11 @@
 			this.i = i;
 			this.value = value;
 		}
-
+/*
 		String init() {
 			return "upValues[" + i + "] = " + value + ";  ";
 		}
-
+*/
 		@Override public Expr exp() {
 			Expr exp = new Expr(Val.SINGLE,false);
 			exp.add( new Object() {
@@ -168,6 +168,10 @@
 
 	}
 
+	private static AtomicInteger classCounter = new AtomicInteger();
+	private int innerCounter = 0;
+	private final List<Inner> inners = new ArrayList<Inner>();
+
 	private Frame frame;
 	private final Parser parser;
 	private final Stmts top;
@@ -225,36 +229,29 @@
 		return t;
 	}
 
-	private Class newFnClass(Stmts stmt) {
-		return toFnClass( stmt, frame.upValueSymbols );
+	private Expr newFnExp(Stmts stmt,String name) {
+		String className = "INNER" + ++innerCounter;
+		Inner inner = new Inner( stmt, name, className );
+		inners.add(inner);
+		return inner.toInnerFnExp( frame.upValueSymbols );
+//		return toFnExp( stmt, frame.upValueSymbols, name );
 	}
 
-	private Expr newFnExp(Stmts stmt,String name) {
-		return toFnExp( stmt, frame.upValueSymbols, name );
-	}
-/*
-	Class Expression() throws ParseException {
-		Spaces();
-		parser.begin();
-		Expr expr = ExprZ();
-		if( expr != null && parser.endOfInput() ) {
-			top.add( "return " );
-			top.addAll( expr );
-			top.add( ";  " );
-			top.hasReturn = true;
-			return parser.success(newFnClass(top));
-		}
-		return parser.failure(null);
-	}
-*/
 	Class RequiredModule() throws ParseException {
 		GetRequiredModule();
-		return newFnClass(top);
+		String className = "EXP" + classCounter.incrementAndGet();
+		String classCode = toFnString( top, frame.upValueSymbols, className, inners );
+		try {
+			return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode);
+		} catch(ClassNotFoundException e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	String RequiredModuleSource() throws ParseException {
 		GetRequiredModule();
-		return toFnString( top, frame.upValueSymbols );
+		String className = "EXP" + classCounter.incrementAndGet();
+		return toFnString( top, frame.upValueSymbols, className, inners );
 	}
 
 	void GetRequiredModule() throws ParseException {
@@ -729,7 +726,7 @@
 
 	private Stmts ExpressionsStmt() throws ParseException {
 		parser.begin();
-		Expr exp = ExprZ();
+		Expr exp = Expression();
 		if( exp != null && exp.isStmt ) {
 			Stmts stmt = new Stmts();
 			if( exp.valType==Val.SINGLE ) {
@@ -755,10 +752,10 @@
 
 	private Expr RequiredExpr() throws ParseException {
 		parser.begin();
-		return parser.success(required(ExprZ(),"Bad expression"));
+		return parser.success(required(Expression(),"Bad expression"));
 	}
 
-	private Expr ExprZ() throws ParseException {
+	private Expr Expression() throws ParseException {
 		return OrExpr();
 	}
 
@@ -1175,7 +1172,7 @@
 			return parser.success(newExp);
 		}
 		parser.rollback();
-		Expr exprs = ExprZ();
+		Expr exprs = Expression();
 		if( exprs != null ) {
 			return parser.success(exprs);
 		}
@@ -1381,7 +1378,7 @@
 
 	private boolean ExpList(List<Expr> builder) throws ParseException {
 		parser.begin();
-		Expr exp = ExprZ();
+		Expr exp = Expression();
 		if( exp==null )
 			return parser.failure();
 		exp.addNewLines();
@@ -1872,8 +1869,6 @@
 	}
 
 
-	private static AtomicInteger classCounter = new AtomicInteger();
-
 	private enum Val { SINGLE, ARRAY }
 
 	private class Expr extends ParseList {
@@ -1956,27 +1951,11 @@
 		boolean hasReturn = false;
 	}
 
-	private Class toFnClass(Stmts stmts,List<UpSym> upValueSymbols) {
-		String className = "EXP" + classCounter.incrementAndGet();
-		String classCode = toFnString(stmts,upValueSymbols,className);
-		try {
-//System.out.println(parser.sourceName);
-//System.out.println(classCode);
-			return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode);
-		} catch(ClassNotFoundException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	private String toFnString(Stmts stmts,List<UpSym> upValueSymbols) {
-		String className = "EXP" + classCounter.incrementAndGet();
-		return toFnString(stmts,upValueSymbols,className);
-	}
-
-	private String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className) {
+	private static String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className,List<Inner> inners) {
 		if( !stmts.hasReturn )
 			stmts.add( "\nreturn LuanFunction.NOTHING;" );
-		return ""
+		StringBuilder sb = new StringBuilder();
+		sb.append( ""
 			+"package luan.impl;  "
 			+"import luan.LuanClosure;  "
 			+"import luan.Luan;  "
@@ -1986,8 +1965,7 @@
 
 			+"public class " + className +" extends LuanClosure {  "
 				+"public "+className+"(Luan luan,boolean javaOk,String sourceName) throws LuanException {  "
-					+"super(luan,"+upValueSymbols.size()+",javaOk,sourceName);  "
-					+ init(upValueSymbols)
+					+"super(luan,"+toUpValues(upValueSymbols)+",javaOk,sourceName);  "
 				+"}  "
 
 				+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
@@ -1995,11 +1973,87 @@
 					+"Object t;  "
 					+"Object[] a;  "
 					+ stmts
-				+"\n}  "
+				+"\n}\n"
+		);
+		for( Inner inner : inners ) {
+			sb.append( '\n' );
+			sb.append( inner.toInnerFnString(lines(sb.toString())) + '\n' );
+		}
+		sb.append( ""
 			+"}\n"
-		;
+		);
+		return sb.toString();
 	}
 
+	private class Inner {
+		private final Stmts stmts;
+		private final String name;
+		private final String className;
+		private final int lines;
+		private final int endLine;
+
+		Inner(Stmts stmts,String name,String className) {
+			this.stmts = stmts;
+			this.name = name;
+			this.className = className;
+
+			stmts.addNewLines();
+			if( !stmts.hasReturn )
+				stmts.add( "return LuanFunction.NOTHING;  " );
+			this.lines = lines( stmts.toString() );
+			this.endLine = lines( parser.textFrom(0) );
+		}
+
+		Expr toInnerFnExp(List<UpSym> upValueSymbols) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(
+				"new "+className+"(luan(),"+toUpValues(upValueSymbols)+",javaOk,sourceName)"
+			);
+			for( int i=0; i<lines; i++ ) {
+				sb.append('\n');
+			}
+
+			Expr exp = new Expr(Val.SINGLE,false);
+			exp.add( sb.toString() );
+			return exp;
+		}
+
+		String toInnerFnString(int line) {
+			int diff = line + lines - endLine;
+			String name = this.name!=null ? this.name : "";
+			name += "$" + diff;
+			//name += "_" + lines + "_" + endLine + "_" + line;
+			StringBuilder sb = new StringBuilder();
+			sb.append( ""
+				+"private static class " + className +" extends LuanClosure {  "
+					+className+"(Luan luan,Pointer[] upValues,boolean javaOk,String sourceName) throws LuanException {  "
+						+"super(luan,upValues,javaOk,sourceName);  "
+					+"}  "
+					+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
+						+"return _" + name + "(luan,args);  "
+					+"}  "
+					+"private Object _" + name + "(Luan luan,Object[] args) throws LuanException {  "
+						+"final Pointer[] parentUpValues = upValues;  "
+						+"Object t;  "
+						+"Object[] a;  "
+						+ stmts
+					+"}  "
+				+"}  "
+			);
+			return sb.toString();
+		}
+	}
+
+	private static int lines(String s) {
+		int lines = 0;
+		final int n = s.length();
+		for( int i=0; i<n; i++ ) {
+			if( s.charAt(i) == '\n' )
+				lines++;
+		}
+		return lines;
+	}
+/*
 	private Expr toFnExp(Stmts stmt,List<UpSym> upValueSymbols,String name) {
 		stmt.addNewLines();
 		if( !stmt.hasReturn )
@@ -2039,5 +2093,15 @@
 		}
 		return sb.toString();
 	}
+*/
+	private static String toUpValues(List<UpSym> upValueSymbols) {
+		StringBuilder sb = new StringBuilder();
+		sb.append( "new Pointer[]{ " );
+		for( UpSym upSym : upValueSymbols ) {
+			sb.append( upSym.value + ", " );
+		}
+		sb.append( "}" );
+		return sb.toString();
+	}
 
 }