diff --git a/Makefile b/Makefile index c9bd28a..4a2d6c6 100644 --- a/Makefile +++ b/Makefile @@ -11,17 +11,17 @@ _make_a1_: web: _make_vm_ mkdir -p _tmp_ - set -x; javac -source 1.6 -target 1.6 -warn:none \ + set -x; javac -source 1.6 -target 1.6 -nowarn \ -g \ -cp $(JUNIT):$(JARS) \ -d _tmp_ \ terse-vm/src/terse/vm/*.java\ terse-web/src/terse/web/WebServer.java touch w_web.txt - java -cp _tmp_:$(JUNIT) terse.web.WebServer 8080 + java -ea -cp _tmp_:$(JUNIT) terse.web.WebServer 8080 reweb: _make_vm_ - java -cp _tmp_:$(JUNIT) terse.web.WebServer 8080 + java -ea -cp _tmp_:$(JUNIT) terse.web.WebServer 8080 reweb1: _make_vm_ java -cp _tmp_:$(JUNIT) terse.web.WebServer 8081 diff --git a/prelude.txt b/prelude.txt index 46d7c9a..a3dd26d 100644 --- a/prelude.txt +++ b/prelude.txt @@ -2966,7 +2966,9 @@ meth ADozenYaksApp value IF( path len == 2 )THEN( me verbSelf. )ELSE( - me apply: 'verb[ path z]' args: (). + method= ('verb', path z)jam. + me apply: method args: (). + "me apply: 'verb[ path z]' args: ()." ) ). meth ADozenYaksApp link:cmd:q: @@ -2994,7 +2996,8 @@ meth ADozenYaksApp verbTop TAG('input'; 'type', 'submit'; 'value', 'Create'); - ) ); + ); + ); ) @@ -3039,7 +3042,7 @@ meth ADozenYaksApp verbSelf FOR(f: self friends) MAP(f dhmut str head: 8) join: ', '; TAG('p'); Ht dl: FOR(f: self friends) MAP( - HT(' *'; me link: f who cmd: 'FriendChan' q: DICT('fwho': f who); '* ') + HT(' *'; me link: f who cmd: 'FriendChan' q: DICT('fwho', f who;); '* ') ); ) ). @@ -3318,10 +3321,12 @@ meth HtCls ul: meth HtCls dl: "Defintion List." - HT(TAG('dl', HT(FOR( k,v:a )MAP( HT( - TAG('dt', HT(k,)); - TAG('dd', HT(v,)); - ))))) + HT(TAG('dl', HT( + FOR( k,v:a )MAP( HT( + TAG('dt'; HT(k;);); + TAG('dd'; HT(v;);); + )) + ))) ##END diff --git a/terse-a1/src/terse/a1/TerseActivity.java b/terse-a1/src/terse/a1/TerseActivity.java index 1f3f37b..35e70fd 100644 --- a/terse-a1/src/terse/a1/TerseActivity.java +++ b/terse-a1/src/terse/a1/TerseActivity.java @@ -708,9 +708,9 @@ public class TerseActivity extends Activity { String[] words = ((Str) pair.vec.get(0)).str .split("\\|"); Log.i("TT-WORDS", - terp.arrayToString(words)); + terp.show(words)); toast_text += "\n\n" - + Static.arrayToString(words); + + Static.show(words); if (words[1].equals("link")) { Uri uri = new Uri.Builder() .scheme("terse") diff --git a/terse-vm/src/terse/vm/Expr.java b/terse-vm/src/terse/vm/Expr.java index 62e7ef7..49a8876 100644 --- a/terse-vm/src/terse/vm/Expr.java +++ b/terse-vm/src/terse/vm/Expr.java @@ -53,6 +53,10 @@ public abstract class Expr extends Obj { this.rest = rest; return this; } + + final String substr() { + return front.substring(0, front.length() - rest.length()); + } /** Does it need parens around it, in toString()? */ boolean isComplicated() { @@ -634,16 +638,18 @@ public abstract class Expr extends Obj { } if (r.cls.trace || m.trace) { say("Sending message <%s> to <%s#%s> with <%s>", m.name, - r.cls.cname, r.toString(), arrayToString(args)); + r.cls.cname, r.toString(), show(args)); } Ur z = null; try { z = m.apply(f, r, a); } catch (RuntimeException ex) { String what = fmt( - "\n * During SEND <%s %s> TO <%s#%s> WITH %s", - r.cls.cname, m.name, r.cls.cname, r.toString(), - arrayToString(a)); + "\n * During SEND: <%s %s>\n * * TO: %s«%s»", + r.cls.cname, m.name, r.cls.cname, r.toString()); + for (Ur u : a) { + what += "\n * * * ARG: " + u.cls.cname + "«" + u + "»"; + } retoss("%s", ex.toString() + what); } if (r.cls.trace || m.trace) { @@ -716,8 +722,8 @@ public abstract class Expr extends Obj { terp().say("<><><>"); String[] words = msg.split(":"); - terp().say("msg words:", arrayToString(words)); - terp().say("locations:", arrayToString(this.sourceLoc)); + terp().say("msg words:", show(words)); + terp().say("locations:", show(this.sourceLoc)); for (int i = 0; i < words.length; i++) { if (words[i].length() > 0 && this.sourceLoc[i] >= 0) { terp().say("[%d] '%s' @%s >>====>>", i, words[i], sourceLoc[i]); diff --git a/terse-vm/src/terse/vm/Parser.java b/terse-vm/src/terse/vm/Parser.java index 2bd56a0..c6a2da6 100644 --- a/terse-vm/src/terse/vm/Parser.java +++ b/terse-vm/src/terse/vm/Parser.java @@ -33,6 +33,7 @@ import terse.vm.Expr.Send; import terse.vm.Ur.Obj; // BUG: (x-2,y-2) parses very wrong. "-2" gets detected, and "." gets inserted. +// «%s» public class Parser extends Obj { // =cls "meth" Parser Obj @@ -53,6 +54,7 @@ public class Parser extends Obj { // This is the public function to parse a string. public static Expr.MethTop parseMethod(Cls onCls, String methName, String code) { Terp terp = onCls.terp; + terp.say("START PARSE CLS %s METH %s\nCODE «%s»\n", onCls, methName, code); Parser p = new Parser(onCls, methName, code); int numArgs = 0; if (isAlphaMessage(methName)) { @@ -70,16 +72,18 @@ public class Parser extends Obj { p.localVarSpelling.put("a", "a"); numArgs = 1; } + Expr expr1 = null; try { - p.parseExpr(); // Once to learn names of variables. + expr1 = p.parseExpr(); // Once to learn names of variables. } catch (Exception ex) { ex.printStackTrace(); terp.toss("ERROR DURING PARSING: <%s>\nWHILE PARSING THIS SOURCE [len=%d]:\n`%s`\nUNPARSED REMAINDER [len=%d]:\n`%s`\n", show(ex), p.lex.front.length(), p.lex.front, p.lex.rest.length(), p.lex.rest); } + terp.say("Parsed: %s", expr1); if (p.lex.w.trim().length() > 0) { - terp.toss("Parser: Leftover word after parsing: <%s>", - p.lex.w.trim()); + terp.toss("Parser: Leftover word after parsing: <<<%s>>> Leftover junk: <<<%s>>>", + p.lex.w.trim(), p.lex.rest.trim()); } if (p.lex.rest.trim().length() > 0) { terp.toss("Parser: Leftover junk after parsing: <%s>", @@ -167,7 +171,7 @@ public class Parser extends Obj { for (String k : c.myVarNames) { Integer i = onCls.allVarMap.get(k); if (i == null) { - terp.toss("allVarMap.get(%s) is NULL: onCls=%s cls=%s allVarMap=%s", onCls, c, Static.arrayToString(c.myVarNames)); + terp.toss("allVarMap.get(%s) is NULL: onCls=%s cls=%s allVarMap=%s", onCls, c, Static.show(c.myVarNames)); } //say("PARSER PUTTING VAR %s", k); this.instVars.put(k.toLowerCase(), i); @@ -236,10 +240,15 @@ public class Parser extends Obj { Expr z = new Expr.PutLValue(lvalue, rhs); z.front = front; z.white = white; z.rest = lex.rest; + say("GOT ASN STMT: «%s»", z.substr()); + say("GOT ASN STMT: «%s»", z); return z; } lex.recallState(); - return parseList(); + Expr z = parseList(); + say("GOT STMT: «%s»", z.substr()); + say("GOT STMT: «%s»", z); + return z; } // When a variable is assigned, it must be either Inst or Local. @@ -348,7 +357,9 @@ public class Parser extends Obj { keywords += lex.keywordName().toLowerCase() + ":"; locs = append(locs, lex.frontLocation()); lex.advance(); - assert lex.w.charAt(0) == ':'; + if (lex.w.charAt(0) != ':') { + toss("Expected : but got %s REST=%s", lex.w, lex.rest); + } lex.advance(); Expr unary = parseUnary(); Expr tuple = parseBinary3(unary); @@ -477,7 +488,7 @@ public class Parser extends Obj { private Expr interpolateLiteralString(String a) { -// say("Interpolate <<< %s", a); + say("Interpolate oncls=%s <<< «%s»", onCls, a); try { final int n = a.length(); Expr[] list = exprs(); @@ -492,19 +503,20 @@ public class Parser extends Obj { continue; } else if (i + 2 < n && a.charAt(i) == '[' && a.charAt(i + 1) != '[') { - // We spotted single (, look for closing ) + // We spotted single [, look for closing ] Expr found = null; int nested = 0; int j = i + 1; for (; j < n; j++) { if (a.charAt(j) == ']' && nested == 0) { - String bodyStr = a.substring(i, j); + String bodyStr = a.substring(i+1, j); // Put the current parser state on hold, // and compile the bodyStr as a Block. // Enclose it in parens, so it looks like a block. // Set found to an expression that evaluates the block. TLex onHold = lex; lex = new TLex(terp, "(" + bodyStr + ")"); + terp.say("PARSE INTERPOLATED BLOCK ON CLS %s\nCODE «%s»\n", onCls, bodyStr); Expr block = parseBlock(); // Remember parseblock() was the exception that advanced past closing ')'. if (lex.rest.length() != 0) { @@ -564,7 +576,7 @@ public class Parser extends Obj { z = new Expr.Send(mkVec, "jam", terp.emptyExprs, ints(lex.frontLocation())); } -// say("Interpolate >>> %s", z); + say("Interpolate >>> «%s»", z); return z; } catch (RuntimeException ex) { ex.printStackTrace(); @@ -647,7 +659,9 @@ public class Parser extends Obj { } private Expr parseBlock() { - assert lex.opensParen(); + if (!lex.opensParen()) { + toss("Expected opensParen but got %s REST=%s", lex.w, lex.rest); + } lex.advance(); Expr[] params = exprs(); @@ -664,16 +678,18 @@ public class Parser extends Obj { } } Expr body = parseExpr(); - assert lex.closesParen() : fmt( - "lex=%s<%s> body=<%s>", lex.t, lex.w, body);// Do not advance; - // parsePrim() does - // that after - // switch(). - return new Expr.Block(body, params); + if (!lex.closesParen()) { + toss("parseBlock: Expected closesParen but got %s\nPARAMS=%s\nBODY=%s\nREST=%s", lex.w, show(params), body, lex.rest); + } + Expr z = new Expr.Block(body, params); + say("GOT BLOCK: «%s»", z); + return z; } private Expr parseParen() { - assert lex.opensParen(); + if (!lex.opensParen()) { + toss("Expected opensParen but got %s REST=%s", lex.w, lex.rest); + } lex.advance(); if (lex.closesParen()) { // The unit tuple (). It's an empty but mutable vector, not a @@ -681,7 +697,9 @@ public class Parser extends Obj { return new Expr.MakeVec(terp, emptyExprs, ','); } Expr body = parseExpr(); - assert lex.closesParen(); + if (!lex.closesParen()) { + toss("Expected closesParen but got %s REST=%s", lex.w, lex.rest); + } // Do not advance; parsePrim() does that after switch(). return body; } @@ -692,12 +710,19 @@ public class Parser extends Obj { int[] locs = ints(-1); // "macro:" is implicit, thus -1. while (lex.t == Pat.NAME && lex.isMacro()) { names.add(lex.w); + terp().say("parseMacro: building %s", show(names)); locs = append(locs, lex.frontLocation()); lex.advance(); - assert lex.opensParen(); + if (!lex.opensParen()) { + terp().toss("Expected Open Paren after Macro Word %s but token is %s and REST=«%s»", show(names), lex.w, lex.rest); + } + terp().say("parseMacro: Sitting on Open Paren, REST=«%s»", lex.rest); Expr.Block b = (Expr.Block) parseBlock(); blocks.add(b); - assert lex.closesParen(); + if (!lex.closesParen()) { + terp().toss("Expected Close Paren after Macro Word %s and EXPR=«%s»\n but token is %s and REST=«%s»", show(names), b, lex.w, lex.rest); + } + terp().say("parseMacro: Sitting on Close Paren, REST=«%s»", lex.rest); lex.advance(); } final int sz = names.size(); @@ -708,6 +733,7 @@ public class Parser extends Obj { message.append(':'); bb = append(bb, blocks.get(i)); } + terp().say("parseMacro: Finished , REST=«%s»", show(names), lex.rest); return new Expr.Send(new Expr.GetSelf(terp), message.toString(), bb, locs); } @@ -723,6 +749,8 @@ public class Parser extends Obj { } if (lex.w.equals(";")) { a = parseLvListOrNull(a); + if (a == null) + return null; } a.front = front; a.white = white; a.rest = lex.rest; @@ -1029,13 +1057,17 @@ public class Parser extends Obj { /** Name without the trailing colons or slashes. */ String keywordName() { - assert isKeyword(); + if (!isKeyword()) { + terp.toss("Expected keywordName but got Type %s Namely %s and REST=%s", this.t, this.w, this.rest); + } return w; } /** Look ahead at the next token, to distinguish MACRO. */ boolean isMacro() { - assert (t == Pat.NAME); + if (t != Pat.NAME) { + terp.toss("Expected Type NAME but got Type %s Namely %s and REST=%s", this.t, this.w, this.rest); + } storeState(); advance(); boolean z = opensParen(); diff --git a/terse-vm/src/terse/vm/Static.java b/terse-vm/src/terse/vm/Static.java index c532d68..14f00f2 100644 --- a/terse-vm/src/terse/vm/Static.java +++ b/terse-vm/src/terse/vm/Static.java @@ -29,6 +29,7 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; @@ -55,7 +56,12 @@ public class Static { } public static String fmt(String s, Object... objects) { - return String.format(s, objects); + try { + return String.format(s, objects); + } catch (Exception ex) { + ex.printStackTrace(); + return "EXCEPTION " + ex + " DURING FORMAT " + s; + } } public static String GetStackTrace(final Throwable e) { @@ -88,7 +94,7 @@ public class Static { return sb.toString(); } - public static String arrayToString(Expr[] a) { + public static String show(Expr[] a) { StringBuilder z = new StringBuilder("["); for (Expr e : a) { z.append(fmt("%s, ", e.toString())); @@ -97,7 +103,7 @@ public class Static { return z.toString(); } - public static String arrayToString(Ur[] a) { + public static String show(Ur[] a) { StringBuilder z = new StringBuilder("["); for (Ur e : a) { z.append(fmt("%s, ", e.toString())); @@ -106,7 +112,7 @@ public class Static { return z.toString(); } - public static String arrayToString(String[] a) { + public static String show(String[] a) { if (a == null) return ""; StringBuilder z = new StringBuilder("["); @@ -117,7 +123,7 @@ public class Static { return z.toString(); } - public static String arrayToString(int[] a) { + public static String show(int[] a) { if (a == null) return ""; StringBuilder z = new StringBuilder(); @@ -948,4 +954,13 @@ public class Static { t.printStackTrace(out); return stringWriter.toString(); } + + public static String show(ArrayList names) { + StringBuilder sb = new StringBuilder("["); + for (String s : names) { + sb.append("«" + s + "», "); + } + sb.append("]"); + return sb.toString(); + } } diff --git a/terse-vm/src/terse/vm/Terp.java b/terse-vm/src/terse/vm/Terp.java index 1b52ae0..083a12e 100644 --- a/terse-vm/src/terse/vm/Terp.java +++ b/terse-vm/src/terse/vm/Terp.java @@ -366,11 +366,11 @@ public abstract class Terp extends Static { z.dict.put(v.vec.get(0), v.vec.get(1)); } else { toss("To initialize assoc in Dict, expected Vec of length 2, but got <%s#%d#%s>; inside <%s>", - v.cls, v.vec.size(), v, arrayToString(arr)); + v.cls, v.vec.size(), v, show(arr)); } } else { toss("To initialize assoc in Dict, expected Vec of length 2, but got <%s#%s>; inside <%s>", - arr[i].cls, arr[i], arrayToString(arr)); + arr[i].cls, arr[i], show(arr)); } } return z; @@ -978,21 +978,20 @@ public abstract class Terp extends Static { this.msg = "?????"; this.args = args; - String[] argstrs = new String[args.length]; + System.err.println("TerseBaseException: " + format); for (int i = 0; i < args.length; i++) { try { - argstrs[i] = fmt("<%s:%s>", args[i].getClass().getName(), - args[i].toString()); + System.err.println(fmt(" EXC ARG %s«%s»", args[i].getClass().getName(), + args[i].toString())); } catch (RuntimeException _) { - argstrs[i] = "???"; } } - this.msg = fmt(format, (Object[]) /*argstrs*/ args); + this.msg = fmt(format, args); } @Override public String toString() { - return fmt(msg, args); + return msg; } } private class TerseException extends TerseBaseException { diff --git a/terse-web/src/terse/web/WebServer.java b/terse-web/src/terse/web/WebServer.java index bd7f3a9..43bbda0 100644 --- a/terse-web/src/terse/web/WebServer.java +++ b/terse-web/src/terse/web/WebServer.java @@ -552,7 +552,7 @@ public class WebServer extends Static { if (args.length > 0) { port = Integer.parseInt(args[0]); } - System.err.format("Args are %s\n", Static.arrayToString(args)); + System.err.format("Args are %s\n", Static.show(args)); System.err.format("Binding to port %d\n", port); HttpServer server = HttpServer.create(new InetSocketAddress(port), 20); server.createContext("/favicon.ico", new FavIconHandler());