Author: ptw
Date: 2007-09-05 05:53:39 -0700 (Wed, 05 Sep 2007)
New Revision: 6361

Modified:
   openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/compiler/LzRuntime.lzs
   openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzBacktrace.lzs
   openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzMessage.lzs
   
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/dhtml/LzDebug.js
   
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/swf/LzDebug.as
   
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
   
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
   
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
Log:
Change 20070903-ptw-a by [EMAIL PROTECTED] on 2007-09-03 18:01:48 EDT
    in /Users/ptw/OpenLaszlo/wafflecone-2
    for http://svn.openlaszlo.org/openlaszlo/branches/wafflecone

Summary: Add file/line information to backtraces

Bugs Fixed:
LPP-4549 'runtime warnings should include file references, line #s'

Technical Reviewer: max (Message-ID: <[EMAIL PROTECTED]>), [EMAIL PROTECTED] 
(pending)
QA Reviewer: ewinard (pending)

Details:
    LzMessage: Get file/line information from backtrace if available,
    tweak format of locationString.

    LzDebug.*: correct padding computation for computeSlotDescription.

    LzDebug.js: _dbg_name takes precedence over runtime function name.

    LzBacktrace, LzRuntime: Move backtraceStack creation to runtime so it is
    available as early as needed.

    LzBacktrace:  Add __LzStackFrame.isUserFrame,
    .filename, .lineno.  Update _dbg_name to display file and line
    information.  Add LzBacktrace.userStackFrame to get first non-LFC
    frame from a backtrace.

    Compiler: Correct precedence computations for unparser, ensure
    parens are added in all the appropriate places.  Needed to handle
    expression-lists that backtrace annotation inserts.

    JavascriptGenerator, CodeGenerator: Copy location info when
    re-writing functions.  Note line numbers of call sites for
    backtrace.  Note file and line on functions for backtraces.

Tests:
    smokecheck with backtrace on shows file/line information in debug
    messages and in backtraces.



Modified: openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/compiler/LzRuntime.lzs
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/compiler/LzRuntime.lzs       
2007-09-05 05:18:10 UTC (rev 6360)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/compiler/LzRuntime.lzs       
2007-09-05 12:53:39 UTC (rev 6361)
@@ -189,6 +189,15 @@
     */
   var Debug = new Object;
 
+  /** Backtrace stack
+    * @access private
+    */
+  Debug.backtraceStack = new Array();
+  /** Max depth allowed
+    * @access private
+    */
+  Debug.backtraceStack.maxDepth = 100;
+
   /**
     * Doc'd on real definition
     * Bootstrap version

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzBacktrace.lzs
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzBacktrace.lzs     
2007-09-05 05:18:10 UTC (rev 6360)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzBacktrace.lzs     
2007-09-05 12:53:39 UTC (rev 6361)
@@ -12,16 +12,10 @@
   */
 
 // Support for backtraces in the debugger
+// -- Declared in LzRuntime
+// Debug.backtraceStack = new Array();
+// Debug.backtraceStack.maxDepth = 100;
 
