From fc6f357a0e5199615963cc53e07f6b2e423b3824 Mon Sep 17 00:00:00 2001 From: mfranz Date: Tue, 16 Oct 2007 15:24:30 +0000 Subject: [PATCH] add new debugging function proptrace(), which outputs all regular property writes (not directly written tied ones), all node additions and removal. Frames are separated with a line. Turn off ANSI coloring if you want to pipe the results into a file: --prop:sim/startup/terminal-ansi-colors=0 --- Nasal/debug.nas | 46 ++++++++++++++++++++++++++++++++++++++++++++-- Nasal/globals.nas | 11 +++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Nasal/debug.nas b/Nasal/debug.nas index f5f290867..18da3e90f 100644 --- a/Nasal/debug.nas +++ b/Nasal/debug.nas @@ -12,6 +12,10 @@ # debug.backtrace([]} ... writes backtrace with local variables # (similar to gdb's "bt full) # +# debug.proptrace([]]) ... trace property write/add/remove +# events under the subtree. +# Defaults are "/" and 1 second. +# # debug.tree([ [, ]) ... dump property tree under property path # or props.Node hash (default: root). If # is unset or 0, use flat mode @@ -35,6 +39,7 @@ # # debug.printerror() ... prints error vector as set by call() # +# debug.propify() ... turn about everything into a props.Node # # CAVE: this file makes extensive use of ANSI color codes. These are # interpreted by UNIX shells and MS Windows with ANSI.SYS extension @@ -74,8 +79,23 @@ var _varname = func(s) { _c("1", s) } # variable_name var ghosttypes = {}; -var tree = func(p = "", graph = 1) { - var n = isa(p, props.Node) ? p : props.globals.getNode(p, 0); +## +# Turn p into props.Node (if it isn't yet), or return nil. +# +var propify = func(p, create = 0) { + var type = typeof(p); + if (type == "ghost" and ghosttype(p) == ghosttype(props.globals._g)) + return props.wrapNode(p); + if (type == "scalar" and num(p) == nil) + return props.globals.getNode(p, create); + if (isa(p, props.Node)) + return p; + return nil; +} + + +var tree = func(n = "", graph = 1) { + n = propify(n); if (n == nil) dump(n); else @@ -203,6 +223,28 @@ var backtrace = func(desc = nil) { var bt = backtrace; +var proptrace = func(root = "/", time = 1) { + var i = 0; + var mark = setlistener("/sim/signals/frame", func { + print("-------------------- FRAME --------------------"); + }); + var trace = setlistener(propify(root), func(this, base, type) { + i += 1; + if (type > 0) + print("ADD ", this.getPath()); + elsif (type < 0) + print("DEL ", this.getPath()); + else + print("SET ", this.getPath(), " = ", string(this.getValue()), " ", _attrib(this)); + }, 0, 2); + settimer(func { + removelistener(trace); + removelistener(mark); + print("proptrace: stop (", i, " calls)"); + }, time, 1); +} + + ## # Executes function f with optional arguments and prints execution # time in seconds. Examples: diff --git a/Nasal/globals.nas b/Nasal/globals.nas index 5573ab6d0..0ed8ef4d1 100644 --- a/Nasal/globals.nas +++ b/Nasal/globals.nas @@ -63,10 +63,13 @@ var interpolate = func(node, val...) { ## -# Convenience wrapper for the _setlistener function. Takes a -# single string or props.Node object in arg[0] indicating the -# listened to property, a function in arg[1], and an optional -# bool in arg[2], which triggers the function initially if true. +# Wrapper for the _setlistener function. Takes a property path string +# or props.Node object in arg[0] indicating the listened to property, +# a function in arg[1], an optional bool in arg[2], which triggers the +# function initially if true, and an optional integer in arg[3], which +# sets the listener's runtime behavior to "only trigger on change" (0), +# "always trigger on write" (2), and "trigger even when children are +# written to" (2). # var setlistener = func(node, fun, init=0, runtime=1) { if(isa(node, props.Node)) node = node._g;