changeset 1384:f5368cd8c056

remove template expressions and String.concat
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 15 Aug 2019 14:33:35 -0600
parents a3d0d1c2ce89
children 4d6c1bb8f975
files conv.txt src/luan/host/Util.luan src/luan/impl/LuanParser.java src/luan/modules/String.luan src/luan/modules/StringLuan.java website/src/diff.html website/src/manual.html
diffstat 7 files changed, 87 insertions(+), 164 deletions(-) [+]
line wrap: on
line diff
--- a/conv.txt	Thu Aug 01 16:49:47 2019 -0600
+++ b/conv.txt	Thu Aug 15 14:33:35 2019 -0600
@@ -1,3 +1,7 @@
+(%>
+( %>
+String.concat
+
 Lucene.update_in_transaction
 
 Lucene.index
--- a/src/luan/host/Util.luan	Thu Aug 01 16:49:47 2019 -0600
+++ b/src/luan/host/Util.luan	Thu Aug 15 14:33:35 2019 -0600
@@ -28,9 +28,7 @@
 	local encoded = Base64.getEncoder().encodeToString(sha1)
 	local file = Io.schemes.file(dir.."/password.nginx")
 	file.delete()
-	file.write_text( %>
-admin:{SHA}<%=encoded%>
-<%	)
+	file.write_text("admin:{SHA}"..encoded.."\n")
 end
 
 local function digest_authentication(dir,password)
@@ -43,18 +41,14 @@
 	end
 	local file = Io.schemes.file(dir.."/password.nginx")
 	file.delete()
-	file.write_text( %>
-admin:Restricted:<%=encoded%>
-<%	)
+	file.write_text("admin:Restricted:"..encoded.."\n")
 end
 
 function Util.write_password(domain,password)
 	local dir = Hosting.sites_dir..lower(domain)
 	local file = Io.schemes.file(dir.."/info.luan")
 	file.delete()
-	file.write_text( %>
-return <%= stringify{password=password} %>
-<%	)
+	file.write_text("return "..stringify{password=password}.."\n")
 	digest_authentication(dir,password)
 end
 
--- a/src/luan/impl/LuanParser.java	Thu Aug 01 16:49:47 2019 -0600
+++ b/src/luan/impl/LuanParser.java	Thu Aug 15 14:33:35 2019 -0600
@@ -168,20 +168,6 @@
 
 	}
 
-	private static class In {
-		static final In NOTHING = new In(false);
-
-		final boolean template;
-
-		private In(boolean template) {
-			this.template = template;
-		}
-
-		In template() {
-			return template ? this : new In(true);
-		}
-	}
-
 	private Frame frame;
 	private final Parser parser;
 	private final Stmts top;
@@ -250,7 +236,7 @@
 	Class Expression() throws ParseException {
 		Spaces();
 		parser.begin();
-		Expr expr = ExprZ(In.NOTHING);
+		Expr expr = ExprZ();
 		if( expr != null && parser.endOfInput() ) {
 			top.add( "return " );
 			top.addAll( expr );
@@ -373,7 +359,7 @@
 	}
 
 	private Stmts TemplateStmt() throws ParseException {
-		Expr exprs = TemplateExpressions(In.NOTHING);
+		Expr exprs = TemplateExpressions();
 		if( exprs == null )
 			return null;
 		Stmts stmt = new Stmts();
@@ -383,20 +369,17 @@
 		return stmt;
 	}
 
-	private Expr TemplateExpressions(In in) throws ParseException {
-		if( in.template )
-			return null;
+	private Expr TemplateExpressions() throws ParseException {
 		int start = parser.begin();
 		if( !parser.match( "%>" ) )
 			return parser.failure(null);
 		EndOfLine();
-		In inTemplate = in.template();
 		List<Expr> builder = new ArrayList<Expr>();
 		while(true) {
 			if( parser.match( "<%=" ) ) {
 				Spaces();
 				Expr exp = new Expr(Val.SINGLE,false);
-				exp.addAll( RequiredExpr(inTemplate).single() );
+				exp.addAll( RequiredExpr().single() );
 				builder.add(exp);
 				RequiredMatch( "%>" );
 			} else if( parser.match( "<%" ) ) {
@@ -426,7 +409,7 @@
 		parser.begin();
 		if( !Keyword("return") )
 			return parser.failure(null);
-		Expr exprs = ExpStringList(In.NOTHING);
+		Expr exprs = ExpStringList();
 		Stmts stmt = new Stmts();
 		stmt.add( "return " );
 		if( exprs != null )
@@ -503,7 +486,7 @@
 		List<String> names = RequiredNameList();
 		if( !Keyword("in") )
 			return parser.failure(null);
-		Expr expr = RequiredExpr(In.NOTHING).single();
+		Expr expr = RequiredExpr().single();
 		RequiredKeyword("do");
 
 		String fnVar = "fn"+ ++forCounter;
@@ -550,7 +533,7 @@
 		Stmts stmt = new Stmts();
 		if( parser.match( '=' ) ) {
 			Spaces();
-			Expr values = ExpStringList(In.NOTHING);
+			Expr values = ExpStringList();
 			if( values==null )
 				throw parser.exception("Expressions expected");
 			stmt.addAll( makeLocalSetStmt(names,values) );
@@ -599,7 +582,7 @@
 		parser.begin();
 		if( !Keyword("while") )
 			return parser.failure(null);
-		Expr cnd = RequiredExpr(In.NOTHING).single();
+		Expr cnd = RequiredExpr().single();
 		RequiredKeyword("do");
 		Stmts loop = RequiredLoopBlock();
 		RequiredEnd("end_while");
@@ -618,7 +601,7 @@
 			return parser.failure(null);
 		Stmts loop =RequiredLoopBlock();
 		RequiredKeyword("until");
-		Expr cnd = RequiredExpr(In.NOTHING).single();
+		Expr cnd = RequiredExpr().single();
 		Stmts stmt = new Stmts();
 		stmt.add( "do {  " );
 		stmt.addAll( loop );
@@ -643,7 +626,7 @@
 		Expr cnd;
 		Stmts block;
 		boolean hasReturn = true;
-		cnd = RequiredExpr(In.NOTHING).single();
+		cnd = RequiredExpr().single();
 		RequiredKeyword("then");
 		block = RequiredBlock();
 		stmt.add( "if( Luan.checkBoolean(" );
@@ -653,7 +636,7 @@
 		if( !block.hasReturn )
 			hasReturn = false;
 		while( Keyword("elseif") ) {
-			cnd = RequiredExpr(In.NOTHING).single();
+			cnd = RequiredExpr().single();
 			RequiredKeyword("then");
 			block = RequiredBlock();
 			stmt.add( "} else if( Luan.checkBoolean(" );
@@ -695,7 +678,7 @@
 		if( !parser.match( '=' ) )
 			return parser.failure(null);
 		Spaces();
-		Expr values = ExpStringList(In.NOTHING);
+		Expr values = ExpStringList();
 		if( values==null )
 //			throw parser.exception("Expressions expected");
 			return parser.failure(null);
@@ -746,7 +729,7 @@
 
 	private Stmts ExpressionsStmt() throws ParseException {
 		parser.begin();
-		Expr exp = ExprZ(In.NOTHING);
+		Expr exp = ExprZ();
 		if( exp != null && exp.isStmt ) {
 			Stmts stmt = new Stmts();
 			if( exp.valType==Val.SINGLE ) {
@@ -764,29 +747,29 @@
 
 	private Var SettableVar() throws ParseException {
 		int start = parser.begin();
-		Var var = VarZ(In.NOTHING);
+		Var var = VarZ();
 		if( var==null || !var.isSettable() )
 			return parser.failure(null);
 		return parser.success( var );
 	}
 
-	private Expr RequiredExpr(In in) throws ParseException {
+	private Expr RequiredExpr() throws ParseException {
 		parser.begin();
-		return parser.success(required(ExprZ(in),"Bad expression"));
+		return parser.success(required(ExprZ(),"Bad expression"));
 	}
 
-	private Expr ExprZ(In in) throws ParseException {
-		return OrExpr(in);
+	private Expr ExprZ() throws ParseException {
+		return OrExpr();
 	}
 
-	private Expr OrExpr(In in) throws ParseException {
+	private Expr OrExpr() throws ParseException {
 		parser.begin();
-		Expr exp = AndExpr(in);
+		Expr exp = AndExpr();
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("or") ) {
 			exp = exp.single();
-			Expr exp2 = required(AndExpr(in)).single();
+			Expr exp2 = required(AndExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,true);
 			newExp.add( "(LuanImpl.cnd(t = " );
 			newExp.addAll( exp );
@@ -798,14 +781,14 @@
 		return parser.success(exp);
 	}
 
-	private Expr AndExpr(In in) throws ParseException {
+	private Expr AndExpr() throws ParseException {
 		parser.begin();
-		Expr exp = RelExpr(in);
+		Expr exp = RelExpr();
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("and") ) {
 			exp = exp.single();
-			Expr exp2 = required(RelExpr(in)).single();
+			Expr exp2 = required(RelExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,true);
 			newExp.add( "(LuanImpl.cnd(t = " );
 			newExp.addAll( exp );
@@ -817,16 +800,16 @@
 		return parser.success(exp);
 	}
 
-	private Expr RelExpr(In in) throws ParseException {
+	private Expr RelExpr() throws ParseException {
 		parser.begin();
-		Expr exp = ConcatExpr(in);
+		Expr exp = ConcatExpr();
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match("==") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.eq(" );
 				newExp.addAll( exp );
@@ -837,7 +820,7 @@
 			} else if( parser.match("~=") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "!LuanImpl.eq(" );
 				newExp.addAll( exp );
@@ -848,7 +831,7 @@
 			} else if( parser.match("<=") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.le(" );
 				newExp.addAll( exp );
@@ -859,7 +842,7 @@
 			} else if( parser.match(">=") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.le(" );
 				newExp.addAll( exp2 );
@@ -870,7 +853,7 @@
 			} else if( parser.match("<") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.lt(" );
 				newExp.addAll( exp );
@@ -881,7 +864,7 @@
 			} else if( parser.match(">") ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(ConcatExpr(in)).single();
+				Expr exp2 = required(ConcatExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.lt(" );
 				newExp.addAll( exp2 );
@@ -895,15 +878,15 @@
 		return parser.success(exp);
 	}
 
-	private Expr ConcatExpr(In in) throws ParseException {
+	private Expr ConcatExpr() throws ParseException {
 		parser.begin();
-		Expr exp = SumExpr(in);
+		Expr exp = SumExpr();
 		if( exp==null )
 			return parser.failure(null);
 		if( parser.match("..") ) {
 			Spaces();
 			exp = exp.single();
-			Expr exp2 = required(ConcatExpr(in)).single();
+			Expr exp2 = required(ConcatExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "LuanImpl.concat(" );
 			newExp.addAll( exp );
@@ -915,16 +898,16 @@
 		return parser.success(exp);
 	}
 
-	private Expr SumExpr(In in) throws ParseException {
+	private Expr SumExpr() throws ParseException {
 		parser.begin();
-		Expr exp = TermExpr(in);
+		Expr exp = TermExpr();
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match('+') ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(TermExpr(in)).single();
+				Expr exp2 = required(TermExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.add(" );
 				newExp.addAll( exp );
@@ -935,7 +918,7 @@
 			} else if( Minus() ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(TermExpr(in)).single();
+				Expr exp2 = required(TermExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.sub(" );
 				newExp.addAll( exp );
@@ -954,16 +937,16 @@
 		return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure();
 	}
 
-	private Expr TermExpr(In in) throws ParseException {
+	private Expr TermExpr() throws ParseException {
 		parser.begin();
-		Expr exp = UnaryExpr(in);
+		Expr exp = UnaryExpr();
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match('*') ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(UnaryExpr(in)).single();
+				Expr exp2 = required(UnaryExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.mul(" );
 				newExp.addAll( exp );
@@ -974,7 +957,7 @@
 			} else if( parser.match('/') ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(UnaryExpr(in)).single();
+				Expr exp2 = required(UnaryExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.div(" );
 				newExp.addAll( exp );
@@ -985,7 +968,7 @@
 			} else if( Mod() ) {
 				Spaces();
 				exp = exp.single();
-				Expr exp2 = required(UnaryExpr(in)).single();
+				Expr exp2 = required(UnaryExpr()).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
 				newExp.add( "LuanImpl.mod(" );
 				newExp.addAll( exp );
@@ -1004,11 +987,11 @@
 		return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure();
 	}
 
-	private Expr UnaryExpr(In in) throws ParseException {
+	private Expr UnaryExpr() throws ParseException {
 		parser.begin();
 		if( parser.match('#') ) {
 			Spaces();
-			Expr exp = required(UnaryExpr(in)).single();
+			Expr exp = required(UnaryExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "LuanImpl.len(" );
 			newExp.addAll( exp );
@@ -1017,7 +1000,7 @@
 		}
 		if( Minus() ) {
 			Spaces();
-			Expr exp = required(UnaryExpr(in)).single();
+			Expr exp = required(UnaryExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "LuanImpl.unm(" );
 			newExp.addAll( exp );
@@ -1026,27 +1009,27 @@
 		}
 		if( Keyword("not") ) {
 			Spaces();
-			Expr exp = required(UnaryExpr(in)).single();
+			Expr exp = required(UnaryExpr()).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "!Luan.checkBoolean(" );
 			newExp.addAll( exp );
 			newExp.add( ")" );
 			return parser.success(newExp);
 		}
-		Expr exp = PowExpr(in);
+		Expr exp = PowExpr();
 		if( exp==null )
 			return parser.failure(null);
 		return parser.success(exp);
 	}
 
-	private Expr PowExpr(In in) throws ParseException {
+	private Expr PowExpr() throws ParseException {
 		parser.begin();
-		Expr exp1 = SingleExpr(in);
+		Expr exp1 = SingleExpr();
 		if( exp1==null )
 			return parser.failure(null);
 		if( parser.match('^') ) {
 			Spaces();
-			Expr exp2 = required(PowExpr(in));
+			Expr exp2 = required(PowExpr());
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "LuanImpl.pow(" );
 			newExp.addAll( exp1.single() );
@@ -1058,12 +1041,12 @@
 		return parser.success(exp1);
 	}
 
-	private Expr SingleExpr(In in) throws ParseException {
+	private Expr SingleExpr() throws ParseException {
 		parser.begin();
 		Expr exp = FunctionExpr();
 		if( exp != null )
 			return parser.success(exp);
-		exp = VarExp(in);
+		exp = VarExp();
 		if( exp != null )
 			return parser.success(exp);
 		exp = VarArgs();
@@ -1162,9 +1145,6 @@
 				Spaces();  lastExp.addNewLines();
 			}
 		} while( FieldSep() );
-		Expr exp = TemplateExpressions(In.NOTHING);
-		if( exp != null )
-			builder.add(exp);
 		if( !parser.match('}') )
 			throw parser.exception("Expected table element or '}'");
 		tblExp.addAll( expString(builder).array() );
@@ -1180,12 +1160,12 @@
 
 	private Expr Field() throws ParseException {
 		parser.begin();
-		Expr exp = SubExpr(In.NOTHING);
+		Expr exp = SubExpr();
 		if( exp==null )
 			exp = NameExpr();
 		if( exp!=null && parser.match('=') ) {
 			Spaces();
-			Expr val = RequiredExpr(In.NOTHING).single();
+			Expr val = RequiredExpr().single();
 			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.add( "new TableField(" );
 			newExp.addAll( exp );
@@ -1195,34 +1175,34 @@
 			return parser.success(newExp);
 		}
 		parser.rollback();
-		Expr exprs = ExprZ(In.NOTHING);
+		Expr exprs = ExprZ();
 		if( exprs != null ) {
 			return parser.success(exprs);
 		}
 		return parser.failure(null);
 	}
 
-	private Expr VarExp(In in) throws ParseException {
-		Var var = VarZ(in);
+	private Expr VarExp() throws ParseException {
+		Var var = VarZ();
 		return var==null ? null : var.exp();
 	}
 
-	private Var VarZ(In in) throws ParseException {
+	private Var VarZ() throws ParseException {
 		parser.begin();
-		Var var = VarStart(in);
+		Var var = VarStart();
 		if( var==null )
 			return parser.failure(null);
 		Var var2;
-		while( (var2=Var2(in,var.exp())) != null ) {
+		while( (var2=Var2(var.exp())) != null ) {
 			var = var2;
 		}
 		return parser.success(var);
 	}
 
-	private Var VarStart(In in) throws ParseException {
+	private Var VarStart() throws ParseException {
 		if( parser.match('(') ) {
 			Spaces();
-			Expr exp = RequiredExpr(in).single();
+			Expr exp = RequiredExpr().single();
 			RequiredMatch(')');
 			Spaces();
 			return exprVar(exp);
@@ -1240,9 +1220,9 @@
 		return null;
 	}
 
-	private Var Var2(In in,Expr exp1) throws ParseException {
+	private Var Var2(Expr exp1) throws ParseException {
 		parser.begin();
-		Expr exp2 = SubExpr(in);
+		Expr exp2 = SubExpr();
 		if( exp2 != null )
 			return parser.success(indexVar(exp1,exp2));
 		if( parser.match('.') ) {
@@ -1252,7 +1232,7 @@
 				return parser.success(indexVar(exp1,exp2));
 			return parser.failure(null);
 		}
-		Expr fnCall = Args( in, exp1, new ArrayList<Expr>() );
+		Expr fnCall = Args( exp1, new ArrayList<Expr>() );
 		if( fnCall != null )
 			return parser.success(exprVar(fnCall));
 		return parser.failure(null);
@@ -1363,18 +1343,18 @@
 		};
 	}
 
-	private Expr Args(In in,Expr fn,List<Expr> builder) throws ParseException {
+	private Expr Args(Expr fn,List<Expr> builder) throws ParseException {
 		parser.begin();
-		return args(in,builder)
+		return args(builder)
 			? parser.success( callExpStr( fn, expString(builder) ) )
 			: parser.failure((Expr)null);
 	}
 
-	private boolean args(In in,List<Expr> builder) throws ParseException {
+	private boolean args(List<Expr> builder) throws ParseException {
 		parser.begin();
 		if( parser.match('(') ) {
 			Spaces();
-			ExpList(in,builder);  // optional
+			ExpList(builder);  // optional
 			if( !parser.match(')') )
 				throw parser.exception("Expression or ')' expected");
 			Spaces();
@@ -1394,43 +1374,33 @@
 		return parser.failure();
 	}
 
-	private Expr ExpStringList(In in) throws ParseException {
+	private Expr ExpStringList() throws ParseException {
 		List<Expr> builder = new ArrayList<Expr>();
-		return ExpList(in,builder) ? expString(builder) : null;
+		return ExpList(builder) ? expString(builder) : null;
 	}
 
-	private boolean ExpList(In in,List<Expr> builder) throws ParseException {
+	private boolean ExpList(List<Expr> builder) throws ParseException {
 		parser.begin();
-		Expr exp = TemplateExpressions(in);
-		if( exp != null ) {
-			builder.add(exp);
-			return parser.success();
-		}
-		exp = ExprZ(in);
+		Expr exp = ExprZ();
 		if( exp==null )
 			return parser.failure();
 		exp.addNewLines();
 		builder.add(exp);
 		while( parser.match(',') ) {
 			Spaces();
-			exp = TemplateExpressions(in);
-			if( exp != null ) {
-				builder.add(exp);
-				return parser.success();
-			}
-			exp = RequiredExpr(in);
+			exp = RequiredExpr();
 			exp.prependNewLines();
 			builder.add(exp);
 		}
 		return parser.success();
 	}
 
-	private Expr SubExpr(In in) throws ParseException {
+	private Expr SubExpr() throws ParseException {
 		parser.begin();
 		if( !parser.match('[') || parser.test("[") || parser.test("=") )
 			return parser.failure(null);
 		Spaces();
-		Expr exp = RequiredExpr(In.NOTHING).single();
+		Expr exp = RequiredExpr().single();
 		RequiredMatch(']');
 		Spaces();
 		return parser.success(exp);
--- a/src/luan/modules/String.luan	Thu Aug 01 16:49:47 2019 -0600
+++ b/src/luan/modules/String.luan	Thu Aug 15 14:33:35 2019 -0600
@@ -5,7 +5,6 @@
 local String = {}
 
 String.char = StringLuan.char_
-String.concat = StringLuan.concat
 String.encode = StringLuan.encode
 String.find = StringLuan.find
 String.format = StringLuan.format
--- a/src/luan/modules/StringLuan.java	Thu Aug 01 16:49:47 2019 -0600
+++ b/src/luan/modules/StringLuan.java	Thu Aug 15 14:33:35 2019 -0600
@@ -208,14 +208,6 @@
 		return String.format(format,args);
 	}
 
-	public static String concat(Object... args) throws LuanException {
-		StringBuilder sb = new StringBuilder();
-		for( Object arg : args ) {
-			sb.append( Luan.luanToString(arg) );
-		}
-		return sb.toString();
-	}
-
 	public static String encode(String s) {
 		return Luan.stringEncode(s);
 	}
--- a/website/src/diff.html	Thu Aug 01 16:49:47 2019 -0600
+++ b/website/src/diff.html	Thu Aug 15 14:33:35 2019 -0600
@@ -58,7 +58,6 @@
 				<li><a href="#concatenation">Concatenation</a></li>
 				<li><a href="#constructors">Table Constructors</a></li>
 				<li><a href="#fn_calls">Function Calls</a></li>
-				<li><a href="#template_expr">Template Expressions</a></li>
 			</ul>
 		</li>
 	</ul>
@@ -209,9 +208,5 @@
 
 <p>Luan doesn't support <em>proper tail calls</em>.  Because Java doesn't support this cleanly, this was left out.</p>
 
-<h4 heading><a name="template_expr" href="#template_expr">Template Expressions</a></h4>
-
-<p>Template expressions are a Luan addition that don't exist in Lua.  See <a href="manual.html#template_expr">Template Expressions</a> in the Luan Reference Manual.</p>
-		
 </body>
 </html>
--- a/website/src/manual.html	Thu Aug 01 16:49:47 2019 -0600
+++ b/website/src/manual.html	Thu Aug 15 14:33:35 2019 -0600
@@ -70,7 +70,6 @@
 				<li><a href="#constructors">Table Constructors</a></li>
 				<li><a href="#fn_calls">Function Calls</a></li>
 				<li><a href="#fn_def">Function Definitions</a></li>
-				<li><a href="#template_expr">Template Expressions</a></li>
 			</ul>
 		</li>
 		<li><a href="#visibility">Visibility Rules</a></li>
@@ -1086,7 +1085,7 @@
 
 <h4 heading><a name="template_stmt" href="#template_stmt">Template Statements</a></h4>
 
-<p>Template statements are based on <a href="#template_expr">template exressions</a> and provide the full equivalent of <a href="http://en.wikipedia.org/wiki/JavaServer_Pages">JSP</a> but in a general way.  Template statements write the equivalent template exression to standard output.  For example:</p>
+<p>Template statements provide the full equivalent of <a href="http://en.wikipedia.org/wiki/JavaServer_Pages">JSP</a> but in a general way.  Template statements write to standard output.  For example:</p>
 
 <pre>
 	local name = "Bob"
@@ -1100,10 +1099,7 @@
 
 <pre>
 	local name = "Bob"
-	require("luan:Io.luan").stdout.write( %>
-	Hello <%= name %>!
-	Bye <%= name %>.
-	<% )
+	require("luan:Io.luan").stdout.write( "Hello ", name , "!\nBye ", name , ".\n" )
 </pre>
 
 
@@ -1664,26 +1660,6 @@
 then the function returns with no results.
 
 
-<h4 heading><a name="template_expr" href="#template_expr">Template Expressions</a></h4>
-
-<p>Luan template expression are based on <a href="http://en.wikipedia.org/wiki/JavaServer_Pages">JSP</a>.  Template expressions return multiple values.  Here is an example:</p>
-
-<pre>
-	local name = "Bob"
-	write( %>Hello <%= name %>!<% )
-</pre>
-
-<p>This is equivalent to the code:</p>
-
-<pre>
-	local name = "Bob"
-	write( "Hello ", name, "!" )
-</pre>
-
-<p>The strings in template expressions may be multiple lines.</p>
-
-
-
 <h3 heading><a name="visibility" href="#visibility">Visibility Rules</a></h3>
 
 <p>
@@ -2280,13 +2256,6 @@
 to its corresponding argument.
 
 
-<h4 heading><a name="String.concat" href="#String.concat"><code>String.concat (&middot;&middot;&middot;)</code></a></h4>
-
-<p>
-Concatenates the <a href="#Luan.to_string"><code>to_string</code></a> value of all arguments.
-
-
-
 <h4 heading><a name="String.encode" href="#String.encode"><code>String.encode (s)</code></a></h4>
 
 <p>