-/** Backtrace stack
-  * @access private
-  */
-Debug.backtraceStack = new Array();
-/** Max depth allowed
-  * @access private
-  */
-Debug.backtraceStack.maxDepth = 100;
-
 {
 #pragma "debugBacktrace=false"
   /** @access private */
@@ -59,17 +53,45 @@
 var __LzStackFrame = function (args) {
   if (args instanceof Array) {
     this['this'] = args['this'];
-    this['function'] = args['callee'];
+    this['function'] = args.callee;
+    this.__lineno = ('lineno' in args) ? args.lineno : 
this['function']._dbg_lineno;
   }
   this.arguments = args;
 }
 
 /**
+ * Is this a user stack frame?
+ * @access private
+ */
+  __LzStackFrame.prototype.isUserFrame = function () {
+    return this['function']._dbg_filename.indexOf('lfc') != 0;
+  }
+
+/**
+ * Filename associated with a stack frame
+ * @access private
+ */
+  __LzStackFrame.prototype.filename = function () {
+    return this['function']._dbg_filename;
+  }
+
+/**
+ * Lineno associated with a stack frame
+ * @access private
+ */
+  __LzStackFrame.prototype.lineno = function () {
+    return this.__lineno;
+  }
+
+/**
   * Debug printer
   * @access private
   */
 __LzStackFrame.prototype._dbg_name = function () {
-  return Debug.formatToString('%0.72w.apply(%w, %w)', this['function'], 
this['this'], this.arguments);
+  var callee = this['function'];
+  var filename = callee._dbg_filename;
+  var lineno = this.__lineno;
+  return Debug.formatToString('%0.64w @%s#%d', callee, filename, lineno);
 }
 
 /**
@@ -98,8 +120,9 @@
   for (var i = 0; i < l; i++) {
     var fr = bs[i];
     // Reuse stack frames so they are unique
-    if (! fr.hasOwnProperty('__LzStackFrame')) {
-#pragma "passThrough=true"
+    if ((! fr.hasOwnProperty('__LzStackFrame')) ||
+        // Bad modularity
+        (fr.lineno != fr.__LzStackFrame.__lineno)) {
       fr.__LzStackFrame = new __LzStackFrame(fr);
     }
     this[i] = fr.__LzStackFrame;
@@ -113,6 +136,19 @@
 // LzBacktrace.prototype.constructor = LzBacktrace;
 
 /**
+ * Find the topmost user stack frame
+ * @access private
+ */
+  LzBacktrace.prototype.userStackFrame = function () {
+    for (var i = this.length - 1; i >= 0; i--) {
+      var fr = this[i];
+      if (fr.isUserFrame()) {
+        return fr;
+      }
+    }
+  }
+
+/**
   * Convert a backtrace to a string
   * @param printer:Function the function to print the backtrace
   * functions with.  Defaults to Debug.__String
@@ -157,6 +193,12 @@
 }
 
 /**
+  * Debug printer
+  * @access private
+  */
+LzBacktrace.prototype._dbg_typename = "Backtrace";
+
+/**
   * Snapshot the current call stack into a LzBacktrace object which
   * can be printed or inspected
   * 

Modified: openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzMessage.lzs
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzMessage.lzs       
2007-09-05 05:18:10 UTC (rev 6360)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/LzMessage.lzs       
2007-09-05 12:53:39 UTC (rev 6361)
@@ -14,10 +14,16 @@
 
 /**
   * A message is a string with annotations for the objects represented.
+  *
+  * This replaces the bootstrap LzMessage class in
+  * compiler/LzFormatter
+  *
   * @param String message: initial message
   * @access private
+  *
+  * @devnote TODO: [2007-09-05 ptw] Convert to class declaration
   */
-var LzMessage = function (message) {
+var LzMessage = function LzMessage (message) {
   // A Message would like to be a subclass of string, but mutable
   // TODO: [2006-04-11 ptw] Make this a real class
   this.constructor = arguments.callee;
@@ -255,7 +261,7 @@
   * @seealso LzSourceMessage.format
   * @access private
   */
-var LzSourceMessage = function (file, line, message) {
+function LzSourceMessage (file, line, message) {
   switch (arguments.length) {
     case 0:
     file = null;
@@ -264,13 +270,6 @@
     case 2:
     message = '';
   }
-  this.file = file;
-  this.line = line;
-  if (message instanceof LzMessage) {
-    this.message = message;
-  } else {
-    this.message = new LzMessage(message);
-  }
   // Append a backtrace if there is one -- skip back to the
   // $reportSourceWarning or warnInternal frames.
   if ('backtraceStack' in Debug) {
@@ -288,12 +287,25 @@
     }
     if (Debug.backtraceStack.length > skip) {
       this.backtrace = Debug.backtrace(skip);
+      // Heuristicate file/line from backtrace if available
+      if (file == null && this.backtrace) {
+        var top = this.backtrace.userStackFrame();
+        if (top) {
+          file = top.filename();
+          line = top.lineno();
+        }
+      }
     }
   }
+  this.file = file;
+  this.line = line;
+  if (message instanceof LzMessage) {
+    this.message = message;
+  } else {
+    this.message = new LzMessage(message);
+  }
 }
 
-/* Correct constructor */
-LzSourceMessage.prototype.constructor = LzSourceMessage;
 LzSourceMessage.prototype.type = '';
 LzSourceMessage.prototype.color = '#000000';
 
@@ -343,17 +355,16 @@
  * Get the location as a string
  */
 LzSourceMessage.prototype.locationString = function () {
-  var str = this.type + ':';
+  var str = this.type;
   if (this.file) {
-    str += ' ';
+    str += ' @';
     str += this.file;
-    str += ':';
     if (this.line) {
+      str += '#';
       str += this.line;
-      str += ':';
     }
   }
-  str += ' ';
+  str += ': ';
   return str;
 }
 
@@ -407,7 +418,7 @@
   * An Warn is a sourceMessage with the tag 'WARN'
   * @access private
   */
-var LzWarning = function(file, line, message) {
+function LzWarning (file, line, message) {
   // super.apply(arguments);
   LzSourceMessage.apply(this, arguments);
 }
@@ -423,7 +434,7 @@
   * An Error is a sourceMessage with the tag 'ERROR'
   * @access private
   */
-var LzError = function(file, line, message) {
+function LzError (file, line, message) {
   // super.apply(arguments);
   LzSourceMessage.apply(this, arguments);
 }
@@ -438,7 +449,7 @@
   * An Info is a sourceMessage with the tag 'INFO'
   * @access private
   */
-var LzInfo = function(file, line, message) {
+function LzInfo (file, line, message) {
   // super.apply(arguments);
   LzSourceMessage.apply(this, arguments);
 }
@@ -453,7 +464,7 @@
   * An Debug is a sourceMessage with the tag 'DEBUG'
   * @access private
   */
-var LzDebug = function(file, line, message) {
+function LzDebug (file, line, message) {
   // super.apply(arguments);
   LzSourceMessage.apply(this, arguments);
 }

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/dhtml/LzDebug.js
===================================================================
--- 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/dhtml/LzDebug.js
   2007-09-05 05:18:10 UTC (rev 6360)
+++ 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/dhtml/LzDebug.js
   2007-09-05 12:53:39 UTC (rev 6361)
@@ -94,13 +94,16 @@
  */
 Debug.functionName = function (fn, mustBeUnique) {
   if (fn && (fn instanceof Function)) {
-    // tip o' the pin to osteele.com
-    var fstring = fn.toString();
-    var m = fstring.match(this.functionNamePattern);
-    if (m) {
-      var n = m[1];
-    } else if (fn.hasOwnProperty('_dbg_name')) {
+    // _dbg_name takes precedence over the actual function name
+    if (fn.hasOwnProperty('_dbg_name')) {
       var n = fn._dbg_name;
+    } else {
+      // tip o' the pin to osteele.com
+      var fstring = fn.toString();
+      var m = fstring.match(this.functionNamePattern);
+      if (m) {
+        var n = m[1];
+      }
     }
     if (n) {
       if ((! mustBeUnique) || (fn === global[n])) {
@@ -550,6 +553,7 @@
  */
 Debug.computeSlotDescription = function (obj, key, val, wid) {
   var r = key + ':';
+  wid++;
   try {
     // Annotate 'weight' if available
     if (this.markGeneration > 0) {

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/swf/LzDebug.as
===================================================================
--- 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/swf/LzDebug.as 
    2007-09-05 05:18:10 UTC (rev 6360)
+++ 
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/debugger/platform/swf/LzDebug.as 
    2007-09-05 12:53:39 UTC (rev 6361)
@@ -614,6 +614,7 @@
   */
 Debug.computeSlotDescription = function (obj, key, val, wid) {
   var r = key + ':';
+  wid++;
   // Annotate 'weight' if available
   if (this.markGeneration > 0) {
     var annotation = this.annotation;

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
===================================================================
--- 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
  2007-09-05 05:18:10 UTC (rev 6360)
+++ 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
  2007-09-05 12:53:39 UTC (rev 6361)
@@ -831,6 +831,7 @@
           assert c.length == 3;
           p.add(c[0]);
           SimpleNode funexpr = new ASTFunctionExpression(0);
+          funexpr.setBeginLocation(n.filename, n.beginLine, n.beginColumn);
           funexpr.setChildren(c);
           p.add(funexpr);
         } else if (n instanceof ASTVariableStatement) {
@@ -2028,6 +2029,22 @@
       }
     }
 
+    // Note current call-site in a function context and backtracing
+    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
+        (context.findFunctionContext() != null)) {
+      Map registers = (Map)context.get(TranslationContext.REGISTERS);
+      // We know arguments register will exist if we are doing
+      // bactraces because it will be referenced in the function
+      // prefix.
+      if (registers != null && registers.containsKey("arguments")) {
+        
collector.push(Values.Register(((Instructions.Register)registers.get("arguments")).regno));
+        collector.push("lineno");
+        collector.push(node.beginLine);
+        collector.emit(Instructions.SetMember);
+      }
+    }
+
+    // Okay, it is not going to be transformed.  Just do it!
     visitCallParameters(node, isReferenced, args);
     boolean isref = translateReferenceForCall(fnexpr, true, node);
     if (isref) {
@@ -2293,6 +2310,7 @@
     return true;
   }
 
+  // useName => declaration not expression
   void translateFunction(SimpleNode node, boolean useName, SimpleNode[] 
children) {
     // label for profiling return
     String label = newLabel(node);
@@ -2329,6 +2347,7 @@
   }
 
   // Internal helper function for above
+  // useName => declaration not expression
   SimpleNode translateFunctionInternal(SimpleNode node, boolean useName, 
SimpleNode[] children) {
     // ast can be any of:
     //   FunctionDefinition(name, args, body)
@@ -2757,6 +2776,30 @@
       collector.push("name");
       collector.push(userFunctionName);
       collector.emit(Instructions.SetMember);
+      if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
+        // TODO: [2007-09-04 ptw] Come up with a better way to
+        // distinguish LFC from user stack frames.  See
+        // lfc/debugger/LzBactrace
+        String fn = (options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) 
? "lfc/" : "") + filename;
+        if (functionName != null) {
+          collector.push(functionName);
+          collector.emit(Instructions.GetVariable);
+        } else {
+          collector.emit(Instructions.DUP);
+        }
+        collector.push("_dbg_filename");
+        collector.push(fn);
+        collector.emit(Instructions.SetMember);
+        if (functionName != null) {
+          collector.push(functionName);
+          collector.emit(Instructions.GetVariable);
+        } else {
+          collector.emit(Instructions.DUP);
+        }
+        collector.push("_dbg_lineno");
+        collector.push(lineno);
+        collector.emit(Instructions.SetMember);
+      }
     }
     if (options.getBoolean(Compiler.CONSTRAINT_FUNCTION)) {
 //       assert (functionName != null);

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
===================================================================
--- 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
       2007-09-05 05:18:10 UTC (rev 6360)
+++ 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
       2007-09-05 12:53:39 UTC (rev 6361)
@@ -1035,6 +1035,9 @@
       // TODO: [2005-11-17 ptw] Not quite right, but javacc doesn't
       // tell us the range of its Ops
       for (int i = 0; i < 256; i++) { on.add("<" + Integer.toString(i) + ">"); 
}
+      on.set(Ops.LPAREN, "(");
+      on.set(Ops.LBRACKET, "[");
+      on.set(Ops.DOT, ".");
       on.set(Ops.ASSIGN, "=");
       on.set(Ops.COMMA, ",");
       on.set(Ops.GT, ">");
@@ -1088,22 +1091,14 @@
 
     public String visitAssignmentExpression(SimpleNode node, String[] 
children) {
       int thisPrec = prec(((ASTOperator)node.get(1)).getOperator(), false);
-      for (int i = 1; i < children.length; i += 2) {
-        children[i] = maybeAddParens(thisPrec, node.get(i), children[i]);
-      }
+      assert children.length == 3;
+      children[2] = maybeAddParens(thisPrec, node.get(2), children[2], true);
       return children[0] + SPACE + children[1] + delimit(children [2], false);
     }
     public String visitCallExpression(SimpleNode node, String[] children) {
-      SimpleNode c = node.get(0);
-      // Only needed because our parser is broken
-      if (c instanceof ASTFunctionExpression) {
-        return "(" + children[0] + ")(" + children[1] + ")";
-      } else {
-        // CallExpression is prec 0, even though it has no operator
-        // but associativity means you don't need parens
-//         children[0] = maybeAddParens(0, c, children[0])
-        return children[0] + "(" + children[1] + ")";
-      }
+      int thisPrec = prec(Ops.LPAREN, true);
+      children[0] = maybeAddParens(thisPrec, node.get(0), children[0], true);
+      return children[0] + "(" + children[1] + ")";
     }
     public String visitSuperCallExpression(SimpleNode node, String[] children) 
{
       // Same as above
@@ -1111,7 +1106,7 @@
     }
     public String visitConditionalExpression(SimpleNode node, String[] 
children) {
       int thisPrec = prec(Ops.COLON, false);
-      for (int i = 1; i < children.length; i++) {
+      for (int i = 0; i < children.length; i++) {
         children[i] = maybeAddParens(thisPrec, node.get(i), children[i]);
       }
       return children[0] + CONDITIONAL + children[1] + ALTERNATIVE + 
children[2];
@@ -1218,7 +1213,7 @@
     public int prec(int op, boolean unary) {
       String n = OperatorNames[op];
       String classes[][] = {
-        {"()", "[]", ".", "new"},
+        {"(", "[", ".", "new"},
         {"!", "~", "-", "+", "--", "++", "typeof", "void", "delete"},
         {"*", "/", "%"},
         {"+", "-"},
@@ -1240,6 +1235,10 @@
     }
 
     public String visitArrayLiteral(SimpleNode node, String[] children) {
+      int thisPrec = prec(Ops.COMMA, false);
+      for (int i = 0; i < children.length; i++) {
+        children[i] = maybeAddParens(thisPrec, node.get(i), children[i], 
false);
+      }
       return "[" + join(COMMA, children) + "]";
     }
 
@@ -1247,6 +1246,12 @@
       return maybeAddParens(parentPrec, node, nodeRep, false);
     }
 
+    // Set assoc to true if the sub-expression appears in a place
+    // where operator associativity implies the parens, e.g. on the
+    // left operand of a binary operator that is left-to-right
+    // associative.  (It is always safe to leave it false, you will
+    // just end up with extra parens where you don't need them, which
+    // will impact compression but not correctness.)
     public String maybeAddParens(int parentPrec, SimpleNode node, String 
nodeRep, boolean assoc) {
       int thisPrec = Integer.MAX_VALUE;
       if (node instanceof ASTBinaryExpressionSequence ||
@@ -1264,14 +1269,31 @@
         thisPrec = prec(Ops.COLON, false);
       } else if (node instanceof ASTNewExpression) {
         thisPrec = prec(Ops.NEW, true);
-      } else if (node instanceof ASTCallExpression ||
-                 node instanceof ASTPropertyValueReference ||
-                 node instanceof ASTPropertyIdentifierReference) {
-        // These have prec of 0 even though they don't have ops
-        thisPrec = 0;
+      } else if (node instanceof ASTCallExpression) {
+        thisPrec = prec(Ops.LPAREN, true);
+      } else if (node instanceof ASTPropertyValueReference) {
+        thisPrec = prec(Ops.DOT, true);
+      } else if (node instanceof ASTPropertyIdentifierReference) {
+        thisPrec = prec(Ops.LBRACKET, true);
       } else if (node instanceof ASTExpressionList) {
         thisPrec = prec(Ops.COMMA, false);
+      } else if (// Our compiler is broken -- if one of these shows up
+                 // in an expression, it had to have been in an
+                 // expression list initially
+                 node instanceof ASTFunctionExpression ||
+                 node instanceof ASTFunctionDeclaration) {
+        thisPrec = prec(Ops.ASSIGN, false);
+      } else if (node instanceof ASTObjectLiteral ||
+                 node instanceof ASTArrayLiteral ||
+                 node instanceof ASTIdentifier ||
+                 node instanceof ASTThisReference ||
+                 node instanceof ASTLiteral) {
+        ;
+      } else {
+        System.err.println("No prec for " + node + " in " + nodeString(node));
+        (new CompilerException()).printStackTrace();
       }
+      
       if (assoc ? (thisPrec < parentPrec) : (thisPrec <= parentPrec)) {
         nodeRep = "(" + nodeRep + ")";
       }
@@ -1383,15 +1405,19 @@
     public String visitObjectLiteral(SimpleNode node, String[] children) {
       StringBuffer s = new StringBuffer("{");
       int len = children.length - 1;
+      int thisPrec = prec(Ops.COMMA, false);
       for (int i = 0; i < len; i++) {
-        s.append(children[i]);
         if (i % 2 != 0) {
+          children[i] = maybeAddParens(thisPrec, node.get(i), children[i], 
false);
+          s.append(children[i]);
           s.append(COMMA);
         } else {
+          s.append(children[i]);
           s.append(COLON);
         }
       }
       if (len > 0) {
+        children[len] = maybeAddParens(thisPrec, node.get(len), children[len], 
false);
         s.append(children[len]);
       }
       s.append("}");
@@ -1405,6 +1431,9 @@
 
     public String visitVariableDeclaration(SimpleNode node, String[] children) 
{
       if (children.length > 1) {
+        int thisPrec = prec(Ops.ASSIGN, false);
+        assert children.length == 2;
+        children[1] = maybeAddParens(thisPrec, node.get(1), children[1], true);
         return "var " + children[0] + ASSIGN + children[1];
       } else {
         return "var " + children[0];

Modified: 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
===================================================================
--- 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
    2007-09-05 05:18:10 UTC (rev 6360)
+++ 
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
    2007-09-05 12:53:39 UTC (rev 6361)
@@ -670,6 +670,7 @@
           assert c.length == 3;
           p.add(c[0]);
           SimpleNode funexpr = new ASTFunctionExpression(0);
+          funexpr.setBeginLocation(n.filename, n.beginLine, n.beginColumn);
           funexpr.setChildren(c);
           p.add(funexpr);
         } else if (n instanceof ASTVariableStatement) {
@@ -1517,6 +1518,14 @@
 //     if (options.getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
 //       return makeCheckedNode(node);
 //     }
+    // Note current call-site in a function context and backtracing
+    if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 
0)) &&
+        (context.findFunctionContext() != null)) {
+      SimpleNode newNode = new ASTExpressionList(0);
+      newNode.set(0, (new Compiler.Parser()).parse("$lzsc$a.lineno = " + 
node.beginLine).get(0).get(0));
+      newNode.set(1, new Compiler.PassThroughNode(node));
+      return visitExpression(newNode);
+    }
     return node;
   }
 
@@ -1679,6 +1688,7 @@
     return node;
   }
 
+  // useName => declaration not expression
   SimpleNode translateFunction(SimpleNode node, boolean useName, SimpleNode[] 
children) {
     // TODO: [2003-04-15 ptw] bind context slot macro
     SimpleNode[] result;
@@ -1720,6 +1730,7 @@
   static java.util.regex.Pattern identifierPattern = 
java.util.regex.Pattern.compile("[\\w$_]+");
 
   // Internal helper function for above
+  // useName => declaration not expression
   SimpleNode[] translateFunctionInternal(SimpleNode node, boolean useName, 
SimpleNode[] children) {
     // ast can be any of:
     //   FunctionDefinition(name, args, body)
@@ -2007,6 +2018,7 @@
       if (scriptElement || used.containsKey(name)) {
         SimpleNode fundecl = (SimpleNode)fundefs.get(name);
         SimpleNode funexpr = new ASTFunctionExpression(0);
+        funexpr.setBeginLocation(fundecl.filename, fundecl.beginLine, 
fundecl.beginColumn);
         funexpr.setChildren(fundecl.getChildren());
         Map map = new HashMap();
         map.put("_1", funexpr);
@@ -2048,13 +2060,34 @@
     // Finally replace the function body with that whole enchilada
     children[stmtsIndex] = newStmts;
     if ( options.getBoolean(Compiler.NAME_FUNCTIONS)) {
-      if (functionName != null) {
-        // the name will be available from the runtime
+      // TODO: [2007-09-04 ptw] Come up with a better way to
+      // distinguish LFC from user stack frames.  See
+      // lfc/debugger/LzBactrace
+      String fn = (options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) ? 
"lfc/" : "") + filename;
+      if (functionName != null &&
+          // Either it is a declaration or we are not doing
+          // backtraces, so the name will be available from the
+          // runtime
+          (useName || (! (options.getBoolean(Compiler.DEBUG_BACKTRACE))))) {
+        if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
+          SimpleNode newNode = new ASTStatementList(0);
+          newNode.set(0, new Compiler.PassThroughNode(node));
+          newNode.set(1, parseFragment(functionName + "._dbg_filename = " + 
ScriptCompiler.quote(fn)));
+          newNode.set(2, parseFragment(functionName + "._dbg_lineno = " + 
lineno));
+          node = visitStatement(newNode);
+        }
       } else {
         Map map = new HashMap();
         map.put("_1", node);
         SimpleNode newNode = new Compiler.PassThroughNode((new 
Compiler.Parser()).substitute(
-          "(function () {var $lzsc$temp = _1; $lzsc$temp._dbg_name = " + 
ScriptCompiler.quote(userFunctionName) + "; return $lzsc$temp})()",
+          "(function () {" +
+          "   var $lzsc$temp = _1;" +
+          "   $lzsc$temp._dbg_name = " + 
ScriptCompiler.quote(userFunctionName) + ";" +
+          ((options.getBoolean(Compiler.DEBUG_BACKTRACE)) ?
+           ("   $lzsc$temp._dbg_filename = " + ScriptCompiler.quote(fn) + ";" +
+            "   $lzsc$temp._dbg_lineno = " + lineno + ";") : 
+           "") +
+          "   return $lzsc$temp})()",
           map));
         node = newNode;
       }


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to